mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge branch 'master' into master-14217
# Conflicts: # tests/baselines/reference/bestChoiceType.symbols # tests/baselines/reference/classExpressionWithStaticProperties3.symbols # tests/baselines/reference/classExpressionWithStaticPropertiesES63.symbols # tests/baselines/reference/declarationEmitPromise.symbols # tests/baselines/reference/keyofAndIndexedAccess.symbols # tests/baselines/reference/mapOnTupleTypes01.symbols # tests/baselines/reference/mapOnTupleTypes02.symbols # tests/baselines/reference/mappedTypeRelationships.errors.txt # tests/baselines/reference/noImplicitAnyInContextuallyTypesFunctionParamter.symbols # tests/baselines/reference/specializationsShouldNotAffectEachOther.symbols # tests/baselines/reference/tsxSpreadChildren.symbols # tests/baselines/reference/typedArrays.symbols
This commit is contained in:
+13
-36
@@ -2,6 +2,7 @@
|
||||
import * as cp from "child_process";
|
||||
import * as path from "path";
|
||||
import * as fs from "fs";
|
||||
import child_process = require("child_process");
|
||||
import originalGulp = require("gulp");
|
||||
import helpMaker = require("gulp-help");
|
||||
import runSequence = require("run-sequence");
|
||||
@@ -416,7 +417,7 @@ gulp.task(servicesFile, false, ["lib", "generate-diagnostics"], () => {
|
||||
file.path = nodeDefinitionsFile;
|
||||
return content + "\r\nexport = ts;";
|
||||
}))
|
||||
.pipe(gulp.dest(".")),
|
||||
.pipe(gulp.dest("src/services")),
|
||||
completedDts.pipe(clone())
|
||||
.pipe(insert.transform((content, file) => {
|
||||
file.path = nodeStandaloneDefinitionsFile;
|
||||
@@ -477,12 +478,12 @@ gulp.task(tsserverLibraryFile, false, [servicesFile], (done) => {
|
||||
return merge2([
|
||||
js.pipe(prependCopyright())
|
||||
.pipe(sourcemaps.write("."))
|
||||
.pipe(gulp.dest(".")),
|
||||
.pipe(gulp.dest("src/server")),
|
||||
dts.pipe(prependCopyright(/*outputCopyright*/true))
|
||||
.pipe(insert.transform((content) => {
|
||||
return content + "\r\nexport = ts;\r\nexport as namespace ts;";
|
||||
}))
|
||||
.pipe(gulp.dest("."))
|
||||
.pipe(gulp.dest("src/server"))
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -749,7 +750,7 @@ gulp.task("browserify", "Runs browserify on run.js to produce a file suitable fo
|
||||
const originalMap = file.sourceMap;
|
||||
const 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(s));
|
||||
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
|
||||
originalMap.file = "built/local/_stream_0.js";
|
||||
|
||||
@@ -960,7 +961,7 @@ gulp.task("update-sublime", "Updates the sublime plugin's tsserver", ["local", s
|
||||
});
|
||||
|
||||
gulp.task("build-rules", "Compiles tslint rules to js", () => {
|
||||
const settings: tsc.Settings = getCompilerSettings({ module: "commonjs" }, /*useBuiltCompiler*/ false);
|
||||
const settings: tsc.Settings = getCompilerSettings({ module: "commonjs", "lib": ["es6"] }, /*useBuiltCompiler*/ false);
|
||||
const dest = path.join(builtLocalDirectory, "tslint");
|
||||
return gulp.src("scripts/tslint/**/*.ts")
|
||||
.pipe(newer({
|
||||
@@ -1019,40 +1020,16 @@ function spawnLintWorker(files: {path: string}[], callback: (failures: number) =
|
||||
}
|
||||
|
||||
gulp.task("lint", "Runs tslint on the compiler sources. Optional arguments are: --f[iles]=regex", ["build-rules"], () => {
|
||||
const fileMatcher = RegExp(cmdLineOptions["files"]);
|
||||
if (fold.isTravis()) console.log(fold.start("lint"));
|
||||
|
||||
let files: {stat: fs.Stats, path: string}[] = [];
|
||||
return gulp.src(lintTargets, { read: false })
|
||||
.pipe(through2.obj((chunk, enc, cb) => {
|
||||
files.push(chunk);
|
||||
cb();
|
||||
}, (cb) => {
|
||||
files = files.filter(file => fileMatcher.test(file.path)).sort((filea, fileb) => filea.stat.size - fileb.stat.size);
|
||||
const workerCount = cmdLineOptions["workers"];
|
||||
for (let i = 0; i < workerCount; i++) {
|
||||
spawnLintWorker(files, finished);
|
||||
}
|
||||
|
||||
let completed = 0;
|
||||
let failures = 0;
|
||||
function finished(fails) {
|
||||
completed++;
|
||||
failures += fails;
|
||||
if (completed === workerCount) {
|
||||
if (fold.isTravis()) console.log(fold.end("lint"));
|
||||
if (failures > 0) {
|
||||
throw new Error(`Linter errors: ${failures}`);
|
||||
}
|
||||
else {
|
||||
cb();
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
const fileMatcher = cmdLineOptions["files"];
|
||||
const files = fileMatcher
|
||||
? `src/**/${fileMatcher}`
|
||||
: "Gulpfile.ts 'src/**/*.ts' --exclude src/lib/es5.d.ts --exclude 'src/lib/*.generated.d.ts' --exclude 'src/harness/unittests/services/**/*.ts'";
|
||||
const cmd = `node node_modules/tslint/bin/tslint ${files} --format stylish`;
|
||||
console.log("Linting: " + cmd);
|
||||
child_process.execSync(cmd, { stdio: [0, 1, 2] });
|
||||
});
|
||||
|
||||
|
||||
gulp.task("default", "Runs 'local'", ["local"]);
|
||||
|
||||
gulp.task("watch", "Watches the src/ directory for changes and executes runtests-parallel.", [], () => {
|
||||
|
||||
+21
-50
@@ -11,11 +11,7 @@ var ts = require("./lib/typescript");
|
||||
|
||||
// Variables
|
||||
var compilerDirectory = "src/compiler/";
|
||||
var servicesDirectory = "src/services/";
|
||||
var serverDirectory = "src/server/";
|
||||
var typingsInstallerDirectory = "src/server/typingsInstaller";
|
||||
var cancellationTokenDirectory = "src/server/cancellationToken";
|
||||
var watchGuardDirectory = "src/server/watchGuard";
|
||||
var harnessDirectory = "src/harness/";
|
||||
var libraryDirectory = "src/lib/";
|
||||
var scriptsDirectory = "scripts/";
|
||||
@@ -131,6 +127,7 @@ var harnessSources = harnessCoreSources.concat([
|
||||
"matchFiles.ts",
|
||||
"initializeTSConfig.ts",
|
||||
"printer.ts",
|
||||
"textChanges.ts",
|
||||
"transform.ts",
|
||||
"customTransforms.ts",
|
||||
].map(function (f) {
|
||||
@@ -333,7 +330,7 @@ function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, opts
|
||||
options += " --lib " + opts.lib
|
||||
}
|
||||
else {
|
||||
options += " --lib es5,scripthost"
|
||||
options += " --lib es5"
|
||||
}
|
||||
options += " --noUnusedLocals --noUnusedParameters";
|
||||
|
||||
@@ -422,7 +419,7 @@ compileFile(buildProtocolJs,
|
||||
[buildProtocolTs],
|
||||
[],
|
||||
/*useBuiltCompiler*/ false,
|
||||
{noOutFile: true});
|
||||
{ noOutFile: true, lib: "es6" });
|
||||
|
||||
file(buildProtocolDts, [buildProtocolTs, buildProtocolJs, typescriptServicesDts], function() {
|
||||
|
||||
@@ -584,16 +581,16 @@ compileFile(
|
||||
file(typescriptServicesDts, [servicesFile]);
|
||||
|
||||
var cancellationTokenFile = path.join(builtLocalDirectory, "cancellationToken.js");
|
||||
compileFile(cancellationTokenFile, cancellationTokenSources, [builtLocalDirectory].concat(cancellationTokenSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { outDir: builtLocalDirectory, noOutFile: true });
|
||||
compileFile(cancellationTokenFile, cancellationTokenSources, [builtLocalDirectory].concat(cancellationTokenSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { types: ["node"], outDir: builtLocalDirectory, noOutFile: true, lib: "es6" });
|
||||
|
||||
var typingsInstallerFile = path.join(builtLocalDirectory, "typingsInstaller.js");
|
||||
compileFile(typingsInstallerFile, typingsInstallerSources, [builtLocalDirectory].concat(typingsInstallerSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { outDir: builtLocalDirectory, noOutFile: false });
|
||||
compileFile(typingsInstallerFile, typingsInstallerSources, [builtLocalDirectory].concat(typingsInstallerSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { types: ["node"], outDir: builtLocalDirectory, noOutFile: false, lib: "es6" });
|
||||
|
||||
var watchGuardFile = path.join(builtLocalDirectory, "watchGuard.js");
|
||||
compileFile(watchGuardFile, watchGuardSources, [builtLocalDirectory].concat(watchGuardSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { outDir: builtLocalDirectory, noOutFile: false });
|
||||
compileFile(watchGuardFile, watchGuardSources, [builtLocalDirectory].concat(watchGuardSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { types: ["node"], outDir: builtLocalDirectory, noOutFile: false, lib: "es6" });
|
||||
|
||||
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 });
|
||||
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");
|
||||
compileFile(
|
||||
@@ -717,7 +714,7 @@ compileFile(
|
||||
/*prereqs*/[builtLocalDirectory, tscFile].concat(libraryTargets).concat(servicesSources).concat(harnessSources),
|
||||
/*prefixes*/[],
|
||||
/*useBuiltCompiler:*/ true,
|
||||
/*opts*/ { inlineSourceMap: true, types: ["node", "mocha", "chai"] });
|
||||
/*opts*/ { inlineSourceMap: true, types: ["node", "mocha", "chai"], lib: "es6" });
|
||||
|
||||
var internalTests = "internal/";
|
||||
|
||||
@@ -1104,7 +1101,8 @@ var tslintRules = [
|
||||
"noInOperatorRule",
|
||||
"noIncrementDecrementRule",
|
||||
"objectLiteralSurroundingSpaceRule",
|
||||
"noTypeAssertionWhitespaceRule"
|
||||
"noTypeAssertionWhitespaceRule",
|
||||
"noBomRule"
|
||||
];
|
||||
var tslintRulesFiles = tslintRules.map(function (p) {
|
||||
return path.join(tslintRuleDir, p + ".ts");
|
||||
@@ -1179,43 +1177,16 @@ function spawnLintWorker(files, callback) {
|
||||
}
|
||||
|
||||
desc("Runs tslint on the compiler sources. Optional arguments are: f[iles]=regex");
|
||||
task("lint", ["build-rules"], function () {
|
||||
task("lint", ["build-rules"], () => {
|
||||
if (fold.isTravis()) console.log(fold.start("lint"));
|
||||
var startTime = mark();
|
||||
var failed = 0;
|
||||
var fileMatcher = RegExp(process.env.f || process.env.file || process.env.files || "");
|
||||
var done = {};
|
||||
for (var i in lintTargets) {
|
||||
var target = lintTargets[i];
|
||||
if (!done[target] && fileMatcher.test(target)) {
|
||||
done[target] = fs.statSync(target).size;
|
||||
}
|
||||
}
|
||||
|
||||
var workerCount = (process.env.workerCount && +process.env.workerCount) || os.cpus().length;
|
||||
|
||||
var names = Object.keys(done).sort(function (namea, nameb) {
|
||||
return done[namea] - done[nameb];
|
||||
const fileMatcher = process.env.f || process.env.file || process.env.files;
|
||||
const files = fileMatcher
|
||||
? `src/**/${fileMatcher}`
|
||||
: "Gulpfile.ts 'src/**/*.ts' --exclude src/lib/es5.d.ts --exclude 'src/lib/*.generated.d.ts' --exclude 'src/harness/unittests/services/**/*.ts'";
|
||||
const cmd = `node node_modules/tslint/bin/tslint ${files} --format stylish`;
|
||||
console.log("Linting: " + cmd);
|
||||
jake.exec([cmd], { interactive: true }, () => {
|
||||
if (fold.isTravis()) console.log(fold.end("lint"));
|
||||
complete();
|
||||
});
|
||||
|
||||
for (var i = 0; i < workerCount; i++) {
|
||||
spawnLintWorker(names, finished);
|
||||
}
|
||||
|
||||
var completed = 0;
|
||||
var failures = 0;
|
||||
function finished(fails) {
|
||||
completed++;
|
||||
failures += fails;
|
||||
if (completed === workerCount) {
|
||||
measure(startTime);
|
||||
if (fold.isTravis()) console.log(fold.end("lint"));
|
||||
if (failures > 0) {
|
||||
fail('Linter errors.', failed);
|
||||
}
|
||||
else {
|
||||
complete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}, { async: true });
|
||||
});
|
||||
|
||||
@@ -39,8 +39,8 @@ with any additional questions or comments.
|
||||
|
||||
## Documentation
|
||||
|
||||
* [Quick tutorial](http://www.typescriptlang.org/Tutorial)
|
||||
* [Programming handbook](http://www.typescriptlang.org/Handbook)
|
||||
* [Quick tutorial](http://www.typescriptlang.org/docs/tutorial.html)
|
||||
* [Programming handbook](http://www.typescriptlang.org/docs/handbook/basic-types.html)
|
||||
* [Language specification](https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md)
|
||||
* [Homepage](http://www.typescriptlang.org/)
|
||||
|
||||
@@ -95,4 +95,4 @@ node built/local/tsc.js hello.ts
|
||||
|
||||
## Roadmap
|
||||
|
||||
For details on our planned features and future direction please refer to our [roadmap](https://github.com/Microsoft/TypeScript/wiki/Roadmap).
|
||||
For details on our planned features and future direction please refer to our [roadmap](https://github.com/Microsoft/TypeScript/wiki/Roadmap).
|
||||
|
||||
+10
-15
@@ -1,15 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg version="1.1" id="logo-typescript" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 283.09 69.57">
|
||||
<g fill="#007ACC">
|
||||
<path d="M34.98 7.56H20.43v45.07h-5.91V7.56H0V2.21h34.98V7.56z"/>
|
||||
<path d="M57.94 16.63L41.38 58.39c-2.95 7.45-7.1 11.18-12.45 11.18 -1.5 0-2.75-0.15-3.76-0.46v-5.17c1.24 0.42 2.38 0.63 3.41 0.63 2.91 0 5.09-1.73 6.54-5.2l2.88-6.82L23.94 16.63h6.4l9.74 27.7c0.12 0.35 0.36 1.27 0.74 2.74h0.21c0.12-0.56 0.35-1.45 0.7-2.67l10.23-27.77H57.94z"/>
|
||||
<path d="M67.37 47.43h-0.14v21.76h-5.77V16.63h5.77v6.33h0.14c2.84-4.78 6.98-7.17 12.45-7.17 4.64 0 8.26 1.61 10.86 4.83 2.6 3.22 3.9 7.54 3.9 12.96 0 6.02-1.46 10.85-4.39 14.47 -2.93 3.62-6.94 5.43-12.02 5.43C73.5 53.47 69.9 51.46 67.37 47.43zM67.23 32.91v5.03c0 2.98 0.97 5.5 2.9 7.58s4.39 3.11 7.37 3.11c3.49 0 6.23-1.34 8.21-4.01 1.98-2.67 2.97-6.39 2.97-11.14 0-4.01-0.93-7.15-2.78-9.42 -1.85-2.27-4.36-3.41-7.52-3.41 -3.35 0-6.05 1.17-8.09 3.5C68.25 26.47 67.23 29.39 67.23 32.91z"/>
|
||||
<path d="M129.56 36.07h-25.42c0.09 4.01 1.17 7.1 3.23 9.28 2.06 2.18 4.9 3.27 8.51 3.27 4.05 0 7.78-1.34 11.18-4.01v5.41c-3.16 2.3-7.35 3.45-12.55 3.45 -5.09 0-9.08-1.63-11.99-4.9 -2.91-3.27-4.36-7.87-4.36-13.8 0-5.6 1.59-10.17 4.76-13.69 3.18-3.53 7.12-5.29 11.83-5.29s8.35 1.52 10.93 4.57c2.58 3.05 3.87 7.28 3.87 12.69V36.07zM123.65 31.18c-0.02-3.33-0.83-5.92-2.41-7.77 -1.58-1.85-3.78-2.78-6.59-2.78 -2.72 0-5.03 0.97-6.93 2.92 -1.9 1.95-3.07 4.49-3.52 7.63H123.65z"/>
|
||||
<path d="M134.6 50.59v-6.96c0.73 0.7 1.6 1.34 2.62 1.9 1.02 0.56 2.09 1.04 3.22 1.42s2.26 0.69 3.39 0.9c1.14 0.21 2.19 0.32 3.15 0.32 3.32 0 5.81-0.67 7.45-2.02 1.64-1.35 2.46-3.29 2.46-5.82 0-1.36-0.27-2.54-0.82-3.55 -0.55-1.01-1.3-1.93-2.27-2.76s-2.11-1.63-3.43-2.39c-1.32-0.76-2.74-1.56-4.26-2.41 -1.61-0.89-3.11-1.79-4.5-2.71 -1.39-0.91-2.61-1.92-3.63-3.02 -1.03-1.1-1.84-2.35-2.43-3.74 -0.59-1.39-0.88-3.03-0.88-4.9 0-2.3 0.46-4.29 1.38-5.99 0.92-1.7 2.13-3.1 3.64-4.2 1.5-1.1 3.21-1.92 5.13-2.46 1.92-0.54 3.88-0.81 5.87-0.81 4.55 0 7.86 0.6 9.94 1.79v6.64c-2.72-2.06-6.22-3.09-10.49-3.09 -1.18 0-2.36 0.14-3.54 0.4 -1.18 0.27-2.23 0.71-3.15 1.32 -0.92 0.61-1.67 1.39-2.25 2.36 -0.58 0.96-0.87 2.13-0.87 3.52 0 1.29 0.22 2.4 0.66 3.34 0.44 0.94 1.09 1.79 1.95 2.57 0.86 0.77 1.9 1.52 3.14 2.25 1.23 0.73 2.65 1.52 4.26 2.39 1.65 0.89 3.22 1.83 4.7 2.81s2.78 2.07 3.89 3.27c1.11 1.2 2 2.52 2.65 3.97 0.65 1.45 0.98 3.12 0.98 4.99 0 2.48-0.45 4.59-1.33 6.31 -0.89 1.72-2.09 3.12-3.6 4.2 -1.51 1.08-3.25 1.86-5.23 2.34 -1.97 0.48-4.05 0.72-6.24 0.72 -0.73 0-1.63-0.06-2.7-0.19s-2.17-0.32-3.28-0.56c-1.12-0.25-2.17-0.55-3.17-0.91C136 51.44 135.21 51.03 134.6 50.59z"/>
|
||||
<path d="M193.25 50.98c-2.77 1.66-6.05 2.5-9.84 2.5 -5.13 0-9.28-1.67-12.43-5.01s-4.73-7.67-4.73-12.99c0-5.93 1.7-10.69 5.1-14.29 3.4-3.6 7.93-5.4 13.61-5.4 3.16 0 5.95 0.59 8.37 1.76v5.91c-2.67-1.88-5.53-2.81-8.58-2.81 -3.68 0-6.7 1.32-9.05 3.96s-3.53 6.1-3.53 10.39c0 4.22 1.11 7.55 3.32 9.98s5.19 3.66 8.91 3.66c3.14 0 6.09-1.04 8.86-3.13V50.98z"/>
|
||||
<path d="M215.56 22.46c-1.01-0.77-2.46-1.16-4.36-1.16 -2.46 0-4.52 1.16-6.17 3.48s-2.48 5.48-2.48 9.49v18.35h-5.77v-36h5.77v7.42h0.14c0.82-2.53 2.07-4.51 3.76-5.92 1.69-1.42 3.57-2.13 5.66-2.13 1.5 0 2.65 0.16 3.45 0.49V22.46z"/>
|
||||
<path d="M222.18 7.49c-1.03 0-1.91-0.35-2.64-1.05s-1.09-1.59-1.09-2.67c0-1.08 0.36-1.97 1.09-2.69 0.73-0.71 1.61-1.07 2.64-1.07 1.05 0 1.95 0.36 2.69 1.07 0.74 0.72 1.11 1.61 1.11 2.69 0 1.03-0.37 1.91-1.11 2.64C224.13 7.12 223.23 7.49 222.18 7.49zM224.99 52.63h-5.77v-36h5.77V52.63z"/>
|
||||
<path d="M234.29 47.43h-0.14v21.76h-5.77V16.63h5.77v6.33h0.14c2.84-4.78 6.98-7.17 12.45-7.17 4.64 0 8.26 1.61 10.86 4.83 2.6 3.22 3.9 7.54 3.9 12.96 0 6.02-1.46 10.85-4.39 14.47s-6.94 5.43-12.02 5.43C240.42 53.47 236.82 51.46 234.29 47.43zM234.15 32.91v5.03c0 2.98 0.97 5.5 2.9 7.58s4.39 3.11 7.37 3.11c3.49 0 6.23-1.34 8.21-4.01s2.97-6.39 2.97-11.14c0-4.01-0.93-7.15-2.78-9.42 -1.85-2.27-4.36-3.41-7.52-3.41 -3.35 0-6.05 1.17-8.09 3.5C235.17 26.47 234.15 29.39 234.15 32.91z"/>
|
||||
<path d="M283.09 52.28c-1.36 0.75-3.15 1.12-5.38 1.12 -6.3 0-9.46-3.52-9.46-10.55v-21.3h-6.19v-4.92h6.19V7.84l5.77-1.86v10.65h9.07v4.92h-9.07v20.28c0 2.41 0.41 4.14 1.23 5.17s2.18 1.55 4.08 1.55c1.45 0 2.71-0.4 3.76-1.2V52.28z"/>
|
||||
</g>
|
||||
</svg>
|
||||
<svg id="logo-typescript" xmlns="http://www.w3.org/2000/svg" viewBox="-64.9 417 216.5 51.9">
|
||||
<style>
|
||||
.st0 {
|
||||
fill: #000
|
||||
}
|
||||
</style>
|
||||
<path class="st0" d="M-38.2 421.7h-11.1V456h-4.5v-34.3h-11.1v-4.1h26.6v4.1h.1z" />
|
||||
<path class="st0" d="M-16.9 428.6l-12.6 31.8c-2.3 5.7-5.4 8.5-9.5 8.5-1.1 0-2.1-.1-2.9-.3v-3.9c.9.3 1.8.5 2.6.5 2.2 0 3.9-1.3 5-4l2.2-5.2-10.7-27.4h4.9l7.4 21.1c.1.3.3 1 .6 2.1h.2c.1-.4.3-1.1.5-2l7.8-21.2h4.5zM-9.5 452.1h-.1v16.6H-14v-40h4.4v4.8h.1c2.2-3.6 5.3-5.5 9.5-5.5 3.5 0 6.3 1.2 8.3 3.7s3 5.7 3 9.9c0 4.6-1.1 8.3-3.3 11s-5.3 4.1-9.2 4.1c-3.6 0-6.3-1.5-8.3-4.6zm-.1-11.1v3.8c0 2.3.7 4.2 2.2 5.8s3.3 2.4 5.6 2.4c2.7 0 4.7-1 6.3-3.1 1.6-2.1 2.3-4.9 2.3-8.5 0-3.1-.7-5.4-2.1-7.2-1.4-1.7-3.3-2.6-5.7-2.6-2.6 0-4.6.9-6.2 2.7-1.6 1.8-2.4 4-2.4 6.7zM38.4 443.4H19c.1 3.1.9 5.4 2.5 7.1s3.7 2.5 6.5 2.5c3.1 0 5.9-1 8.5-3.1v4.1c-2.4 1.8-5.6 2.6-9.6 2.6-3.9 0-6.9-1.2-9.1-3.7-2.2-2.5-3.3-6-3.3-10.5 0-4.3 1.2-7.7 3.6-10.4 2.4-2.7 5.4-4 9-4s6.4 1.2 8.3 3.5c2 2.3 2.9 5.5 2.9 9.7v2.2h.1zm-4.5-3.7c0-2.5-.6-4.5-1.8-5.9-1.2-1.4-2.9-2.1-5-2.1s-3.8.7-5.3 2.2c-1.4 1.5-2.3 3.4-2.7 5.8h14.8zM40.8 454.7v-3c2.8 1.8 5.5 2.6 8.4 2.6 3 0 5.3-.6 6.8-1.9 1.6-1.2 2.3-3 2.3-5.2 0-2-.5-3.5-1.6-4.7-1-1.2-3.3-2.8-6.8-4.8-3.9-2.3-6.4-4.2-7.4-5.7s-1.6-3.3-1.6-5.3c0-2.7 1.1-5 3.2-6.9 2.1-1.9 4.9-2.8 8.4-2.8 2.3 0 4.6.4 6.9 1.2v2.8c-2.3-1-4.7-1.5-7.2-1.5-2.6 0-4.7.7-6.2 2s-2.3 3-2.3 5 .5 3.5 1.6 4.7c1 1.2 3.3 2.7 6.8 4.7 3.6 2 6 3.8 7.2 5.4 1.2 1.6 1.8 3.4 1.8 5.5 0 2.9-1 5.3-3.1 7.2-2 1.9-4.9 2.8-8.7 2.8-1.3 0-2.8-.2-4.6-.6-1.6-.5-2.9-1-3.9-1.5zM84.3 454.8c-2 1.2-4.5 1.9-7.3 1.9-3.7 0-6.7-1.3-9-3.8-2.3-2.6-3.4-5.9-3.4-10.1 0-4.4 1.3-7.9 3.9-10.7 2.6-2.8 5.9-4.2 9.9-4.2 2.1 0 4.1.4 6.1 1.3v2.8c-2-1.2-4.1-1.8-6.5-1.8-3.2 0-5.8 1.2-7.8 3.5s-3 5.3-3 9c0 3.6.9 6.4 2.7 8.6 1.8 2.2 4.2 3.2 7.2 3.2 2.7 0 5.1-.7 7.2-2.2v2.5zM100.9 431.2c-.8-.6-1.8-.9-2.9-.9-2.2 0-4 1.1-5.4 3.3-1.5 2.2-2.2 5.4-2.2 9.5V456H88v-27.4h2.4v6.1h.1c.6-2.1 1.6-3.7 3-4.9 1.4-1.2 2.9-1.7 4.7-1.7 1 0 1.9.2 2.7.5v2.6zM105.1 421.7c-.5 0-1-.2-1.4-.6s-.6-.9-.6-1.5.2-1.1.6-1.4c.4-.4.9-.5 1.4-.5.6 0 1 .2 1.5.5.4.4.6.8.6 1.4s-.2 1.1-.6 1.5c-.5.4-.9.6-1.5.6zm-1.2 34.4v-27.4h2.5v27.4h-2.5zM115 451.2h-.1v17.5h-2.5v-40h2.5v5.7h.1c1-2 2.4-3.6 4.2-4.7 1.8-1.1 3.8-1.6 6-1.6 3.5 0 6.2 1.2 8.2 3.6 2 2.4 2.9 5.7 2.9 9.8 0 4.6-1.1 8.3-3.4 11.1-2.2 2.8-5.2 4.2-8.9 4.2-4-.1-7-1.9-9-5.6zm-.1-10.2v3.5c0 2.8.9 5.1 2.6 7.1s4 3 6.8 3 5.1-1.2 6.8-3.6c1.7-2.4 2.6-5.6 2.6-9.5 0-3.4-.8-6.2-2.4-8.2s-3.8-3-6.4-3c-3.2 0-5.7 1.1-7.4 3.2-1.7 2.1-2.6 4.6-2.6 7.5zM151.6 455.7c-1.3.6-2.5.9-3.6.9-4.1 0-6.1-2.4-6.1-7.3v-18.4H137v-2.3h4.9v-7.1c.4-.1.8-.3 1.2-.4.4-.1.8-.3 1.2-.4v8h7.2v2.3h-7.2v18.1c0 1.9.3 3.3.9 4.1.6.8 1.6 1.3 3 1.3 1 0 2.1-.3 3.3-1v2.2h.1z"
|
||||
/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 2.7 KiB |
+1
-1
@@ -2,7 +2,7 @@
|
||||
<!-- QUESTIONS: This is not a general support forum! Ask Qs at http://stackoverflow.com/questions/tagged/typescript -->
|
||||
<!-- SUGGESTIONS: See https://github.com/Microsoft/TypeScript-wiki/blob/master/Writing-Good-Design-Proposals.md -->
|
||||
|
||||
**TypeScript Version:** 2.1.1 / nightly (2.2.0-dev.201xxxxx)
|
||||
**TypeScript Version:** 2.2.1 / nightly (2.2.0-dev.201xxxxx)
|
||||
|
||||
**Code**
|
||||
|
||||
|
||||
@@ -2,52 +2,62 @@ import * as Lint from "tslint/lib";
|
||||
import * as ts from "typescript";
|
||||
|
||||
export class Rule extends Lint.Rules.AbstractRule {
|
||||
public static FAILURE_STRING_FACTORY = (name: string, currently: string) => `Tag boolean argument as '${name}' (currently '${currently}')`;
|
||||
public static FAILURE_STRING_FACTORY(name: string, currently?: string): string {
|
||||
const current = currently ? ` (currently '${currently}')` : "";
|
||||
return `Tag boolean argument as '${name}'${current}`;
|
||||
}
|
||||
|
||||
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
||||
// Cheat to get type checker
|
||||
const program = ts.createProgram([sourceFile.fileName], Lint.createCompilerOptions());
|
||||
const checker = program.getTypeChecker();
|
||||
return this.applyWithWalker(new BooleanTriviaWalker(checker, program.getSourceFile(sourceFile.fileName), this.getOptions()));
|
||||
return this.applyWithFunction(program.getSourceFile(sourceFile.fileName), ctx => walk(ctx, checker));
|
||||
}
|
||||
}
|
||||
|
||||
class BooleanTriviaWalker extends Lint.RuleWalker {
|
||||
constructor(private checker: ts.TypeChecker, file: ts.SourceFile, opts: Lint.IOptions) {
|
||||
super(file, opts);
|
||||
function walk(ctx: Lint.WalkContext<void>, checker: ts.TypeChecker): void {
|
||||
ts.forEachChild(ctx.sourceFile, recur);
|
||||
function recur(node: ts.Node): void {
|
||||
if (node.kind === ts.SyntaxKind.CallExpression) {
|
||||
checkCall(node as ts.CallExpression);
|
||||
}
|
||||
ts.forEachChild(node, recur);
|
||||
}
|
||||
|
||||
visitCallExpression(node: ts.CallExpression) {
|
||||
super.visitCallExpression(node);
|
||||
if (node.arguments && node.arguments.some(arg => arg.kind === ts.SyntaxKind.TrueKeyword || arg.kind === ts.SyntaxKind.FalseKeyword)) {
|
||||
const targetCallSignature = this.checker.getResolvedSignature(node);
|
||||
if (!!targetCallSignature) {
|
||||
const targetParameters = targetCallSignature.getParameters();
|
||||
const source = this.getSourceFile();
|
||||
for (let index = 0; index < targetParameters.length; index++) {
|
||||
const param = targetParameters[index];
|
||||
const arg = node.arguments[index];
|
||||
if (!(arg && param)) {
|
||||
continue;
|
||||
}
|
||||
function checkCall(node: ts.CallExpression): void {
|
||||
if (!node.arguments || !node.arguments.some(arg => arg.kind === ts.SyntaxKind.TrueKeyword || arg.kind === ts.SyntaxKind.FalseKeyword)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const argType = this.checker.getContextualType(arg);
|
||||
if (argType && (argType.getFlags() & ts.TypeFlags.Boolean)) {
|
||||
if (arg.kind !== ts.SyntaxKind.TrueKeyword && arg.kind !== ts.SyntaxKind.FalseKeyword) {
|
||||
continue;
|
||||
}
|
||||
let triviaContent: string;
|
||||
const ranges = ts.getLeadingCommentRanges(arg.getFullText(), 0);
|
||||
if (ranges && ranges.length === 1 && ranges[0].kind === ts.SyntaxKind.MultiLineCommentTrivia) {
|
||||
triviaContent = arg.getFullText().slice(ranges[0].pos + 2, ranges[0].end - 2); // +/-2 to remove /**/
|
||||
}
|
||||
const targetCallSignature = checker.getResolvedSignature(node);
|
||||
if (!targetCallSignature) {
|
||||
return;
|
||||
}
|
||||
|
||||
const paramName = param.getName();
|
||||
if (triviaContent !== paramName && triviaContent !== paramName + ":") {
|
||||
this.addFailure(this.createFailure(arg.getStart(source), arg.getWidth(source), Rule.FAILURE_STRING_FACTORY(param.getName(), triviaContent)));
|
||||
}
|
||||
}
|
||||
const targetParameters = targetCallSignature.getParameters();
|
||||
for (let index = 0; index < targetParameters.length; index++) {
|
||||
const param = targetParameters[index];
|
||||
const arg = node.arguments[index];
|
||||
if (!(arg && param)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const argType = checker.getContextualType(arg);
|
||||
if (argType && (argType.getFlags() & ts.TypeFlags.Boolean)) {
|
||||
if (arg.kind !== ts.SyntaxKind.TrueKeyword && arg.kind !== ts.SyntaxKind.FalseKeyword) {
|
||||
continue;
|
||||
}
|
||||
let triviaContent: string | undefined;
|
||||
const ranges = ts.getLeadingCommentRanges(arg.getFullText(), 0);
|
||||
if (ranges && ranges.length === 1 && ranges[0].kind === ts.SyntaxKind.MultiLineCommentTrivia) {
|
||||
triviaContent = arg.getFullText().slice(ranges[0].pos + 2, ranges[0].end - 2); // +/-2 to remove /**/
|
||||
}
|
||||
|
||||
const paramName = param.getName();
|
||||
if (triviaContent !== paramName && triviaContent !== paramName + ":") {
|
||||
ctx.addFailureAtNode(arg, Rule.FAILURE_STRING_FACTORY(param.getName(), triviaContent));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,50 +9,56 @@ export class Rule extends Lint.Rules.AbstractRule {
|
||||
public static ELSE_FAILURE_STRING = "'else' should not be on the same line as the preceeding block's curly brace";
|
||||
|
||||
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
||||
return this.applyWithWalker(new NextLineWalker(sourceFile, this.getOptions()));
|
||||
const options = this.getOptions().ruleArguments;
|
||||
const checkCatch = options.indexOf(OPTION_CATCH) !== -1;
|
||||
const checkElse = options.indexOf(OPTION_ELSE) !== -1;
|
||||
return this.applyWithFunction(sourceFile, ctx => walk(ctx, checkCatch, checkElse));
|
||||
}
|
||||
}
|
||||
|
||||
class NextLineWalker extends Lint.RuleWalker {
|
||||
public visitIfStatement(node: ts.IfStatement) {
|
||||
const sourceFile = node.getSourceFile();
|
||||
const thenStatement = node.thenStatement;
|
||||
|
||||
const elseStatement = node.elseStatement;
|
||||
if (!!elseStatement) {
|
||||
// find the else keyword
|
||||
const elseKeyword = getFirstChildOfKind(node, ts.SyntaxKind.ElseKeyword);
|
||||
if (this.hasOption(OPTION_ELSE) && !!elseKeyword) {
|
||||
const thenStatementEndLoc = sourceFile.getLineAndCharacterOfPosition(thenStatement.getEnd());
|
||||
const elseKeywordLoc = sourceFile.getLineAndCharacterOfPosition(elseKeyword.getStart(sourceFile));
|
||||
if (thenStatementEndLoc.line === elseKeywordLoc.line) {
|
||||
const failure = this.createFailure(elseKeyword.getStart(sourceFile), elseKeyword.getWidth(sourceFile), Rule.ELSE_FAILURE_STRING);
|
||||
this.addFailure(failure);
|
||||
}
|
||||
}
|
||||
function walk(ctx: Lint.WalkContext<void>, checkCatch: boolean, checkElse: boolean): void {
|
||||
const { sourceFile } = ctx;
|
||||
function recur(node: ts.Node): void {
|
||||
switch (node.kind) {
|
||||
case ts.SyntaxKind.IfStatement:
|
||||
checkIf(node as ts.IfStatement);
|
||||
break;
|
||||
case ts.SyntaxKind.TryStatement:
|
||||
checkTry(node as ts.TryStatement);
|
||||
break;
|
||||
}
|
||||
|
||||
super.visitIfStatement(node);
|
||||
ts.forEachChild(node, recur);
|
||||
}
|
||||
|
||||
public visitTryStatement(node: ts.TryStatement) {
|
||||
const sourceFile = node.getSourceFile();
|
||||
const catchClause = node.catchClause;
|
||||
function checkIf(node: ts.IfStatement): void {
|
||||
const { thenStatement, elseStatement } = node;
|
||||
if (!elseStatement) {
|
||||
return;
|
||||
}
|
||||
|
||||
// "visit" try block
|
||||
const tryBlock = node.tryBlock;
|
||||
|
||||
if (this.hasOption(OPTION_CATCH) && !!catchClause) {
|
||||
const tryClosingBrace = tryBlock.getLastToken(sourceFile);
|
||||
const catchKeyword = catchClause.getFirstToken(sourceFile);
|
||||
const tryClosingBraceLoc = sourceFile.getLineAndCharacterOfPosition(tryClosingBrace.getEnd());
|
||||
const catchKeywordLoc = sourceFile.getLineAndCharacterOfPosition(catchKeyword.getStart(sourceFile));
|
||||
if (tryClosingBraceLoc.line === catchKeywordLoc.line) {
|
||||
const failure = this.createFailure(catchKeyword.getStart(sourceFile), catchKeyword.getWidth(sourceFile), Rule.CATCH_FAILURE_STRING);
|
||||
this.addFailure(failure);
|
||||
// find the else keyword
|
||||
const elseKeyword = getFirstChildOfKind(node, ts.SyntaxKind.ElseKeyword);
|
||||
if (checkElse && !!elseKeyword) {
|
||||
const thenStatementEndLoc = sourceFile.getLineAndCharacterOfPosition(thenStatement.getEnd());
|
||||
const elseKeywordLoc = sourceFile.getLineAndCharacterOfPosition(elseKeyword.getStart(sourceFile));
|
||||
if (thenStatementEndLoc.line === elseKeywordLoc.line) {
|
||||
ctx.addFailureAtNode(elseKeyword, Rule.ELSE_FAILURE_STRING);
|
||||
}
|
||||
}
|
||||
super.visitTryStatement(node);
|
||||
}
|
||||
|
||||
function checkTry({ tryBlock, catchClause }: ts.TryStatement): void {
|
||||
if (!checkCatch || !catchClause) {
|
||||
return;
|
||||
}
|
||||
|
||||
const tryClosingBrace = tryBlock.getLastToken(sourceFile);
|
||||
const catchKeyword = catchClause.getFirstToken(sourceFile);
|
||||
const tryClosingBraceLoc = sourceFile.getLineAndCharacterOfPosition(tryClosingBrace.getEnd());
|
||||
const catchKeywordLoc = sourceFile.getLineAndCharacterOfPosition(catchKeyword.getStart(sourceFile));
|
||||
if (tryClosingBraceLoc.line === catchKeywordLoc.line) {
|
||||
ctx.addFailureAtNode(catchKeyword, Rule.CATCH_FAILURE_STRING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import * as Lint from "tslint/lib";
|
||||
import * as ts from "typescript";
|
||||
|
||||
export class Rule extends Lint.Rules.AbstractRule {
|
||||
public static FAILURE_STRING = "This file has a BOM.";
|
||||
|
||||
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
||||
return this.applyWithFunction(sourceFile, walk);
|
||||
}
|
||||
}
|
||||
|
||||
function walk(ctx: Lint.WalkContext<void>): void {
|
||||
if (ctx.sourceFile.text[0] === "\ufeff") {
|
||||
ctx.addFailure(0, 1, Rule.FAILURE_STRING);
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,19 @@
|
||||
import * as Lint from "tslint/lib";
|
||||
import * as ts from "typescript";
|
||||
|
||||
|
||||
export class Rule extends Lint.Rules.AbstractRule {
|
||||
public static FAILURE_STRING = "Don't use the 'in' keyword - use 'hasProperty' to check for key presence instead";
|
||||
|
||||
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
||||
return this.applyWithWalker(new InWalker(sourceFile, this.getOptions()));
|
||||
return this.applyWithFunction(sourceFile, walk);
|
||||
}
|
||||
}
|
||||
|
||||
class InWalker extends Lint.RuleWalker {
|
||||
visitNode(node: ts.Node) {
|
||||
super.visitNode(node);
|
||||
if (node.kind === ts.SyntaxKind.InKeyword && node.parent && node.parent.kind === ts.SyntaxKind.BinaryExpression) {
|
||||
this.addFailure(this.createFailure(node.getStart(), node.getWidth(), Rule.FAILURE_STRING));
|
||||
function walk(ctx: Lint.WalkContext<void>): void {
|
||||
ts.forEachChild(ctx.sourceFile, recur);
|
||||
function recur(node: ts.Node): void {
|
||||
if (node.kind === ts.SyntaxKind.InKeyword && node.parent.kind === ts.SyntaxKind.BinaryExpression) {
|
||||
ctx.addFailureAtNode(node, Rule.FAILURE_STRING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,44 +1,55 @@
|
||||
import * as Lint from "tslint/lib";
|
||||
import * as ts from "typescript";
|
||||
|
||||
|
||||
export class Rule extends Lint.Rules.AbstractRule {
|
||||
public static POSTFIX_FAILURE_STRING = "Don't use '++' or '--' postfix operators outside statements or for loops.";
|
||||
public static PREFIX_FAILURE_STRING = "Don't use '++' or '--' prefix operators.";
|
||||
|
||||
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
||||
return this.applyWithWalker(new IncrementDecrementWalker(sourceFile, this.getOptions()));
|
||||
return this.applyWithFunction(sourceFile, walk);
|
||||
}
|
||||
}
|
||||
|
||||
class IncrementDecrementWalker extends Lint.RuleWalker {
|
||||
function walk(ctx: Lint.WalkContext<void>): void {
|
||||
ts.forEachChild(ctx.sourceFile, recur);
|
||||
function recur(node: ts.Node): void {
|
||||
switch (node.kind) {
|
||||
case ts.SyntaxKind.PrefixUnaryExpression:
|
||||
const { operator } = node as ts.PrefixUnaryExpression;
|
||||
if (operator === ts.SyntaxKind.PlusPlusToken || operator === ts.SyntaxKind.MinusMinusToken) {
|
||||
check(node as ts.PrefixUnaryExpression);
|
||||
}
|
||||
break;
|
||||
|
||||
visitPostfixUnaryExpression(node: ts.PostfixUnaryExpression) {
|
||||
super.visitPostfixUnaryExpression(node);
|
||||
if (node.operator === ts.SyntaxKind.PlusPlusToken || node.operator == ts.SyntaxKind.MinusMinusToken) {
|
||||
this.visitIncrementDecrement(node);
|
||||
case ts.SyntaxKind.PostfixUnaryExpression:
|
||||
check(node as ts.PostfixUnaryExpression);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
visitPrefixUnaryExpression(node: ts.PrefixUnaryExpression) {
|
||||
super.visitPrefixUnaryExpression(node);
|
||||
if (node.operator === ts.SyntaxKind.PlusPlusToken || node.operator == ts.SyntaxKind.MinusMinusToken) {
|
||||
this.addFailure(this.createFailure(node.getStart(), node.getWidth(), Rule.PREFIX_FAILURE_STRING));
|
||||
function check(node: ts.UnaryExpression): void {
|
||||
if (!isAllowedLocation(node.parent!)) {
|
||||
ctx.addFailureAtNode(node, Rule.POSTFIX_FAILURE_STRING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
visitIncrementDecrement(node: ts.UnaryExpression) {
|
||||
if (node.parent && (
|
||||
// Can be a statement
|
||||
node.parent.kind === ts.SyntaxKind.ExpressionStatement ||
|
||||
// Can be directly in a for-statement
|
||||
node.parent.kind === ts.SyntaxKind.ForStatement ||
|
||||
// Can be in a comma operator in a for statement (`for (let a = 0, b = 10; a < b; a++, b--)`)
|
||||
node.parent.kind === ts.SyntaxKind.BinaryExpression &&
|
||||
(<ts.BinaryExpression>node.parent).operatorToken.kind === ts.SyntaxKind.CommaToken &&
|
||||
node.parent.parent.kind === ts.SyntaxKind.ForStatement)) {
|
||||
return;
|
||||
}
|
||||
this.addFailure(this.createFailure(node.getStart(), node.getWidth(), Rule.POSTFIX_FAILURE_STRING));
|
||||
function isAllowedLocation(node: ts.Node): boolean {
|
||||
switch (node.kind) {
|
||||
// Can be a statement
|
||||
case ts.SyntaxKind.ExpressionStatement:
|
||||
return true;
|
||||
|
||||
// Can be directly in a for-statement
|
||||
case ts.SyntaxKind.ForStatement:
|
||||
return true;
|
||||
|
||||
// Can be in a comma operator in a for statement (`for (let a = 0, b = 10; a < b; a++, b--)`)
|
||||
case ts.SyntaxKind.BinaryExpression:
|
||||
return (node as ts.BinaryExpression).operatorToken.kind === ts.SyntaxKind.CommaToken &&
|
||||
node.parent!.kind === ts.SyntaxKind.ForStatement;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
import * as Lint from "tslint/lib";
|
||||
import * as ts from "typescript";
|
||||
|
||||
|
||||
export class Rule extends Lint.Rules.AbstractRule {
|
||||
public static TRAILING_FAILURE_STRING = "Excess trailing whitespace found around type assertion.";
|
||||
|
||||
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
||||
return this.applyWithWalker(new TypeAssertionWhitespaceWalker(sourceFile, this.getOptions()));
|
||||
return this.applyWithFunction(sourceFile, walk);
|
||||
}
|
||||
}
|
||||
|
||||
class TypeAssertionWhitespaceWalker extends Lint.RuleWalker {
|
||||
public visitNode(node: ts.Node) {
|
||||
function walk(ctx: Lint.WalkContext<void>): void {
|
||||
ts.forEachChild(ctx.sourceFile, recur);
|
||||
function recur(node: ts.Node) {
|
||||
if (node.kind === ts.SyntaxKind.TypeAssertionExpression) {
|
||||
const refined = node as ts.TypeAssertion;
|
||||
const leftSideWhitespaceStart = refined.type.getEnd() + 1;
|
||||
const rightSideWhitespaceEnd = refined.expression.getStart();
|
||||
if (leftSideWhitespaceStart !== rightSideWhitespaceEnd) {
|
||||
this.addFailure(this.createFailure(leftSideWhitespaceStart, rightSideWhitespaceEnd, Rule.TRAILING_FAILURE_STRING));
|
||||
ctx.addFailure(leftSideWhitespaceStart, rightSideWhitespaceEnd, Rule.TRAILING_FAILURE_STRING);
|
||||
}
|
||||
}
|
||||
super.visitNode(node);
|
||||
ts.forEachChild(node, recur);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import * as Lint from "tslint/lib";
|
||||
import * as ts from "typescript";
|
||||
|
||||
|
||||
export class Rule extends Lint.Rules.AbstractRule {
|
||||
public static LEADING_FAILURE_STRING = "No leading whitespace found on single-line object literal.";
|
||||
public static TRAILING_FAILURE_STRING = "No trailing whitespace found on single-line object literal.";
|
||||
@@ -9,34 +8,37 @@ export class Rule extends Lint.Rules.AbstractRule {
|
||||
public static TRAILING_EXCESS_FAILURE_STRING = "Excess trailing whitespace found on single-line object literal.";
|
||||
|
||||
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
||||
return this.applyWithWalker(new ObjectLiteralSpaceWalker(sourceFile, this.getOptions()));
|
||||
return this.applyWithFunction(sourceFile, walk);
|
||||
}
|
||||
}
|
||||
|
||||
class ObjectLiteralSpaceWalker extends Lint.RuleWalker {
|
||||
public visitNode(node: ts.Node) {
|
||||
function walk(ctx: Lint.WalkContext<void>): void {
|
||||
const { sourceFile } = ctx;
|
||||
ts.forEachChild(sourceFile, recur);
|
||||
function recur(node: ts.Node): void {
|
||||
if (node.kind === ts.SyntaxKind.ObjectLiteralExpression) {
|
||||
const literal = node as ts.ObjectLiteralExpression;
|
||||
const text = literal.getText();
|
||||
if (text.match(/^{[^\n]+}$/g)) {
|
||||
if (text.charAt(1) !== " ") {
|
||||
const failure = this.createFailure(node.pos, node.getWidth(), Rule.LEADING_FAILURE_STRING);
|
||||
this.addFailure(failure);
|
||||
}
|
||||
if (text.charAt(2) === " ") {
|
||||
const failure = this.createFailure(node.pos + 2, 1, Rule.LEADING_EXCESS_FAILURE_STRING);
|
||||
this.addFailure(failure);
|
||||
}
|
||||
if (text.charAt(text.length - 2) !== " ") {
|
||||
const failure = this.createFailure(node.pos, node.getWidth(), Rule.TRAILING_FAILURE_STRING);
|
||||
this.addFailure(failure);
|
||||
}
|
||||
if (text.charAt(text.length - 3) === " ") {
|
||||
const failure = this.createFailure(node.pos + node.getWidth() - 3, 1, Rule.TRAILING_EXCESS_FAILURE_STRING);
|
||||
this.addFailure(failure);
|
||||
}
|
||||
}
|
||||
check(node as ts.ObjectLiteralExpression);
|
||||
}
|
||||
ts.forEachChild(node, recur);
|
||||
}
|
||||
|
||||
function check(node: ts.ObjectLiteralExpression): void {
|
||||
const text = node.getText(sourceFile);
|
||||
if (!text.match(/^{[^\n]+}$/g)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (text.charAt(1) !== " ") {
|
||||
ctx.addFailureAtNode(node, Rule.LEADING_FAILURE_STRING);
|
||||
}
|
||||
if (text.charAt(2) === " ") {
|
||||
ctx.addFailureAt(node.pos + 2, 1, Rule.LEADING_EXCESS_FAILURE_STRING);
|
||||
}
|
||||
if (text.charAt(text.length - 2) !== " ") {
|
||||
ctx.addFailureAtNode(node, Rule.TRAILING_FAILURE_STRING);
|
||||
}
|
||||
if (text.charAt(text.length - 3) === " ") {
|
||||
ctx.addFailureAt(node.pos + node.getWidth() - 3, 1, Rule.TRAILING_EXCESS_FAILURE_STRING);
|
||||
}
|
||||
super.visitNode(node);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"noImplicitAny": true,
|
||||
"noImplicitReturns": true,
|
||||
"noImplicitThis": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"strictNullChecks": true,
|
||||
"module": "commonjs",
|
||||
"outDir": "../../built/local/tslint"
|
||||
}
|
||||
|
||||
@@ -1,34 +1,36 @@
|
||||
import * as Lint from "tslint/lib";
|
||||
import * as ts from "typescript";
|
||||
|
||||
|
||||
export class Rule extends Lint.Rules.AbstractRule {
|
||||
public static FAILURE_STRING = "The '|' and '&' operators must be surrounded by single spaces";
|
||||
|
||||
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
||||
return this.applyWithWalker(new TypeOperatorSpacingWalker(sourceFile, this.getOptions()));
|
||||
return this.applyWithFunction(sourceFile, walk);
|
||||
}
|
||||
}
|
||||
|
||||
class TypeOperatorSpacingWalker extends Lint.RuleWalker {
|
||||
public visitNode(node: ts.Node) {
|
||||
function walk(ctx: Lint.WalkContext<void>): void {
|
||||
const { sourceFile } = ctx;
|
||||
ts.forEachChild(sourceFile, recur);
|
||||
function recur(node: ts.Node): void {
|
||||
if (node.kind === ts.SyntaxKind.UnionType || node.kind === ts.SyntaxKind.IntersectionType) {
|
||||
const types = (<ts.UnionOrIntersectionTypeNode>node).types;
|
||||
let expectedStart = types[0].end + 2; // space, | or &
|
||||
for (let i = 1; i < types.length; i++) {
|
||||
const currentType = types[i];
|
||||
if (expectedStart !== currentType.pos || currentType.getLeadingTriviaWidth() !== 1) {
|
||||
const sourceFile = currentType.getSourceFile();
|
||||
const previousTypeEndPos = sourceFile.getLineAndCharacterOfPosition(types[i - 1].end);
|
||||
const currentTypeStartPos = sourceFile.getLineAndCharacterOfPosition(currentType.pos);
|
||||
if (previousTypeEndPos.line === currentTypeStartPos.line) {
|
||||
const failure = this.createFailure(currentType.pos, currentType.getWidth(), Rule.FAILURE_STRING);
|
||||
this.addFailure(failure);
|
||||
}
|
||||
check((node as ts.UnionOrIntersectionTypeNode).types);
|
||||
}
|
||||
ts.forEachChild(node, recur);
|
||||
}
|
||||
|
||||
function check(types: ts.TypeNode[]): void {
|
||||
let expectedStart = types[0].end + 2; // space, | or &
|
||||
for (let i = 1; i < types.length; i++) {
|
||||
const currentType = types[i];
|
||||
if (expectedStart !== currentType.pos || currentType.getLeadingTriviaWidth() !== 1) {
|
||||
const previousTypeEndPos = sourceFile.getLineAndCharacterOfPosition(types[i - 1].end);
|
||||
const currentTypeStartPos = sourceFile.getLineAndCharacterOfPosition(currentType.pos);
|
||||
if (previousTypeEndPos.line === currentTypeStartPos.line) {
|
||||
ctx.addFailureAtNode(currentType, Rule.FAILURE_STRING);
|
||||
}
|
||||
expectedStart = currentType.end + 2;
|
||||
}
|
||||
expectedStart = currentType.end + 2;
|
||||
}
|
||||
super.visitNode(node);
|
||||
}
|
||||
}
|
||||
|
||||
+71
-20
@@ -182,7 +182,7 @@ namespace ts {
|
||||
return bindSourceFile;
|
||||
|
||||
function bindInStrictMode(file: SourceFile, opts: CompilerOptions): boolean {
|
||||
if (opts.alwaysStrict && !isDeclarationFile(file)) {
|
||||
if ((opts.alwaysStrict === undefined ? opts.strict : opts.alwaysStrict) && !isDeclarationFile(file)) {
|
||||
// bind in strict mode source files with alwaysStrict option
|
||||
return true;
|
||||
}
|
||||
@@ -1903,7 +1903,7 @@ namespace ts {
|
||||
|
||||
// Even though in the AST the jsdoc @typedef node belongs to the current node,
|
||||
// its symbol might be in the same scope with the current node's symbol. Consider:
|
||||
//
|
||||
//
|
||||
// /** @typedef {string | number} MyType */
|
||||
// function foo();
|
||||
//
|
||||
@@ -2289,7 +2289,42 @@ namespace ts {
|
||||
declareSymbol(file.symbol.exports, file.symbol, <PropertyAccessExpression>node.left, SymbolFlags.Property | SymbolFlags.Export, SymbolFlags.None);
|
||||
}
|
||||
|
||||
function isExportsOrModuleExportsOrAlias(node: Node): boolean {
|
||||
return isExportsIdentifier(node) ||
|
||||
isModuleExportsPropertyAccessExpression(node) ||
|
||||
isNameOfExportsOrModuleExportsAliasDeclaration(node);
|
||||
}
|
||||
|
||||
function isNameOfExportsOrModuleExportsAliasDeclaration(node: Node) {
|
||||
if (node.kind === SyntaxKind.Identifier) {
|
||||
const symbol = container.locals.get((<Identifier>node).text);
|
||||
if (symbol && symbol.valueDeclaration && symbol.valueDeclaration.kind === SyntaxKind.VariableDeclaration) {
|
||||
const declaration = symbol.valueDeclaration as VariableDeclaration;
|
||||
if (declaration.initializer) {
|
||||
return isExportsOrModuleExportsOrAliasOrAssignemnt(declaration.initializer);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function isExportsOrModuleExportsOrAliasOrAssignemnt(node: Node): boolean {
|
||||
return isExportsOrModuleExportsOrAlias(node) ||
|
||||
(isAssignmentExpression(node, /*excludeCompoundAssignements*/ true) && (isExportsOrModuleExportsOrAliasOrAssignemnt(node.left) || isExportsOrModuleExportsOrAliasOrAssignemnt(node.right)));
|
||||
}
|
||||
|
||||
function bindModuleExportsAssignment(node: BinaryExpression) {
|
||||
// A common practice in node modules is to set 'export = module.exports = {}', this ensures that 'exports'
|
||||
// is still pointing to 'module.exports'.
|
||||
// We do not want to consider this as 'export=' since a module can have only one of these.
|
||||
// Similarlly we do not want to treat 'module.exports = exports' as an 'export='.
|
||||
const assignedExpression = getRightMostAssignedExpression(node.right);
|
||||
if (isEmptyObjectLiteral(assignedExpression) || isExportsOrModuleExportsOrAlias(assignedExpression)) {
|
||||
// Mark it as a module in case there are no other exports in the file
|
||||
setCommonJsModuleIndicator(node);
|
||||
return;
|
||||
}
|
||||
|
||||
// 'module.exports = expr' assignment
|
||||
setCommonJsModuleIndicator(node);
|
||||
declareSymbol(file.symbol.exports, file.symbol, node, SymbolFlags.Property | SymbolFlags.Export | SymbolFlags.ValueModule, SymbolFlags.None);
|
||||
@@ -2297,23 +2332,30 @@ namespace ts {
|
||||
|
||||
function bindThisPropertyAssignment(node: BinaryExpression) {
|
||||
Debug.assert(isInJavaScriptFile(node));
|
||||
// Declare a 'member' if the container is an ES5 class or ES6 constructor
|
||||
if (container.kind === SyntaxKind.FunctionDeclaration || container.kind === SyntaxKind.FunctionExpression) {
|
||||
container.symbol.members = container.symbol.members || createMap<Symbol>();
|
||||
// It's acceptable for multiple 'this' assignments of the same identifier to occur
|
||||
declareSymbol(container.symbol.members, container.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes & ~SymbolFlags.Property);
|
||||
}
|
||||
else if (container.kind === SyntaxKind.Constructor) {
|
||||
// this.foo assignment in a JavaScript class
|
||||
// Bind this property to the containing class
|
||||
const saveContainer = container;
|
||||
container = container.parent;
|
||||
const symbol = bindPropertyOrMethodOrAccessor(node, SymbolFlags.Property, SymbolFlags.None);
|
||||
if (symbol) {
|
||||
// constructor-declared symbols can be overwritten by subsequent method declarations
|
||||
(symbol as Symbol).isReplaceableByMethod = true;
|
||||
}
|
||||
container = saveContainer;
|
||||
const container = getThisContainer(node, /*includeArrowFunctions*/false);
|
||||
switch (container.kind) {
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.FunctionExpression:
|
||||
// Declare a 'member' if the container is an ES5 class or ES6 constructor
|
||||
container.symbol.members = container.symbol.members || createMap<Symbol>();
|
||||
// It's acceptable for multiple 'this' assignments of the same identifier to occur
|
||||
declareSymbol(container.symbol.members, container.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes & ~SymbolFlags.Property);
|
||||
break;
|
||||
|
||||
case SyntaxKind.Constructor:
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
// 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;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2346,11 +2388,20 @@ namespace ts {
|
||||
leftSideOfAssignment.parent = node;
|
||||
target.parent = leftSideOfAssignment;
|
||||
|
||||
bindPropertyAssignment(target.text, leftSideOfAssignment, /*isPrototypeProperty*/ false);
|
||||
if (isNameOfExportsOrModuleExportsAliasDeclaration(target)) {
|
||||
// This can be an alias for the 'exports' or 'module.exports' names, e.g.
|
||||
// var util = module.exports;
|
||||
// util.property = function ...
|
||||
bindExportsPropertyAssignment(node);
|
||||
}
|
||||
else {
|
||||
bindPropertyAssignment(target.text, leftSideOfAssignment, /*isPrototypeProperty*/ false);
|
||||
}
|
||||
}
|
||||
|
||||
function bindPropertyAssignment(functionName: string, propertyAccessExpression: PropertyAccessExpression, isPrototypeProperty: boolean) {
|
||||
let targetSymbol = container.locals.get(functionName);
|
||||
|
||||
if (targetSymbol && isDeclarationOfFunctionOrClassExpression(targetSymbol)) {
|
||||
targetSymbol = (targetSymbol.valueDeclaration as VariableDeclaration).initializer.symbol;
|
||||
}
|
||||
|
||||
+353
-249
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
/// <reference path="sys.ts"/>
|
||||
/// <reference path="sys.ts"/>
|
||||
/// <reference path="types.ts"/>
|
||||
/// <reference path="core.ts"/>
|
||||
/// <reference path="diagnosticInformationMap.generated.ts"/>
|
||||
@@ -467,6 +467,11 @@ namespace ts {
|
||||
type: "boolean",
|
||||
description: Diagnostics.Parse_in_strict_mode_and_emit_use_strict_for_each_source_file
|
||||
},
|
||||
{
|
||||
name: "strict",
|
||||
type: "boolean",
|
||||
description: Diagnostics.Enable_all_strict_type_checks
|
||||
},
|
||||
{
|
||||
// A list of plugins to load in the language service
|
||||
name: "plugins",
|
||||
@@ -520,7 +525,7 @@ namespace ts {
|
||||
export const defaultInitCompilerOptions: CompilerOptions = {
|
||||
module: ModuleKind.CommonJS,
|
||||
target: ScriptTarget.ES5,
|
||||
noImplicitAny: false,
|
||||
strict: true,
|
||||
sourceMap: false,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/// <reference path="types.ts"/>
|
||||
/// <reference path="types.ts"/>
|
||||
/// <reference path="performance.ts" />
|
||||
|
||||
namespace ts {
|
||||
|
||||
@@ -2413,10 +2413,6 @@
|
||||
"category": "Error",
|
||||
"code": 5012
|
||||
},
|
||||
"Unsupported file encoding.": {
|
||||
"category": "Error",
|
||||
"code": 5013
|
||||
},
|
||||
"Failed to parse file '{0}': {1}.": {
|
||||
"category": "Error",
|
||||
"code": 5014
|
||||
@@ -3045,6 +3041,10 @@
|
||||
"category": "Message",
|
||||
"code": 6149
|
||||
},
|
||||
"Enable all strict type checks.": {
|
||||
"category": "Message",
|
||||
"code": 6150
|
||||
},
|
||||
"Variable '{0}' implicitly has an '{1}' type.": {
|
||||
"category": "Error",
|
||||
"code": 7005
|
||||
|
||||
+33
-4
@@ -1,4 +1,4 @@
|
||||
/// <reference path="checker.ts" />
|
||||
/// <reference path="checker.ts" />
|
||||
/// <reference path="transformer.ts" />
|
||||
/// <reference path="declarationEmitter.ts" />
|
||||
/// <reference path="sourcemap.ts" />
|
||||
@@ -199,6 +199,8 @@ namespace ts {
|
||||
onEmitHelpers,
|
||||
onSetSourceFile,
|
||||
substituteNode,
|
||||
onBeforeEmitNodeArray,
|
||||
onAfterEmitNodeArray
|
||||
} = handlers;
|
||||
|
||||
const newLine = getNewLineCharacter(printerOptions);
|
||||
@@ -635,6 +637,11 @@ namespace ts {
|
||||
if (isExpression(node)) {
|
||||
return pipelineEmitExpression(trySubstituteNode(EmitHint.Expression, node));
|
||||
}
|
||||
|
||||
if (isToken(node)) {
|
||||
writeTokenText(kind);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function pipelineEmitExpression(node: Node): void {
|
||||
@@ -814,8 +821,8 @@ namespace ts {
|
||||
writeIfPresent(node.dotDotDotToken, "...");
|
||||
emit(node.name);
|
||||
writeIfPresent(node.questionToken, "?");
|
||||
emitExpressionWithPrefix(" = ", node.initializer);
|
||||
emitWithPrefix(": ", node.type);
|
||||
emitExpressionWithPrefix(" = ", node.initializer);
|
||||
}
|
||||
|
||||
function emitDecorator(decorator: Decorator) {
|
||||
@@ -1548,6 +1555,10 @@ namespace ts {
|
||||
emitSignatureAndBody(node, emitSignatureHead);
|
||||
}
|
||||
|
||||
function emitBlockCallback(_hint: EmitHint, body: Node): void {
|
||||
emitBlockFunctionBody(<Block>body);
|
||||
}
|
||||
|
||||
function emitSignatureAndBody(node: FunctionLikeDeclaration, emitSignatureHead: (node: SignatureDeclaration) => void) {
|
||||
const body = node.body;
|
||||
if (body) {
|
||||
@@ -1559,12 +1570,22 @@ namespace ts {
|
||||
|
||||
if (getEmitFlags(node) & EmitFlags.ReuseTempVariableScope) {
|
||||
emitSignatureHead(node);
|
||||
emitBlockFunctionBody(body);
|
||||
if (onEmitNode) {
|
||||
onEmitNode(EmitHint.Unspecified, body, emitBlockCallback);
|
||||
}
|
||||
else {
|
||||
emitBlockFunctionBody(body);
|
||||
}
|
||||
}
|
||||
else {
|
||||
pushNameGenerationScope();
|
||||
emitSignatureHead(node);
|
||||
emitBlockFunctionBody(body);
|
||||
if (onEmitNode) {
|
||||
onEmitNode(EmitHint.Unspecified, body, emitBlockCallback);
|
||||
}
|
||||
else {
|
||||
emitBlockFunctionBody(body);
|
||||
}
|
||||
popNameGenerationScope();
|
||||
}
|
||||
|
||||
@@ -2243,6 +2264,10 @@ namespace ts {
|
||||
write(getOpeningBracket(format));
|
||||
}
|
||||
|
||||
if (onBeforeEmitNodeArray) {
|
||||
onBeforeEmitNodeArray(children);
|
||||
}
|
||||
|
||||
if (isEmpty) {
|
||||
// Write a line terminator if the parent node was multi-line
|
||||
if (format & ListFormat.MultiLine) {
|
||||
@@ -2358,6 +2383,10 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
if (onAfterEmitNodeArray) {
|
||||
onAfterEmitNodeArray(children);
|
||||
}
|
||||
|
||||
if (format & ListFormat.BracketsMask) {
|
||||
write(getClosingBracket(format));
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/// <reference path="core.ts"/>
|
||||
/// <reference path="core.ts"/>
|
||||
/// <reference path="utilities.ts"/>
|
||||
|
||||
namespace ts {
|
||||
@@ -1099,6 +1099,10 @@ namespace ts {
|
||||
: node;
|
||||
}
|
||||
|
||||
export function createKeywordTypeNode(kind: KeywordTypeNode["kind"]): KeywordTypeNode {
|
||||
return <KeywordTypeNode>createSynthesizedNode(kind);
|
||||
}
|
||||
|
||||
export function createFunctionDeclaration(decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined) {
|
||||
const node = <FunctionDeclaration>createSynthesizedNode(SyntaxKind.FunctionDeclaration);
|
||||
node.decorators = asNodeArray(decorators);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/// <reference path="core.ts" />
|
||||
/// <reference path="core.ts" />
|
||||
/// <reference path="diagnosticInformationMap.generated.ts" />
|
||||
|
||||
namespace ts {
|
||||
|
||||
+28
-24
@@ -1309,7 +1309,7 @@ namespace ts {
|
||||
case ParsingContext.ObjectBindingElements:
|
||||
return token() === SyntaxKind.OpenBracketToken || token() === SyntaxKind.DotDotDotToken || isLiteralPropertyName();
|
||||
case ParsingContext.HeritageClauseElement:
|
||||
// If we see { } then only consume it as an expression if it is followed by , or {
|
||||
// If we see `{ ... }` then only consume it as an expression if it is followed by `,` or `{`
|
||||
// That way we won't consume the body of a class in its heritage clause.
|
||||
if (token() === SyntaxKind.OpenBraceToken) {
|
||||
return lookAhead(isValidHeritageClauseObjectLiteral);
|
||||
@@ -2113,7 +2113,7 @@ namespace ts {
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function parseTypeParameters(): NodeArray<TypeParameterDeclaration> {
|
||||
function parseTypeParameters(): NodeArray<TypeParameterDeclaration> | undefined {
|
||||
if (token() === SyntaxKind.LessThanToken) {
|
||||
return parseBracketedList(ParsingContext.TypeParameters, parseTypeParameter, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken);
|
||||
}
|
||||
@@ -2183,7 +2183,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function fillSignature(
|
||||
returnToken: SyntaxKind,
|
||||
returnToken: SyntaxKind.ColonToken | SyntaxKind.EqualsGreaterThanToken,
|
||||
yieldContext: boolean,
|
||||
awaitContext: boolean,
|
||||
requireCompleteParameterList: boolean,
|
||||
@@ -2373,14 +2373,14 @@ namespace ts {
|
||||
}
|
||||
|
||||
function isTypeMemberStart(): boolean {
|
||||
let idToken: SyntaxKind;
|
||||
// Return true if we have the start of a signature member
|
||||
if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) {
|
||||
return true;
|
||||
}
|
||||
let idToken: boolean;
|
||||
// Eat up all modifiers, but hold on to the last one in case it is actually an identifier
|
||||
while (isModifierKind(token())) {
|
||||
idToken = token();
|
||||
idToken = true;
|
||||
nextToken();
|
||||
}
|
||||
// Index signatures and computed property names are type members
|
||||
@@ -2389,7 +2389,7 @@ namespace ts {
|
||||
}
|
||||
// Try to get the first property-like token following all modifiers
|
||||
if (isLiteralPropertyName()) {
|
||||
idToken = token();
|
||||
idToken = true;
|
||||
nextToken();
|
||||
}
|
||||
// If we were able to get any potential identifier, check that it is
|
||||
@@ -2497,7 +2497,7 @@ namespace ts {
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function parseKeywordAndNoDot(): TypeNode {
|
||||
function parseKeywordAndNoDot(): TypeNode | undefined {
|
||||
const node = parseTokenNode<TypeNode>();
|
||||
return token() === SyntaxKind.DotToken ? undefined : node;
|
||||
}
|
||||
@@ -2635,7 +2635,7 @@ namespace ts {
|
||||
return parseArrayTypeOrHigher();
|
||||
}
|
||||
|
||||
function parseUnionOrIntersectionType(kind: SyntaxKind, parseConstituentType: () => TypeNode, operator: SyntaxKind): TypeNode {
|
||||
function parseUnionOrIntersectionType(kind: SyntaxKind.UnionType | SyntaxKind.IntersectionType, parseConstituentType: () => TypeNode, operator: SyntaxKind.BarToken | SyntaxKind.AmpersandToken): TypeNode {
|
||||
parseOptional(operator);
|
||||
let type = parseConstituentType();
|
||||
if (token() === operator) {
|
||||
@@ -3863,6 +3863,9 @@ namespace ts {
|
||||
parseErrorAtPosition(openingTagName.pos, openingTagName.end - openingTagName.pos, Diagnostics.JSX_element_0_has_no_corresponding_closing_tag, getTextOfNodeFromSourceText(sourceText, openingTagName));
|
||||
break;
|
||||
}
|
||||
else if (token() === SyntaxKind.ConflictMarkerTrivia) {
|
||||
break;
|
||||
}
|
||||
result.push(parseJsxChild());
|
||||
}
|
||||
|
||||
@@ -5281,8 +5284,8 @@ namespace ts {
|
||||
*
|
||||
* In such situations, 'permitInvalidConstAsModifier' should be set to true.
|
||||
*/
|
||||
function parseModifiers(permitInvalidConstAsModifier?: boolean): NodeArray<Modifier> {
|
||||
let modifiers: NodeArray<Modifier>;
|
||||
function parseModifiers(permitInvalidConstAsModifier?: boolean): NodeArray<Modifier> | undefined {
|
||||
let modifiers: NodeArray<Modifier> | undefined;
|
||||
while (true) {
|
||||
const modifierStart = scanner.getStartPos();
|
||||
const modifierKind = token();
|
||||
@@ -5422,7 +5425,7 @@ namespace ts {
|
||||
return token() === SyntaxKind.ImplementsKeyword && lookAhead(nextTokenIsIdentifierOrKeyword);
|
||||
}
|
||||
|
||||
function parseHeritageClauses(): NodeArray<HeritageClause> {
|
||||
function parseHeritageClauses(): NodeArray<HeritageClause> | undefined {
|
||||
// ClassTail[Yield,Await] : (Modified) See 14.5
|
||||
// ClassHeritage[?Yield,?Await]opt { ClassBody[?Yield,?Await]opt }
|
||||
|
||||
@@ -5433,7 +5436,7 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function parseHeritageClause() {
|
||||
function parseHeritageClause(): HeritageClause | undefined {
|
||||
if (token() === SyntaxKind.ExtendsKeyword || token() === SyntaxKind.ImplementsKeyword) {
|
||||
const node = <HeritageClause>createNode(SyntaxKind.HeritageClause);
|
||||
node.token = token();
|
||||
@@ -5459,7 +5462,7 @@ namespace ts {
|
||||
return token() === SyntaxKind.ExtendsKeyword || token() === SyntaxKind.ImplementsKeyword;
|
||||
}
|
||||
|
||||
function parseClassMembers() {
|
||||
function parseClassMembers(): NodeArray<ClassElement> {
|
||||
return parseList(ParsingContext.ClassMembers, parseClassElement);
|
||||
}
|
||||
|
||||
@@ -5618,17 +5621,7 @@ namespace ts {
|
||||
if (isIdentifier()) {
|
||||
identifier = parseIdentifier();
|
||||
if (token() !== SyntaxKind.CommaToken && token() !== SyntaxKind.FromKeyword) {
|
||||
// ImportEquals declaration of type:
|
||||
// import x = require("mod"); or
|
||||
// import x = M.x;
|
||||
const importEqualsDeclaration = <ImportEqualsDeclaration>createNode(SyntaxKind.ImportEqualsDeclaration, fullStart);
|
||||
importEqualsDeclaration.decorators = decorators;
|
||||
importEqualsDeclaration.modifiers = modifiers;
|
||||
importEqualsDeclaration.name = identifier;
|
||||
parseExpected(SyntaxKind.EqualsToken);
|
||||
importEqualsDeclaration.moduleReference = parseModuleReference();
|
||||
parseSemicolon();
|
||||
return addJSDocComment(finishNode(importEqualsDeclaration));
|
||||
return parseImportEqualsDeclaration(fullStart, decorators, modifiers, identifier);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5652,6 +5645,17 @@ namespace ts {
|
||||
return finishNode(importDeclaration);
|
||||
}
|
||||
|
||||
function parseImportEqualsDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: NodeArray<Modifier>, identifier: ts.Identifier): ImportEqualsDeclaration {
|
||||
const importEqualsDeclaration = <ImportEqualsDeclaration>createNode(SyntaxKind.ImportEqualsDeclaration, fullStart);
|
||||
importEqualsDeclaration.decorators = decorators;
|
||||
importEqualsDeclaration.modifiers = modifiers;
|
||||
importEqualsDeclaration.name = identifier;
|
||||
parseExpected(SyntaxKind.EqualsToken);
|
||||
importEqualsDeclaration.moduleReference = parseModuleReference();
|
||||
parseSemicolon();
|
||||
return addJSDocComment(finishNode(importEqualsDeclaration));
|
||||
}
|
||||
|
||||
function parseImportClause(identifier: Identifier, fullStart: number) {
|
||||
// ImportClause:
|
||||
// ImportedDefaultBinding
|
||||
|
||||
+45
-8
@@ -87,9 +87,6 @@ namespace ts {
|
||||
return sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
|
||||
}
|
||||
|
||||
// returned by CScript sys environment
|
||||
const unsupportedFileEncodingErrorCode = -2147024809;
|
||||
|
||||
function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile {
|
||||
let text: string;
|
||||
try {
|
||||
@@ -100,9 +97,7 @@ namespace ts {
|
||||
}
|
||||
catch (e) {
|
||||
if (onError) {
|
||||
onError(e.number === unsupportedFileEncodingErrorCode
|
||||
? createCompilerDiagnostic(Diagnostics.Unsupported_file_encoding).messageText
|
||||
: e.message);
|
||||
onError(e.message);
|
||||
}
|
||||
text = "";
|
||||
}
|
||||
@@ -290,6 +285,11 @@ namespace ts {
|
||||
return resolutions;
|
||||
}
|
||||
|
||||
interface DiagnosticCache {
|
||||
perFile?: FileMap<Diagnostic[]>;
|
||||
allDiagnostics?: Diagnostic[];
|
||||
}
|
||||
|
||||
export function createProgram(rootNames: string[], options: CompilerOptions, host?: CompilerHost, oldProgram?: Program): Program {
|
||||
let program: Program;
|
||||
let files: SourceFile[] = [];
|
||||
@@ -298,6 +298,9 @@ namespace ts {
|
||||
let noDiagnosticsTypeChecker: TypeChecker;
|
||||
let classifiableNames: Map<string>;
|
||||
|
||||
const cachedSemanticDiagnosticsForFile: DiagnosticCache = {};
|
||||
const cachedDeclarationDiagnosticsForFile: DiagnosticCache = {};
|
||||
|
||||
let resolvedTypeReferenceDirectives = createMap<ResolvedTypeReferenceDirective>();
|
||||
let fileProcessingDiagnostics = createDiagnosticCollection();
|
||||
|
||||
@@ -899,6 +902,10 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getSemanticDiagnosticsForFile(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] {
|
||||
return getAndCacheDiagnostics(sourceFile, cancellationToken, cachedSemanticDiagnosticsForFile, getSemanticDiagnosticsForFileNoCache);
|
||||
}
|
||||
|
||||
function getSemanticDiagnosticsForFileNoCache(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] {
|
||||
return runWithCancellationToken(() => {
|
||||
const typeChecker = getDiagnosticsProducingTypeChecker();
|
||||
|
||||
@@ -1094,7 +1101,11 @@ namespace ts {
|
||||
});
|
||||
}
|
||||
|
||||
function getDeclarationDiagnosticsWorker(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] {
|
||||
function getDeclarationDiagnosticsWorker(sourceFile: SourceFile | undefined, cancellationToken: CancellationToken): Diagnostic[] {
|
||||
return getAndCacheDiagnostics(sourceFile, cancellationToken, cachedDeclarationDiagnosticsForFile, getDeclarationDiagnosticsForFileNoCache);
|
||||
}
|
||||
|
||||
function getDeclarationDiagnosticsForFileNoCache(sourceFile: SourceFile | undefined, cancellationToken: CancellationToken) {
|
||||
return runWithCancellationToken(() => {
|
||||
const resolver = getDiagnosticsProducingTypeChecker().getEmitResolver(sourceFile, cancellationToken);
|
||||
// Don't actually write any files since we're just getting diagnostics.
|
||||
@@ -1102,6 +1113,32 @@ namespace ts {
|
||||
});
|
||||
}
|
||||
|
||||
function getAndCacheDiagnostics(
|
||||
sourceFile: SourceFile | undefined,
|
||||
cancellationToken: CancellationToken,
|
||||
cache: DiagnosticCache,
|
||||
getDiagnostics: (sourceFile: SourceFile, cancellationToken: CancellationToken) => Diagnostic[]) {
|
||||
|
||||
const cachedResult = sourceFile
|
||||
? cache.perFile && cache.perFile.get(sourceFile.path)
|
||||
: cache.allDiagnostics;
|
||||
|
||||
if (cachedResult) {
|
||||
return cachedResult;
|
||||
}
|
||||
const result = getDiagnostics(sourceFile, cancellationToken) || emptyArray;
|
||||
if (sourceFile) {
|
||||
if (!cache.perFile) {
|
||||
cache.perFile = createFileMap<Diagnostic[]>();
|
||||
}
|
||||
cache.perFile.set(sourceFile.path, result);
|
||||
}
|
||||
else {
|
||||
cache.allDiagnostics = result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function getDeclarationDiagnosticsForFile(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] {
|
||||
return isDeclarationFile(sourceFile) ? [] : getDeclarationDiagnosticsWorker(sourceFile, cancellationToken);
|
||||
}
|
||||
@@ -1630,7 +1667,7 @@ namespace ts {
|
||||
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "lib", "noLib"));
|
||||
}
|
||||
|
||||
if (options.noImplicitUseStrict && options.alwaysStrict) {
|
||||
if (options.noImplicitUseStrict && (options.alwaysStrict === undefined ? options.strict : options.alwaysStrict)) {
|
||||
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "noImplicitUseStrict", "alwaysStrict"));
|
||||
}
|
||||
|
||||
|
||||
@@ -333,7 +333,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function getLineStarts(sourceFile: SourceFile): number[] {
|
||||
export function getLineStarts(sourceFile: SourceFileLike): number[] {
|
||||
return sourceFile.lineMap || (sourceFile.lineMap = computeLineStarts(sourceFile.text));
|
||||
}
|
||||
|
||||
@@ -1716,7 +1716,14 @@ namespace ts {
|
||||
while (pos < end) {
|
||||
pos++;
|
||||
char = text.charCodeAt(pos);
|
||||
if ((char === CharacterCodes.openBrace) || (char === CharacterCodes.lessThan)) {
|
||||
if (char === CharacterCodes.openBrace) {
|
||||
break;
|
||||
}
|
||||
if (char === CharacterCodes.lessThan) {
|
||||
if (isConflictMarkerTrivia(text, pos)) {
|
||||
pos = scanConflictMarkerTrivia(text, pos, error);
|
||||
return token = SyntaxKind.ConflictMarkerTrivia;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-158
@@ -1,4 +1,4 @@
|
||||
/// <reference path="core.ts"/>
|
||||
/// <reference path="core.ts"/>
|
||||
|
||||
declare function setTimeout(handler: (...args: any[]) => void, timeout: number): any;
|
||||
declare function clearTimeout(handle: any): void;
|
||||
@@ -74,13 +74,6 @@ namespace ts {
|
||||
return parseInt(version.substring(1, dot));
|
||||
}
|
||||
|
||||
declare class Enumerator {
|
||||
public atEnd(): boolean;
|
||||
public moveNext(): boolean;
|
||||
public item(): any;
|
||||
constructor(o: any);
|
||||
}
|
||||
|
||||
declare var ChakraHost: {
|
||||
args: string[];
|
||||
currentDirectory: string;
|
||||
@@ -104,152 +97,6 @@ namespace ts {
|
||||
};
|
||||
|
||||
export let sys: System = (function() {
|
||||
|
||||
function getWScriptSystem(): System {
|
||||
|
||||
const fso = new ActiveXObject("Scripting.FileSystemObject");
|
||||
const shell = new ActiveXObject("WScript.Shell");
|
||||
|
||||
const fileStream = new ActiveXObject("ADODB.Stream");
|
||||
fileStream.Type = 2 /*text*/;
|
||||
|
||||
const binaryStream = new ActiveXObject("ADODB.Stream");
|
||||
binaryStream.Type = 1 /*binary*/;
|
||||
|
||||
const args: string[] = [];
|
||||
for (let i = 0; i < WScript.Arguments.length; i++) {
|
||||
args[i] = WScript.Arguments.Item(i);
|
||||
}
|
||||
|
||||
function readFile(fileName: string, encoding?: string): string {
|
||||
if (!fso.FileExists(fileName)) {
|
||||
return undefined;
|
||||
}
|
||||
fileStream.Open();
|
||||
try {
|
||||
if (encoding) {
|
||||
fileStream.Charset = encoding;
|
||||
fileStream.LoadFromFile(fileName);
|
||||
}
|
||||
else {
|
||||
// Load file and read the first two bytes into a string with no interpretation
|
||||
fileStream.Charset = "x-ansi";
|
||||
fileStream.LoadFromFile(fileName);
|
||||
const bom = fileStream.ReadText(2) || "";
|
||||
// Position must be at 0 before encoding can be changed
|
||||
fileStream.Position = 0;
|
||||
// [0xFF,0xFE] and [0xFE,0xFF] mean utf-16 (little or big endian), otherwise default to utf-8
|
||||
fileStream.Charset = bom.length >= 2 && (bom.charCodeAt(0) === 0xFF && bom.charCodeAt(1) === 0xFE || bom.charCodeAt(0) === 0xFE && bom.charCodeAt(1) === 0xFF) ? "unicode" : "utf-8";
|
||||
}
|
||||
// ReadText method always strips byte order mark from resulting string
|
||||
return fileStream.ReadText();
|
||||
}
|
||||
catch (e) {
|
||||
throw e;
|
||||
}
|
||||
finally {
|
||||
fileStream.Close();
|
||||
}
|
||||
}
|
||||
|
||||
function writeFile(fileName: string, data: string, writeByteOrderMark?: boolean): void {
|
||||
fileStream.Open();
|
||||
binaryStream.Open();
|
||||
try {
|
||||
// Write characters in UTF-8 encoding
|
||||
fileStream.Charset = "utf-8";
|
||||
fileStream.WriteText(data);
|
||||
// If we don't want the BOM, then skip it by setting the starting location to 3 (size of BOM).
|
||||
// If not, start from position 0, as the BOM will be added automatically when charset==utf8.
|
||||
if (writeByteOrderMark) {
|
||||
fileStream.Position = 0;
|
||||
}
|
||||
else {
|
||||
fileStream.Position = 3;
|
||||
}
|
||||
fileStream.CopyTo(binaryStream);
|
||||
binaryStream.SaveToFile(fileName, 2 /*overwrite*/);
|
||||
}
|
||||
finally {
|
||||
binaryStream.Close();
|
||||
fileStream.Close();
|
||||
}
|
||||
}
|
||||
|
||||
function getNames(collection: any): string[] {
|
||||
const result: string[] = [];
|
||||
for (const e = new Enumerator(collection); !e.atEnd(); e.moveNext()) {
|
||||
result.push(e.item().Name);
|
||||
}
|
||||
return result.sort();
|
||||
}
|
||||
|
||||
function getDirectories(path: string): string[] {
|
||||
const folder = fso.GetFolder(path);
|
||||
return getNames(folder.subfolders);
|
||||
}
|
||||
|
||||
function getAccessibleFileSystemEntries(path: string): FileSystemEntries {
|
||||
try {
|
||||
const folder = fso.GetFolder(path || ".");
|
||||
const files = getNames(folder.files);
|
||||
const directories = getNames(folder.subfolders);
|
||||
return { files, directories };
|
||||
}
|
||||
catch (e) {
|
||||
return { files: [], directories: [] };
|
||||
}
|
||||
}
|
||||
|
||||
function readDirectory(path: string, extensions?: string[], excludes?: string[], includes?: string[]): string[] {
|
||||
return matchFiles(path, extensions, excludes, includes, /*useCaseSensitiveFileNames*/ false, shell.CurrentDirectory, getAccessibleFileSystemEntries);
|
||||
}
|
||||
|
||||
const wscriptSystem: System = {
|
||||
args,
|
||||
newLine: "\r\n",
|
||||
useCaseSensitiveFileNames: false,
|
||||
write(s: string): void {
|
||||
WScript.StdOut.Write(s);
|
||||
},
|
||||
readFile,
|
||||
writeFile,
|
||||
resolvePath(path: string): string {
|
||||
return fso.GetAbsolutePathName(path);
|
||||
},
|
||||
fileExists(path: string): boolean {
|
||||
return fso.FileExists(path);
|
||||
},
|
||||
directoryExists(path: string) {
|
||||
return fso.FolderExists(path);
|
||||
},
|
||||
createDirectory(directoryName: string) {
|
||||
if (!wscriptSystem.directoryExists(directoryName)) {
|
||||
fso.CreateFolder(directoryName);
|
||||
}
|
||||
},
|
||||
getExecutingFilePath() {
|
||||
return WScript.ScriptFullName;
|
||||
},
|
||||
getCurrentDirectory() {
|
||||
return shell.CurrentDirectory;
|
||||
},
|
||||
getDirectories,
|
||||
getEnvironmentVariable(name: string) {
|
||||
return new ActiveXObject("WScript.Shell").ExpandEnvironmentStrings(`%${name}%`);
|
||||
},
|
||||
readDirectory,
|
||||
exit(exitCode?: number): void {
|
||||
try {
|
||||
WScript.Quit(exitCode);
|
||||
}
|
||||
catch (e) {
|
||||
}
|
||||
}
|
||||
};
|
||||
return wscriptSystem;
|
||||
}
|
||||
|
||||
function getNodeSystem(): System {
|
||||
const _fs = require("fs");
|
||||
const _path = require("path");
|
||||
@@ -355,7 +202,7 @@ namespace ts {
|
||||
if (len >= 2 && buffer[0] === 0xFE && buffer[1] === 0xFF) {
|
||||
// Big endian UTF-16 byte order mark detected. Since big endian is not supported by node.js,
|
||||
// flip all byte pairs and treat as little endian.
|
||||
len &= ~1;
|
||||
len &= ~1; // Round down to a multiple of 2
|
||||
for (let i = 0; i < len; i += 2) {
|
||||
const temp = buffer[i];
|
||||
buffer[i] = buffer[i + 1];
|
||||
@@ -646,9 +493,6 @@ namespace ts {
|
||||
if (typeof ChakraHost !== "undefined") {
|
||||
sys = getChakraSystem();
|
||||
}
|
||||
else if (typeof WScript !== "undefined" && typeof ActiveXObject === "function") {
|
||||
sys = getWScriptSystem();
|
||||
}
|
||||
else if (typeof process !== "undefined" && process.nextTick && !process.browser && typeof require !== "undefined") {
|
||||
// process and process.nextTick checks if current environment is node-like
|
||||
// process.browser check excludes webpack and browserify
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/// <reference path="visitor.ts" />
|
||||
/// <reference path="visitor.ts" />
|
||||
/// <reference path="transformers/ts.ts" />
|
||||
/// <reference path="transformers/jsx.ts" />
|
||||
/// <reference path="transformers/esnext.ts" />
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace ts {
|
||||
let value: Expression;
|
||||
if (isDestructuringAssignment(node)) {
|
||||
value = node.right;
|
||||
while (isEmptyObjectLiteralOrArrayLiteral(node.left)) {
|
||||
while (isEmptyArrayLiteral(node.left) || isEmptyObjectLiteral(node.left)) {
|
||||
if (isDestructuringAssignment(value)) {
|
||||
location = node = value;
|
||||
value = node.right;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/// <reference path="../factory.ts" />
|
||||
/// <reference path="../factory.ts" />
|
||||
/// <reference path="../visitor.ts" />
|
||||
|
||||
// Transforms generator functions into a compatible ES5 representation with similar runtime
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/// <reference path="../../factory.ts" />
|
||||
/// <reference path="../../factory.ts" />
|
||||
/// <reference path="../../visitor.ts" />
|
||||
/// <reference path="../destructuring.ts" />
|
||||
|
||||
@@ -55,9 +55,7 @@ namespace ts {
|
||||
* @param node The SourceFile node.
|
||||
*/
|
||||
function transformSourceFile(node: SourceFile) {
|
||||
if (isDeclarationFile(node)
|
||||
|| !(isExternalModule(node)
|
||||
|| compilerOptions.isolatedModules)) {
|
||||
if (isDeclarationFile(node) || !(isExternalModule(node) || compilerOptions.isolatedModules)) {
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -74,6 +72,14 @@ namespace ts {
|
||||
return aggregateTransformFlags(updated);
|
||||
}
|
||||
|
||||
|
||||
function shouldEmitUnderscoreUnderscoreESModule() {
|
||||
if (!currentModuleInfo.exportEquals && isExternalModule(currentSourceFile)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a SourceFile into a CommonJS module.
|
||||
*
|
||||
@@ -83,9 +89,10 @@ namespace ts {
|
||||
startLexicalEnvironment();
|
||||
|
||||
const statements: Statement[] = [];
|
||||
const statementOffset = addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict, sourceElementVisitor);
|
||||
const ensureUseStrict = compilerOptions.alwaysStrict || (!compilerOptions.noImplicitUseStrict && isExternalModule(currentSourceFile));
|
||||
const statementOffset = addPrologueDirectives(statements, node.statements, ensureUseStrict, sourceElementVisitor);
|
||||
|
||||
if (!currentModuleInfo.exportEquals) {
|
||||
if (shouldEmitUnderscoreUnderscoreESModule()) {
|
||||
append(statements, createUnderscoreUnderscoreESModule());
|
||||
}
|
||||
|
||||
@@ -378,7 +385,7 @@ namespace ts {
|
||||
const statements: Statement[] = [];
|
||||
const statementOffset = addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict, sourceElementVisitor);
|
||||
|
||||
if (!currentModuleInfo.exportEquals) {
|
||||
if (shouldEmitUnderscoreUnderscoreESModule()) {
|
||||
append(statements, createUnderscoreUnderscoreESModule());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/// <reference path="../../factory.ts" />
|
||||
/// <reference path="../../factory.ts" />
|
||||
/// <reference path="../../visitor.ts" />
|
||||
/// <reference path="../destructuring.ts" />
|
||||
|
||||
@@ -225,7 +225,8 @@ namespace ts {
|
||||
startLexicalEnvironment();
|
||||
|
||||
// Add any prologue directives.
|
||||
const statementOffset = addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict, sourceElementVisitor);
|
||||
const ensureUseStrict = compilerOptions.alwaysStrict || (!compilerOptions.noImplicitUseStrict && isExternalModule(currentSourceFile));
|
||||
const statementOffset = addPrologueDirectives(statements, node.statements, ensureUseStrict, sourceElementVisitor);
|
||||
|
||||
// var __moduleName = context_1 && context_1.id;
|
||||
statements.push(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/// <reference path="../factory.ts" />
|
||||
/// <reference path="../factory.ts" />
|
||||
/// <reference path="../visitor.ts" />
|
||||
/// <reference path="./destructuring.ts" />
|
||||
|
||||
@@ -472,7 +472,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
function visitSourceFile(node: SourceFile) {
|
||||
const alwaysStrict = compilerOptions.alwaysStrict && !(isExternalModule(node) && moduleKind === ModuleKind.ES2015);
|
||||
const alwaysStrict = (compilerOptions.alwaysStrict === undefined ? compilerOptions.strict : compilerOptions.alwaysStrict) &&
|
||||
!(isExternalModule(node) && moduleKind === ModuleKind.ES2015);
|
||||
return updateSourceFileNode(
|
||||
node,
|
||||
visitLexicalEnvironment(node.statements, sourceElementVisitor, context, /*start*/ 0, alwaysStrict));
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
/// <reference path="program.ts"/>
|
||||
/// <reference path="program.ts"/>
|
||||
/// <reference path="commandLineParser.ts"/>
|
||||
|
||||
namespace ts {
|
||||
|
||||
+37
-16
@@ -1,4 +1,4 @@
|
||||
namespace ts {
|
||||
namespace ts {
|
||||
/**
|
||||
* Type of objects whose values are all of the same type.
|
||||
* The `in` and `for-in` operators can *not* be safely used,
|
||||
@@ -519,6 +519,8 @@
|
||||
/* @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 {
|
||||
@@ -963,7 +965,6 @@
|
||||
|
||||
export interface Expression extends Node {
|
||||
_expressionBrand: any;
|
||||
contextualType?: Type; // Used to temporarily assign a contextual type during overload resolution
|
||||
}
|
||||
|
||||
export interface OmittedExpression extends Expression {
|
||||
@@ -1812,7 +1813,7 @@
|
||||
kind: SyntaxKind.ModuleDeclaration;
|
||||
parent?: ModuleBody | SourceFile;
|
||||
name: ModuleName;
|
||||
body?: ModuleBody | JSDocNamespaceDeclaration | Identifier;
|
||||
body?: ModuleBody | JSDocNamespaceDeclaration;
|
||||
}
|
||||
|
||||
export type NamespaceBody = ModuleBlock | NamespaceDeclaration;
|
||||
@@ -1837,6 +1838,11 @@
|
||||
|
||||
export type ModuleReference = EntityName | ExternalModuleReference;
|
||||
|
||||
/**
|
||||
* One of:
|
||||
* - import x = require("mod");
|
||||
* - import x = M.x;
|
||||
*/
|
||||
export interface ImportEqualsDeclaration extends DeclarationStatement {
|
||||
kind: SyntaxKind.ImportEqualsDeclaration;
|
||||
parent?: SourceFile | ModuleBlock;
|
||||
@@ -1888,7 +1894,6 @@
|
||||
export interface NamespaceExportDeclaration extends DeclarationStatement {
|
||||
kind: SyntaxKind.NamespaceExportDeclaration;
|
||||
name: Identifier;
|
||||
moduleReference: LiteralLikeNode;
|
||||
}
|
||||
|
||||
export interface ExportDeclaration extends DeclarationStatement {
|
||||
@@ -2204,6 +2209,16 @@
|
||||
name: string;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
/**
|
||||
* Subset of properties from SourceFile that are used in multiple utility functions
|
||||
*/
|
||||
export interface SourceFileLike {
|
||||
readonly text: string;
|
||||
lineMap: number[];
|
||||
}
|
||||
|
||||
|
||||
// Source files are declarations when they are external modules.
|
||||
export interface SourceFile extends Declaration {
|
||||
kind: SyntaxKind.SourceFile;
|
||||
@@ -2211,7 +2226,7 @@
|
||||
endOfFileToken: Token<SyntaxKind.EndOfFileToken>;
|
||||
|
||||
fileName: string;
|
||||
/* internal */ path: Path;
|
||||
/* @internal */ path: Path;
|
||||
text: string;
|
||||
|
||||
amdDependencies: AmdDependency[];
|
||||
@@ -2810,13 +2825,15 @@
|
||||
export const enum CheckFlags {
|
||||
Instantiated = 1 << 0, // Instantiated symbol
|
||||
SyntheticProperty = 1 << 1, // Property in union or intersection type
|
||||
Readonly = 1 << 2, // Readonly transient symbol
|
||||
Partial = 1 << 3, // Synthetic property present in some but not all constituents
|
||||
HasNonUniformType = 1 << 4, // Synthetic property with non-uniform type in constituents
|
||||
ContainsPublic = 1 << 5, // Synthetic property with public constituent(s)
|
||||
ContainsProtected = 1 << 6, // Synthetic property with protected constituent(s)
|
||||
ContainsPrivate = 1 << 7, // Synthetic property with private constituent(s)
|
||||
ContainsStatic = 1 << 8, // Synthetic property with static constituent(s)
|
||||
SyntheticMethod = 1 << 2, // Method in union or intersection type
|
||||
Readonly = 1 << 3, // Readonly transient symbol
|
||||
Partial = 1 << 4, // Synthetic property present in some but not all constituents
|
||||
HasNonUniformType = 1 << 5, // Synthetic property with non-uniform type in constituents
|
||||
ContainsPublic = 1 << 6, // Synthetic property with public constituent(s)
|
||||
ContainsProtected = 1 << 7, // Synthetic property with protected constituent(s)
|
||||
ContainsPrivate = 1 << 8, // Synthetic property with private constituent(s)
|
||||
ContainsStatic = 1 << 9, // Synthetic property with static constituent(s)
|
||||
Synthetic = SyntheticProperty | SyntheticMethod
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
@@ -3234,6 +3251,7 @@
|
||||
mapper?: TypeMapper; // Type mapper for this inference context
|
||||
failedTypeParameterIndex?: number; // Index of type parameter for which inference failed
|
||||
// It is optional because in contextual signature instantiation, nothing fails
|
||||
useAnyForNoInferences?: boolean; // Use any instead of {} for no inferences
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
@@ -3308,7 +3326,7 @@
|
||||
allowSyntheticDefaultImports?: boolean;
|
||||
allowUnreachableCode?: boolean;
|
||||
allowUnusedLabels?: boolean;
|
||||
alwaysStrict?: boolean;
|
||||
alwaysStrict?: boolean; // Always combine with strict property
|
||||
baseUrl?: string;
|
||||
charset?: string;
|
||||
/* @internal */ configFilePath?: string;
|
||||
@@ -3344,9 +3362,9 @@
|
||||
noEmitOnError?: boolean;
|
||||
noErrorTruncation?: boolean;
|
||||
noFallthroughCasesInSwitch?: boolean;
|
||||
noImplicitAny?: boolean;
|
||||
noImplicitAny?: boolean; // Always combine with strict property
|
||||
noImplicitReturns?: boolean;
|
||||
noImplicitThis?: boolean;
|
||||
noImplicitThis?: boolean; // Always combine with strict property
|
||||
noUnusedLocals?: boolean;
|
||||
noUnusedParameters?: boolean;
|
||||
noImplicitUseStrict?: boolean;
|
||||
@@ -3369,7 +3387,8 @@
|
||||
skipDefaultLibCheck?: boolean;
|
||||
sourceMap?: boolean;
|
||||
sourceRoot?: string;
|
||||
strictNullChecks?: boolean;
|
||||
strict?: boolean;
|
||||
strictNullChecks?: boolean; // Always combine with strict property
|
||||
/* @internal */ stripInternal?: boolean;
|
||||
suppressExcessPropertyErrors?: boolean;
|
||||
suppressImplicitAnyIndexErrors?: boolean;
|
||||
@@ -4129,6 +4148,8 @@
|
||||
/*@internal*/ onEmitSourceMapOfPosition?: (pos: number) => void;
|
||||
/*@internal*/ onEmitHelpers?: (node: Node, writeLines: (text: string) => void) => void;
|
||||
/*@internal*/ onSetSourceFile?: (node: SourceFile) => void;
|
||||
/*@internal*/ onBeforeEmitNodeArray?: (nodes: NodeArray<any>) => void;
|
||||
/*@internal*/ onAfterEmitNodeArray?: (nodes: NodeArray<any>) => void;
|
||||
}
|
||||
|
||||
export interface PrinterOptions {
|
||||
|
||||
+33
-15
@@ -1,4 +1,4 @@
|
||||
/// <reference path="sys.ts" />
|
||||
/// <reference path="sys.ts" />
|
||||
|
||||
/* @internal */
|
||||
namespace ts {
|
||||
@@ -184,7 +184,7 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
export function getStartPositionOfLine(line: number, sourceFile: SourceFile): number {
|
||||
export function getStartPositionOfLine(line: number, sourceFile: SourceFileLike): number {
|
||||
Debug.assert(line >= 0);
|
||||
return getLineStarts(sourceFile)[line];
|
||||
}
|
||||
@@ -204,7 +204,7 @@ namespace ts {
|
||||
return value !== undefined;
|
||||
}
|
||||
|
||||
export function getEndLinePosition(line: number, sourceFile: SourceFile): number {
|
||||
export function getEndLinePosition(line: number, sourceFile: SourceFileLike): number {
|
||||
Debug.assert(line >= 0);
|
||||
const lineStarts = getLineStarts(sourceFile);
|
||||
|
||||
@@ -255,7 +255,11 @@ namespace ts {
|
||||
return !nodeIsMissing(node);
|
||||
}
|
||||
|
||||
export function getTokenPosOfNode(node: Node, sourceFile?: SourceFile, includeJsDoc?: boolean): number {
|
||||
export function isToken(n: Node): boolean {
|
||||
return n.kind >= SyntaxKind.FirstToken && n.kind <= SyntaxKind.LastToken;
|
||||
}
|
||||
|
||||
export function getTokenPosOfNode(node: Node, sourceFile?: SourceFileLike, includeJsDoc?: boolean): number {
|
||||
// With nodes that have no width (i.e. 'Missing' nodes), we actually *don't*
|
||||
// want to skip trivia because this will launch us forward to the next token.
|
||||
if (nodeIsMissing(node)) {
|
||||
@@ -289,7 +293,7 @@ namespace ts {
|
||||
return node.kind >= SyntaxKind.FirstJSDocTagNode && node.kind <= SyntaxKind.LastJSDocTagNode;
|
||||
}
|
||||
|
||||
export function getNonDecoratorTokenPosOfNode(node: Node, sourceFile?: SourceFile): number {
|
||||
export function getNonDecoratorTokenPosOfNode(node: Node, sourceFile?: SourceFileLike): number {
|
||||
if (nodeIsMissing(node) || !node.decorators) {
|
||||
return getTokenPosOfNode(node, sourceFile);
|
||||
}
|
||||
@@ -1425,6 +1429,21 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
export function getRightMostAssignedExpression(node: Node) {
|
||||
while (isAssignmentExpression(node, /*excludeCompoundAssignements*/ true)) {
|
||||
node = node.right;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
export function isExportsIdentifier(node: Node) {
|
||||
return isIdentifier(node) && node.text === "exports";
|
||||
}
|
||||
|
||||
export function isModuleExportsPropertyAccessExpression(node: Node) {
|
||||
return isPropertyAccessExpression(node) && isIdentifier(node.expression) && node.expression.text === "module" && node.name.text === "exports";
|
||||
}
|
||||
|
||||
/// Given a BinaryExpression, returns SpecialPropertyAssignmentKind for the various kinds of property
|
||||
/// assignments we treat as special in the binder
|
||||
export function getSpecialPropertyAssignmentKind(expression: Node): SpecialPropertyAssignmentKind {
|
||||
@@ -2476,7 +2495,7 @@ namespace ts {
|
||||
return indentStrings[1].length;
|
||||
}
|
||||
|
||||
export function createTextWriter(newLine: String): EmitTextWriter {
|
||||
export function createTextWriter(newLine: string): EmitTextWriter {
|
||||
let output: string;
|
||||
let indent: number;
|
||||
let lineStart: boolean;
|
||||
@@ -3148,15 +3167,14 @@ namespace ts {
|
||||
(node.parent.kind === SyntaxKind.PropertyAccessExpression && (<PropertyAccessExpression>node.parent).name === node);
|
||||
}
|
||||
|
||||
export function isEmptyObjectLiteralOrArrayLiteral(expression: Node): boolean {
|
||||
const kind = expression.kind;
|
||||
if (kind === SyntaxKind.ObjectLiteralExpression) {
|
||||
return (<ObjectLiteralExpression>expression).properties.length === 0;
|
||||
}
|
||||
if (kind === SyntaxKind.ArrayLiteralExpression) {
|
||||
return (<ArrayLiteralExpression>expression).elements.length === 0;
|
||||
}
|
||||
return false;
|
||||
export function isEmptyObjectLiteral(expression: Node): boolean {
|
||||
return expression.kind === SyntaxKind.ObjectLiteralExpression &&
|
||||
(<ObjectLiteralExpression>expression).properties.length === 0;
|
||||
}
|
||||
|
||||
export function isEmptyArrayLiteral(expression: Node): boolean {
|
||||
return expression.kind === SyntaxKind.ArrayLiteralExpression &&
|
||||
(<ArrayLiteralExpression>expression).elements.length === 0;
|
||||
}
|
||||
|
||||
export function getLocalSymbolForExportDefault(symbol: Symbol) {
|
||||
|
||||
+76
-76
@@ -1,4 +1,4 @@
|
||||
/// <reference path="checker.ts" />
|
||||
/// <reference path="checker.ts" />
|
||||
/// <reference path="factory.ts" />
|
||||
/// <reference path="utilities.ts" />
|
||||
|
||||
@@ -154,9 +154,9 @@ namespace ts {
|
||||
* Starts a new lexical environment and visits a parameter list, suspending the lexical
|
||||
* environment upon completion.
|
||||
*/
|
||||
export function visitParameterList(nodes: NodeArray<ParameterDeclaration>, visitor: Visitor, context: TransformationContext) {
|
||||
export function visitParameterList(nodes: NodeArray<ParameterDeclaration>, visitor: Visitor, context: TransformationContext, nodesVisitor = visitNodes) {
|
||||
context.startLexicalEnvironment();
|
||||
const updated = visitNodes(nodes, visitor, isParameterDeclaration);
|
||||
const updated = nodesVisitor(nodes, visitor, isParameterDeclaration);
|
||||
context.suspendLexicalEnvironment();
|
||||
return updated;
|
||||
}
|
||||
@@ -204,9 +204,9 @@ namespace ts {
|
||||
* @param visitor The callback used to visit each child.
|
||||
* @param context A lexical environment context for the visitor.
|
||||
*/
|
||||
export function visitEachChild<T extends Node>(node: T | undefined, visitor: Visitor, context: TransformationContext): T | undefined;
|
||||
export function visitEachChild<T extends Node>(node: T | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: typeof visitNodes): T | undefined;
|
||||
|
||||
export function visitEachChild(node: Node, visitor: Visitor, context: TransformationContext): Node {
|
||||
export function visitEachChild(node: Node, visitor: Visitor, context: TransformationContext, nodesVisitor = visitNodes): Node {
|
||||
if (node === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -243,8 +243,8 @@ namespace ts {
|
||||
// Signature elements
|
||||
case SyntaxKind.Parameter:
|
||||
return updateParameter(<ParameterDeclaration>node,
|
||||
visitNodes((<ParameterDeclaration>node).decorators, visitor, isDecorator),
|
||||
visitNodes((<ParameterDeclaration>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<ParameterDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<ParameterDeclaration>node).modifiers, visitor, isModifier),
|
||||
(<ParameterDeclaration>node).dotDotDotToken,
|
||||
visitNode((<ParameterDeclaration>node).name, visitor, isBindingName),
|
||||
visitNode((<ParameterDeclaration>node).type, visitor, isTypeNode),
|
||||
@@ -257,55 +257,55 @@ namespace ts {
|
||||
// Type member
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
return updateProperty(<PropertyDeclaration>node,
|
||||
visitNodes((<PropertyDeclaration>node).decorators, visitor, isDecorator),
|
||||
visitNodes((<PropertyDeclaration>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<PropertyDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<PropertyDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<PropertyDeclaration>node).name, visitor, isPropertyName),
|
||||
visitNode((<PropertyDeclaration>node).type, visitor, isTypeNode),
|
||||
visitNode((<PropertyDeclaration>node).initializer, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
return updateMethod(<MethodDeclaration>node,
|
||||
visitNodes((<MethodDeclaration>node).decorators, visitor, isDecorator),
|
||||
visitNodes((<MethodDeclaration>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<MethodDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<MethodDeclaration>node).modifiers, visitor, isModifier),
|
||||
(<MethodDeclaration>node).asteriskToken,
|
||||
visitNode((<MethodDeclaration>node).name, visitor, isPropertyName),
|
||||
visitNodes((<MethodDeclaration>node).typeParameters, visitor, isTypeParameter),
|
||||
visitParameterList((<MethodDeclaration>node).parameters, visitor, context),
|
||||
nodesVisitor((<MethodDeclaration>node).typeParameters, visitor, isTypeParameter),
|
||||
visitParameterList((<MethodDeclaration>node).parameters, visitor, context, nodesVisitor),
|
||||
visitNode((<MethodDeclaration>node).type, visitor, isTypeNode),
|
||||
visitFunctionBody((<MethodDeclaration>node).body, visitor, context));
|
||||
|
||||
case SyntaxKind.Constructor:
|
||||
return updateConstructor(<ConstructorDeclaration>node,
|
||||
visitNodes((<ConstructorDeclaration>node).decorators, visitor, isDecorator),
|
||||
visitNodes((<ConstructorDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitParameterList((<ConstructorDeclaration>node).parameters, visitor, context),
|
||||
nodesVisitor((<ConstructorDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<ConstructorDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitParameterList((<ConstructorDeclaration>node).parameters, visitor, context, nodesVisitor),
|
||||
visitFunctionBody((<ConstructorDeclaration>node).body, visitor, context));
|
||||
|
||||
case SyntaxKind.GetAccessor:
|
||||
return updateGetAccessor(<GetAccessorDeclaration>node,
|
||||
visitNodes((<GetAccessorDeclaration>node).decorators, visitor, isDecorator),
|
||||
visitNodes((<GetAccessorDeclaration>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<GetAccessorDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<GetAccessorDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<GetAccessorDeclaration>node).name, visitor, isPropertyName),
|
||||
visitParameterList((<GetAccessorDeclaration>node).parameters, visitor, context),
|
||||
visitParameterList((<GetAccessorDeclaration>node).parameters, visitor, context, nodesVisitor),
|
||||
visitNode((<GetAccessorDeclaration>node).type, visitor, isTypeNode),
|
||||
visitFunctionBody((<GetAccessorDeclaration>node).body, visitor, context));
|
||||
|
||||
case SyntaxKind.SetAccessor:
|
||||
return updateSetAccessor(<SetAccessorDeclaration>node,
|
||||
visitNodes((<SetAccessorDeclaration>node).decorators, visitor, isDecorator),
|
||||
visitNodes((<SetAccessorDeclaration>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<SetAccessorDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<SetAccessorDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<SetAccessorDeclaration>node).name, visitor, isPropertyName),
|
||||
visitParameterList((<SetAccessorDeclaration>node).parameters, visitor, context),
|
||||
visitParameterList((<SetAccessorDeclaration>node).parameters, visitor, context, nodesVisitor),
|
||||
visitFunctionBody((<SetAccessorDeclaration>node).body, visitor, context));
|
||||
|
||||
// Binding patterns
|
||||
case SyntaxKind.ObjectBindingPattern:
|
||||
return updateObjectBindingPattern(<ObjectBindingPattern>node,
|
||||
visitNodes((<ObjectBindingPattern>node).elements, visitor, isBindingElement));
|
||||
nodesVisitor((<ObjectBindingPattern>node).elements, visitor, isBindingElement));
|
||||
|
||||
case SyntaxKind.ArrayBindingPattern:
|
||||
return updateArrayBindingPattern(<ArrayBindingPattern>node,
|
||||
visitNodes((<ArrayBindingPattern>node).elements, visitor, isArrayBindingElement));
|
||||
nodesVisitor((<ArrayBindingPattern>node).elements, visitor, isArrayBindingElement));
|
||||
|
||||
case SyntaxKind.BindingElement:
|
||||
return updateBindingElement(<BindingElement>node,
|
||||
@@ -317,11 +317,11 @@ namespace ts {
|
||||
// Expression
|
||||
case SyntaxKind.ArrayLiteralExpression:
|
||||
return updateArrayLiteral(<ArrayLiteralExpression>node,
|
||||
visitNodes((<ArrayLiteralExpression>node).elements, visitor, isExpression));
|
||||
nodesVisitor((<ArrayLiteralExpression>node).elements, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.ObjectLiteralExpression:
|
||||
return updateObjectLiteral(<ObjectLiteralExpression>node,
|
||||
visitNodes((<ObjectLiteralExpression>node).properties, visitor, isObjectLiteralElementLike));
|
||||
nodesVisitor((<ObjectLiteralExpression>node).properties, visitor, isObjectLiteralElementLike));
|
||||
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
return updatePropertyAccess(<PropertyAccessExpression>node,
|
||||
@@ -336,14 +336,14 @@ namespace ts {
|
||||
case SyntaxKind.CallExpression:
|
||||
return updateCall(<CallExpression>node,
|
||||
visitNode((<CallExpression>node).expression, visitor, isExpression),
|
||||
visitNodes((<CallExpression>node).typeArguments, visitor, isTypeNode),
|
||||
visitNodes((<CallExpression>node).arguments, visitor, isExpression));
|
||||
nodesVisitor((<CallExpression>node).typeArguments, visitor, isTypeNode),
|
||||
nodesVisitor((<CallExpression>node).arguments, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.NewExpression:
|
||||
return updateNew(<NewExpression>node,
|
||||
visitNode((<NewExpression>node).expression, visitor, isExpression),
|
||||
visitNodes((<NewExpression>node).typeArguments, visitor, isTypeNode),
|
||||
visitNodes((<NewExpression>node).arguments, visitor, isExpression));
|
||||
nodesVisitor((<NewExpression>node).typeArguments, visitor, isTypeNode),
|
||||
nodesVisitor((<NewExpression>node).arguments, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.TaggedTemplateExpression:
|
||||
return updateTaggedTemplate(<TaggedTemplateExpression>node,
|
||||
@@ -361,19 +361,19 @@ namespace ts {
|
||||
|
||||
case SyntaxKind.FunctionExpression:
|
||||
return updateFunctionExpression(<FunctionExpression>node,
|
||||
visitNodes((<FunctionExpression>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<FunctionExpression>node).modifiers, visitor, isModifier),
|
||||
(<FunctionExpression>node).asteriskToken,
|
||||
visitNode((<FunctionExpression>node).name, visitor, isIdentifier),
|
||||
visitNodes((<FunctionExpression>node).typeParameters, visitor, isTypeParameter),
|
||||
visitParameterList((<FunctionExpression>node).parameters, visitor, context),
|
||||
nodesVisitor((<FunctionExpression>node).typeParameters, visitor, isTypeParameter),
|
||||
visitParameterList((<FunctionExpression>node).parameters, visitor, context, nodesVisitor),
|
||||
visitNode((<FunctionExpression>node).type, visitor, isTypeNode),
|
||||
visitFunctionBody((<FunctionExpression>node).body, visitor, context));
|
||||
|
||||
case SyntaxKind.ArrowFunction:
|
||||
return updateArrowFunction(<ArrowFunction>node,
|
||||
visitNodes((<ArrowFunction>node).modifiers, visitor, isModifier),
|
||||
visitNodes((<ArrowFunction>node).typeParameters, visitor, isTypeParameter),
|
||||
visitParameterList((<ArrowFunction>node).parameters, visitor, context),
|
||||
nodesVisitor((<ArrowFunction>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<ArrowFunction>node).typeParameters, visitor, isTypeParameter),
|
||||
visitParameterList((<ArrowFunction>node).parameters, visitor, context, nodesVisitor),
|
||||
visitNode((<ArrowFunction>node).type, visitor, isTypeNode),
|
||||
visitFunctionBody((<ArrowFunction>node).body, visitor, context));
|
||||
|
||||
@@ -415,7 +415,7 @@ namespace ts {
|
||||
case SyntaxKind.TemplateExpression:
|
||||
return updateTemplateExpression(<TemplateExpression>node,
|
||||
visitNode((<TemplateExpression>node).head, visitor, isTemplateHead),
|
||||
visitNodes((<TemplateExpression>node).templateSpans, visitor, isTemplateSpan));
|
||||
nodesVisitor((<TemplateExpression>node).templateSpans, visitor, isTemplateSpan));
|
||||
|
||||
case SyntaxKind.YieldExpression:
|
||||
return updateYield(<YieldExpression>node,
|
||||
@@ -428,15 +428,15 @@ namespace ts {
|
||||
|
||||
case SyntaxKind.ClassExpression:
|
||||
return updateClassExpression(<ClassExpression>node,
|
||||
visitNodes((<ClassExpression>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<ClassExpression>node).modifiers, visitor, isModifier),
|
||||
visitNode((<ClassExpression>node).name, visitor, isIdentifier),
|
||||
visitNodes((<ClassExpression>node).typeParameters, visitor, isTypeParameter),
|
||||
visitNodes((<ClassExpression>node).heritageClauses, visitor, isHeritageClause),
|
||||
visitNodes((<ClassExpression>node).members, visitor, isClassElement));
|
||||
nodesVisitor((<ClassExpression>node).typeParameters, visitor, isTypeParameter),
|
||||
nodesVisitor((<ClassExpression>node).heritageClauses, visitor, isHeritageClause),
|
||||
nodesVisitor((<ClassExpression>node).members, visitor, isClassElement));
|
||||
|
||||
case SyntaxKind.ExpressionWithTypeArguments:
|
||||
return updateExpressionWithTypeArguments(<ExpressionWithTypeArguments>node,
|
||||
visitNodes((<ExpressionWithTypeArguments>node).typeArguments, visitor, isTypeNode),
|
||||
nodesVisitor((<ExpressionWithTypeArguments>node).typeArguments, visitor, isTypeNode),
|
||||
visitNode((<ExpressionWithTypeArguments>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.AsExpression:
|
||||
@@ -457,11 +457,11 @@ namespace ts {
|
||||
// Element
|
||||
case SyntaxKind.Block:
|
||||
return updateBlock(<Block>node,
|
||||
visitNodes((<Block>node).statements, visitor, isStatement));
|
||||
nodesVisitor((<Block>node).statements, visitor, isStatement));
|
||||
|
||||
case SyntaxKind.VariableStatement:
|
||||
return updateVariableStatement(<VariableStatement>node,
|
||||
visitNodes((<VariableStatement>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<VariableStatement>node).modifiers, visitor, isModifier),
|
||||
visitNode((<VariableStatement>node).declarationList, visitor, isVariableDeclarationList));
|
||||
|
||||
case SyntaxKind.ExpressionStatement:
|
||||
@@ -549,61 +549,61 @@ namespace ts {
|
||||
|
||||
case SyntaxKind.VariableDeclarationList:
|
||||
return updateVariableDeclarationList(<VariableDeclarationList>node,
|
||||
visitNodes((<VariableDeclarationList>node).declarations, visitor, isVariableDeclaration));
|
||||
nodesVisitor((<VariableDeclarationList>node).declarations, visitor, isVariableDeclaration));
|
||||
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
return updateFunctionDeclaration(<FunctionDeclaration>node,
|
||||
visitNodes((<FunctionDeclaration>node).decorators, visitor, isDecorator),
|
||||
visitNodes((<FunctionDeclaration>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<FunctionDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<FunctionDeclaration>node).modifiers, visitor, isModifier),
|
||||
(<FunctionDeclaration>node).asteriskToken,
|
||||
visitNode((<FunctionDeclaration>node).name, visitor, isIdentifier),
|
||||
visitNodes((<FunctionDeclaration>node).typeParameters, visitor, isTypeParameter),
|
||||
visitParameterList((<FunctionDeclaration>node).parameters, visitor, context),
|
||||
nodesVisitor((<FunctionDeclaration>node).typeParameters, visitor, isTypeParameter),
|
||||
visitParameterList((<FunctionDeclaration>node).parameters, visitor, context, nodesVisitor),
|
||||
visitNode((<FunctionDeclaration>node).type, visitor, isTypeNode),
|
||||
visitFunctionBody((<FunctionExpression>node).body, visitor, context));
|
||||
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
return updateClassDeclaration(<ClassDeclaration>node,
|
||||
visitNodes((<ClassDeclaration>node).decorators, visitor, isDecorator),
|
||||
visitNodes((<ClassDeclaration>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<ClassDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<ClassDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<ClassDeclaration>node).name, visitor, isIdentifier),
|
||||
visitNodes((<ClassDeclaration>node).typeParameters, visitor, isTypeParameter),
|
||||
visitNodes((<ClassDeclaration>node).heritageClauses, visitor, isHeritageClause),
|
||||
visitNodes((<ClassDeclaration>node).members, visitor, isClassElement));
|
||||
nodesVisitor((<ClassDeclaration>node).typeParameters, visitor, isTypeParameter),
|
||||
nodesVisitor((<ClassDeclaration>node).heritageClauses, visitor, isHeritageClause),
|
||||
nodesVisitor((<ClassDeclaration>node).members, visitor, isClassElement));
|
||||
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
return updateEnumDeclaration(<EnumDeclaration>node,
|
||||
visitNodes((<EnumDeclaration>node).decorators, visitor, isDecorator),
|
||||
visitNodes((<EnumDeclaration>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<EnumDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<EnumDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<EnumDeclaration>node).name, visitor, isIdentifier),
|
||||
visitNodes((<EnumDeclaration>node).members, visitor, isEnumMember));
|
||||
nodesVisitor((<EnumDeclaration>node).members, visitor, isEnumMember));
|
||||
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
return updateModuleDeclaration(<ModuleDeclaration>node,
|
||||
visitNodes((<ModuleDeclaration>node).decorators, visitor, isDecorator),
|
||||
visitNodes((<ModuleDeclaration>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<ModuleDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<ModuleDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<ModuleDeclaration>node).name, visitor, isIdentifier),
|
||||
visitNode((<ModuleDeclaration>node).body, visitor, isModuleBody));
|
||||
|
||||
case SyntaxKind.ModuleBlock:
|
||||
return updateModuleBlock(<ModuleBlock>node,
|
||||
visitNodes((<ModuleBlock>node).statements, visitor, isStatement));
|
||||
nodesVisitor((<ModuleBlock>node).statements, visitor, isStatement));
|
||||
|
||||
case SyntaxKind.CaseBlock:
|
||||
return updateCaseBlock(<CaseBlock>node,
|
||||
visitNodes((<CaseBlock>node).clauses, visitor, isCaseOrDefaultClause));
|
||||
nodesVisitor((<CaseBlock>node).clauses, visitor, isCaseOrDefaultClause));
|
||||
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
return updateImportEqualsDeclaration(<ImportEqualsDeclaration>node,
|
||||
visitNodes((<ImportEqualsDeclaration>node).decorators, visitor, isDecorator),
|
||||
visitNodes((<ImportEqualsDeclaration>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<ImportEqualsDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<ImportEqualsDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<ImportEqualsDeclaration>node).name, visitor, isIdentifier),
|
||||
visitNode((<ImportEqualsDeclaration>node).moduleReference, visitor, isModuleReference));
|
||||
|
||||
case SyntaxKind.ImportDeclaration:
|
||||
return updateImportDeclaration(<ImportDeclaration>node,
|
||||
visitNodes((<ImportDeclaration>node).decorators, visitor, isDecorator),
|
||||
visitNodes((<ImportDeclaration>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<ImportDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<ImportDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<ImportDeclaration>node).importClause, visitor, isImportClause),
|
||||
visitNode((<ImportDeclaration>node).moduleSpecifier, visitor, isExpression));
|
||||
|
||||
@@ -618,7 +618,7 @@ namespace ts {
|
||||
|
||||
case SyntaxKind.NamedImports:
|
||||
return updateNamedImports(<NamedImports>node,
|
||||
visitNodes((<NamedImports>node).elements, visitor, isImportSpecifier));
|
||||
nodesVisitor((<NamedImports>node).elements, visitor, isImportSpecifier));
|
||||
|
||||
case SyntaxKind.ImportSpecifier:
|
||||
return updateImportSpecifier(<ImportSpecifier>node,
|
||||
@@ -627,20 +627,20 @@ namespace ts {
|
||||
|
||||
case SyntaxKind.ExportAssignment:
|
||||
return updateExportAssignment(<ExportAssignment>node,
|
||||
visitNodes((<ExportAssignment>node).decorators, visitor, isDecorator),
|
||||
visitNodes((<ExportAssignment>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<ExportAssignment>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<ExportAssignment>node).modifiers, visitor, isModifier),
|
||||
visitNode((<ExportAssignment>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.ExportDeclaration:
|
||||
return updateExportDeclaration(<ExportDeclaration>node,
|
||||
visitNodes((<ExportDeclaration>node).decorators, visitor, isDecorator),
|
||||
visitNodes((<ExportDeclaration>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<ExportDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<ExportDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<ExportDeclaration>node).exportClause, visitor, isNamedExports),
|
||||
visitNode((<ExportDeclaration>node).moduleSpecifier, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.NamedExports:
|
||||
return updateNamedExports(<NamedExports>node,
|
||||
visitNodes((<NamedExports>node).elements, visitor, isExportSpecifier));
|
||||
nodesVisitor((<NamedExports>node).elements, visitor, isExportSpecifier));
|
||||
|
||||
case SyntaxKind.ExportSpecifier:
|
||||
return updateExportSpecifier(<ExportSpecifier>node,
|
||||
@@ -656,12 +656,12 @@ namespace ts {
|
||||
case SyntaxKind.JsxElement:
|
||||
return updateJsxElement(<JsxElement>node,
|
||||
visitNode((<JsxElement>node).openingElement, visitor, isJsxOpeningElement),
|
||||
visitNodes((<JsxElement>node).children, visitor, isJsxChild),
|
||||
nodesVisitor((<JsxElement>node).children, visitor, isJsxChild),
|
||||
visitNode((<JsxElement>node).closingElement, visitor, isJsxClosingElement));
|
||||
|
||||
case SyntaxKind.JsxAttributes:
|
||||
return updateJsxAttributes(<JsxAttributes>node,
|
||||
visitNodes((<JsxAttributes>node).properties, visitor, isJsxAttributeLike));
|
||||
nodesVisitor((<JsxAttributes>node).properties, visitor, isJsxAttributeLike));
|
||||
|
||||
case SyntaxKind.JsxSelfClosingElement:
|
||||
return updateJsxSelfClosingElement(<JsxSelfClosingElement>node,
|
||||
@@ -694,15 +694,15 @@ namespace ts {
|
||||
case SyntaxKind.CaseClause:
|
||||
return updateCaseClause(<CaseClause>node,
|
||||
visitNode((<CaseClause>node).expression, visitor, isExpression),
|
||||
visitNodes((<CaseClause>node).statements, visitor, isStatement));
|
||||
nodesVisitor((<CaseClause>node).statements, visitor, isStatement));
|
||||
|
||||
case SyntaxKind.DefaultClause:
|
||||
return updateDefaultClause(<DefaultClause>node,
|
||||
visitNodes((<DefaultClause>node).statements, visitor, isStatement));
|
||||
nodesVisitor((<DefaultClause>node).statements, visitor, isStatement));
|
||||
|
||||
case SyntaxKind.HeritageClause:
|
||||
return updateHeritageClause(<HeritageClause>node,
|
||||
visitNodes((<HeritageClause>node).types, visitor, isExpressionWithTypeArguments));
|
||||
nodesVisitor((<HeritageClause>node).types, visitor, isExpressionWithTypeArguments));
|
||||
|
||||
case SyntaxKind.CatchClause:
|
||||
return updateCatchClause(<CatchClause>node,
|
||||
|
||||
+47
-13
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -22,6 +22,10 @@
|
||||
namespace FourSlash {
|
||||
ts.disableIncrementalParsing = false;
|
||||
|
||||
function normalizeNewLines(s: string) {
|
||||
return s.replace(/\r\n/g, "\n");
|
||||
}
|
||||
|
||||
// Represents a parsed source file with metadata
|
||||
export interface FourSlashFile {
|
||||
// The contents of the file (with markers, etc stripped out)
|
||||
@@ -923,10 +927,13 @@ namespace FourSlash {
|
||||
this.assertObjectsEqual<ReferencesJson>(fullActual, fullExpected);
|
||||
}
|
||||
|
||||
function rangeToReferenceEntry(r: Range) {
|
||||
let { isWriteAccess, isDefinition } = (r.marker && r.marker.data) || { isWriteAccess: false, isDefinition: false };
|
||||
isWriteAccess = !!isWriteAccess; isDefinition = !!isDefinition;
|
||||
return { fileName: r.fileName, textSpan: { start: r.start, length: r.end - r.start }, isWriteAccess, isDefinition };
|
||||
function rangeToReferenceEntry(r: Range): ts.ReferenceEntry {
|
||||
const { isWriteAccess, isDefinition, isInString } = (r.marker && r.marker.data) || { isWriteAccess: false, isDefinition: false, isInString: undefined };
|
||||
const result: ts.ReferenceEntry = { fileName: r.fileName, textSpan: { start: r.start, length: r.end - r.start }, isWriteAccess: !!isWriteAccess, isDefinition: !!isDefinition };
|
||||
if (isInString !== undefined) {
|
||||
result.isInString = isInString;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1851,17 +1858,41 @@ namespace FourSlash {
|
||||
|
||||
const unsatisfiedRanges: Range[] = [];
|
||||
|
||||
const delayedErrors: string[] = [];
|
||||
for (const range of ranges) {
|
||||
const length = range.end - range.start;
|
||||
const matchingImpl = ts.find(implementations, impl =>
|
||||
range.fileName === impl.fileName && range.start === impl.textSpan.start && length === impl.textSpan.length);
|
||||
if (matchingImpl) {
|
||||
if (range.marker && range.marker.data) {
|
||||
const expected = <{ displayParts?: ts.SymbolDisplayPart[], parts: string[], kind?: string }>range.marker.data;
|
||||
if (expected.displayParts) {
|
||||
if (!ts.arrayIsEqualTo(expected.displayParts, matchingImpl.displayParts, displayPartIsEqualTo)) {
|
||||
delayedErrors.push(`Mismatched display parts: expected ${JSON.stringify(expected.displayParts)}, actual ${JSON.stringify(matchingImpl.displayParts)}`);
|
||||
}
|
||||
}
|
||||
else if (expected.parts) {
|
||||
const actualParts = matchingImpl.displayParts.map(p => p.text);
|
||||
if (!ts.arrayIsEqualTo(expected.parts, actualParts)) {
|
||||
delayedErrors.push(`Mismatched non-tagged display parts: expected ${JSON.stringify(expected.parts)}, actual ${JSON.stringify(actualParts)}`);
|
||||
}
|
||||
}
|
||||
if (expected.kind !== undefined) {
|
||||
if (expected.kind !== matchingImpl.kind) {
|
||||
delayedErrors.push(`Mismatched kind: expected ${JSON.stringify(expected.kind)}, actual ${JSON.stringify(matchingImpl.kind)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
matchingImpl.matched = true;
|
||||
}
|
||||
else {
|
||||
unsatisfiedRanges.push(range);
|
||||
}
|
||||
}
|
||||
if (delayedErrors.length) {
|
||||
this.raiseError(delayedErrors.join("\n"));
|
||||
}
|
||||
|
||||
const unmatchedImplementations = implementations.filter(impl => !impl.matched);
|
||||
if (unmatchedImplementations.length || unsatisfiedRanges.length) {
|
||||
@@ -1886,6 +1917,10 @@ namespace FourSlash {
|
||||
function implementationsAreEqual(a: ImplementationLocationInformation, b: ImplementationLocationInformation) {
|
||||
return a.fileName === b.fileName && TestState.textSpansEqual(a.textSpan, b.textSpan);
|
||||
}
|
||||
|
||||
function displayPartIsEqualTo(a: ts.SymbolDisplayPart, b: ts.SymbolDisplayPart): boolean {
|
||||
return a.kind === b.kind && a.text === b.text;
|
||||
}
|
||||
}
|
||||
|
||||
public getMarkers(): Marker[] {
|
||||
@@ -1958,8 +1993,7 @@ namespace FourSlash {
|
||||
|
||||
public verifyCurrentFileContent(text: string) {
|
||||
const actual = this.getFileContent(this.activeFile.fileName);
|
||||
const replaceNewlines = (str: string) => str.replace(/\r\n/g, "\n");
|
||||
if (replaceNewlines(actual) !== replaceNewlines(text)) {
|
||||
if (normalizeNewLines(actual) !== normalizeNewLines(text)) {
|
||||
throw new Error("verifyCurrentFileContent\n" +
|
||||
"\tExpected: \"" + text + "\"\n" +
|
||||
"\t Actual: \"" + actual + "\"");
|
||||
@@ -2135,7 +2169,7 @@ namespace FourSlash {
|
||||
const actualText = this.rangeText(ranges[0]);
|
||||
|
||||
const result = includeWhiteSpace
|
||||
? actualText === expectedText
|
||||
? normalizeNewLines(actualText) === normalizeNewLines(expectedText)
|
||||
: this.removeWhitespace(actualText) === this.removeWhitespace(expectedText);
|
||||
|
||||
if (!result) {
|
||||
@@ -2185,7 +2219,7 @@ namespace FourSlash {
|
||||
continue;
|
||||
}
|
||||
|
||||
const newActions = this.languageService.getCodeFixesAtPosition(fileName, diagnostic.start, diagnostic.length, [diagnostic.code]);
|
||||
const newActions = this.languageService.getCodeFixesAtPosition(fileName, diagnostic.start, diagnostic.length, [diagnostic.code], this.formatCodeSettings);
|
||||
if (newActions && newActions.length) {
|
||||
actions = actions ? actions.concat(newActions) : newActions;
|
||||
}
|
||||
@@ -2248,22 +2282,22 @@ namespace FourSlash {
|
||||
|
||||
if (expected === undefined) {
|
||||
if (actual) {
|
||||
this.raiseError(name + " failed - expected no template but got {newText: \"" + actual.newText + "\" caretOffset: " + actual.caretOffset + "}");
|
||||
this.raiseError(`${name} failed - expected no template but got {newText: "${actual.newText}", caretOffset: ${actual.caretOffset}}`);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (actual === undefined) {
|
||||
this.raiseError(name + " failed - expected the template {newText: \"" + actual.newText + "\" caretOffset: " + actual.caretOffset + "} but got nothing instead");
|
||||
this.raiseError(`${name} failed - expected the template {newText: "${expected.newText}", caretOffset: "${expected.caretOffset}"} but got nothing instead`);
|
||||
}
|
||||
|
||||
if (actual.newText !== expected.newText) {
|
||||
this.raiseError(name + " failed - expected insertion:\n" + this.clarifyNewlines(expected.newText) + "\nactual insertion:\n" + this.clarifyNewlines(actual.newText));
|
||||
this.raiseError(`${name} failed - expected insertion:\n"${this.clarifyNewlines(expected.newText)}"\nactual insertion:\n"${this.clarifyNewlines(actual.newText)}"`);
|
||||
}
|
||||
|
||||
if (actual.caretOffset !== expected.caretOffset) {
|
||||
this.raiseError(name + " failed - expected caretOffset: " + expected.caretOffset + ",\nactual caretOffset:" + actual.caretOffset);
|
||||
this.raiseError(`${name} failed - expected caretOffset: ${expected.caretOffset}\nactual caretOffset:${actual.caretOffset}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-94
@@ -34,12 +34,6 @@ var _chai: typeof chai = require("chai");
|
||||
var assert: typeof _chai.assert = _chai.assert;
|
||||
declare var __dirname: string; // Node-specific
|
||||
var global: NodeJS.Global = <any>Function("return this").call(undefined);
|
||||
declare namespace NodeJS {
|
||||
export interface Global {
|
||||
WScript: typeof WScript;
|
||||
ActiveXObject: typeof ActiveXObject;
|
||||
}
|
||||
}
|
||||
|
||||
declare var window: {};
|
||||
declare var XMLHttpRequest: {
|
||||
@@ -60,14 +54,10 @@ namespace Utils {
|
||||
export const enum ExecutionEnvironment {
|
||||
Node,
|
||||
Browser,
|
||||
CScript
|
||||
}
|
||||
|
||||
export function getExecutionEnvironment() {
|
||||
if (typeof WScript !== "undefined" && typeof ActiveXObject === "function") {
|
||||
return ExecutionEnvironment.CScript;
|
||||
}
|
||||
else if (typeof window !== "undefined") {
|
||||
if (typeof window !== "undefined") {
|
||||
return ExecutionEnvironment.Browser;
|
||||
}
|
||||
else {
|
||||
@@ -93,7 +83,6 @@ namespace Utils {
|
||||
export function evalFile(fileContents: string, fileName: string, nodeContext?: any) {
|
||||
const environment = getExecutionEnvironment();
|
||||
switch (environment) {
|
||||
case ExecutionEnvironment.CScript:
|
||||
case ExecutionEnvironment.Browser:
|
||||
eval(fileContents);
|
||||
break;
|
||||
@@ -516,83 +505,6 @@ namespace Harness {
|
||||
export const virtualFileSystemRoot = "/";
|
||||
|
||||
namespace IOImpl {
|
||||
declare class Enumerator {
|
||||
public atEnd(): boolean;
|
||||
public moveNext(): boolean;
|
||||
public item(): any;
|
||||
constructor(o: any);
|
||||
}
|
||||
|
||||
export namespace CScript {
|
||||
let fso: any;
|
||||
if (global.ActiveXObject) {
|
||||
fso = new global.ActiveXObject("Scripting.FileSystemObject");
|
||||
}
|
||||
else {
|
||||
fso = {};
|
||||
}
|
||||
|
||||
export const args = () => ts.sys.args;
|
||||
export const getExecutingFilePath = () => ts.sys.getExecutingFilePath();
|
||||
export const exit = (exitCode: number) => ts.sys.exit(exitCode);
|
||||
export const resolvePath = (path: string) => ts.sys.resolvePath(path);
|
||||
export const getCurrentDirectory = () => ts.sys.getCurrentDirectory();
|
||||
export const newLine = () => harnessNewLine;
|
||||
export const useCaseSensitiveFileNames = () => ts.sys.useCaseSensitiveFileNames;
|
||||
|
||||
export const readFile: typeof IO.readFile = path => ts.sys.readFile(path);
|
||||
export const writeFile: typeof IO.writeFile = (path, content) => ts.sys.writeFile(path, content);
|
||||
export const directoryName: typeof IO.directoryName = fso.GetParentFolderName;
|
||||
export const getDirectories: typeof IO.getDirectories = dir => ts.sys.getDirectories(dir);
|
||||
export const directoryExists: typeof IO.directoryExists = fso.FolderExists;
|
||||
export const fileExists: typeof IO.fileExists = fso.FileExists;
|
||||
export const log: typeof IO.log = global.WScript && global.WScript.StdOut.WriteLine;
|
||||
export const getEnvironmentVariable: typeof IO.getEnvironmentVariable = name => ts.sys.getEnvironmentVariable(name);
|
||||
export const readDirectory: typeof IO.readDirectory = (path, extension, exclude, include) => ts.sys.readDirectory(path, extension, exclude, include);
|
||||
|
||||
export function createDirectory(path: string) {
|
||||
if (directoryExists(path)) {
|
||||
fso.CreateFolder(path);
|
||||
}
|
||||
}
|
||||
|
||||
export function deleteFile(path: string) {
|
||||
if (fileExists(path)) {
|
||||
fso.DeleteFile(path, true); // true: delete read-only files
|
||||
}
|
||||
}
|
||||
|
||||
export let listFiles: typeof IO.listFiles = (path, spec?, options?) => {
|
||||
options = options || <{ recursive?: boolean; }>{};
|
||||
function filesInFolder(folder: any, root: string): string[] {
|
||||
let paths: string[] = [];
|
||||
let fc: any;
|
||||
|
||||
if (options.recursive) {
|
||||
fc = new Enumerator(folder.subfolders);
|
||||
|
||||
for (; !fc.atEnd(); fc.moveNext()) {
|
||||
paths = paths.concat(filesInFolder(fc.item(), root + "\\" + fc.item().Name));
|
||||
}
|
||||
}
|
||||
|
||||
fc = new Enumerator(folder.files);
|
||||
|
||||
for (; !fc.atEnd(); fc.moveNext()) {
|
||||
if (!spec || fc.item().Name.match(spec)) {
|
||||
paths.push(root + "\\" + fc.item().Name);
|
||||
}
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
const folder: any = fso.GetFolder(path);
|
||||
|
||||
return filesInFolder(folder, path);
|
||||
};
|
||||
}
|
||||
|
||||
export namespace Node {
|
||||
declare const require: any;
|
||||
let fs: any, pathModule: any;
|
||||
@@ -840,16 +752,16 @@ namespace Harness {
|
||||
}
|
||||
}
|
||||
|
||||
switch (Utils.getExecutionEnvironment()) {
|
||||
case Utils.ExecutionEnvironment.CScript:
|
||||
IO = IOImpl.CScript;
|
||||
break;
|
||||
const environment = Utils.getExecutionEnvironment();
|
||||
switch (environment) {
|
||||
case Utils.ExecutionEnvironment.Node:
|
||||
IO = IOImpl.Node;
|
||||
break;
|
||||
case Utils.ExecutionEnvironment.Browser:
|
||||
IO = IOImpl.Network;
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unknown value '${environment}' for ExecutionEnvironment.`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -873,7 +785,7 @@ namespace Harness {
|
||||
/** Aggregate various writes into a single array of lines. Useful for passing to the
|
||||
* TypeScript compiler to fill with source code or errors.
|
||||
*/
|
||||
export class WriterAggregator implements ITextWriter {
|
||||
export class WriterAggregator {
|
||||
public lines: string[] = [];
|
||||
public currentLine = <string>undefined;
|
||||
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
"declaration": false,
|
||||
"types": [
|
||||
"node", "mocha", "chai"
|
||||
],
|
||||
"lib": [
|
||||
"es6",
|
||||
"scripthost"
|
||||
]
|
||||
},
|
||||
"files": [
|
||||
@@ -121,6 +125,7 @@
|
||||
"./unittests/projectErrors.ts",
|
||||
"./unittests/printer.ts",
|
||||
"./unittests/transform.ts",
|
||||
"./unittests/customTransforms.ts"
|
||||
"./unittests/customTransforms.ts",
|
||||
"./unittests/textChanges.ts"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/// <reference path="..\harness.ts" />
|
||||
/// <reference path="..\harness.ts" />
|
||||
|
||||
namespace ts {
|
||||
interface File {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/// <reference path="..\harness.ts" />
|
||||
/// <reference path="..\harness.ts" />
|
||||
/// <reference path="..\..\compiler\commandLineParser.ts" />
|
||||
|
||||
namespace ts {
|
||||
|
||||
@@ -45,6 +45,9 @@ namespace ts {
|
||||
|
||||
// comment9
|
||||
console.log(1 + 2);
|
||||
|
||||
// comment10
|
||||
function functionWithDefaultArgValue(argument: string = "defaultValue"): void { }
|
||||
`, ScriptTarget.ES2015);
|
||||
|
||||
printsCorrectly("default", {}, printer => printer.printFile(sourceFile));
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/// <reference path="..\harness.ts" />
|
||||
/// <reference path="..\harness.ts" />
|
||||
/// <reference path="..\..\harness\harnessLanguageService.ts" />
|
||||
|
||||
namespace ts {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/// <reference path="..\..\harnessLanguageService.ts" />
|
||||
/// <reference path="..\..\harnessLanguageService.ts" />
|
||||
|
||||
interface ClassificationEntry {
|
||||
value: any;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
///<reference path='_project.ts'/>
|
||||
///<reference path='_project.ts'/>
|
||||
|
||||
describe('getFormattingEditsForRange', function() {
|
||||
//
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/// <reference path="..\..\harnessLanguageService.ts" />
|
||||
/// <reference path="..\..\harnessLanguageService.ts" />
|
||||
|
||||
describe("PreProcessFile:", function () {
|
||||
function test(sourceText: string, readImportFile: boolean, detectJavaScriptImports: boolean, expectedPreProcess: ts.PreProcessedFileInfo): void {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/// <reference path="..\harness.ts" />
|
||||
/// <reference path="..\harness.ts" />
|
||||
|
||||
const expect: typeof _chai.expect = _chai.expect;
|
||||
|
||||
|
||||
@@ -0,0 +1,794 @@
|
||||
/// <reference path="..\..\compiler\emitter.ts" />
|
||||
/// <reference path="..\..\services\textChanges.ts" />
|
||||
/// <reference path="..\harness.ts" />
|
||||
|
||||
// Some tests have trailing whitespace
|
||||
// tslint:disable trim-trailing-whitespace
|
||||
|
||||
namespace ts {
|
||||
describe("textChanges", () => {
|
||||
function findChild(name: string, n: Node) {
|
||||
return find(n);
|
||||
|
||||
function find(node: Node): Node {
|
||||
if (isDeclaration(node) && node.name && isIdentifier(node.name) && node.name.text === name) {
|
||||
return node;
|
||||
}
|
||||
else {
|
||||
return forEachChild(node, find);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const printerOptions = { newLine: NewLineKind.LineFeed };
|
||||
const newLineCharacter = getNewLineCharacter(printerOptions);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// validate that positions that were recovered from the printed text actually match positions that will be created if the same text is parsed.
|
||||
function verifyPositions({ text, node }: textChanges.NonFormattedText): void {
|
||||
const nodeList = flattenNodes(node);
|
||||
const sourceFile = createSourceFile("f.ts", text, ScriptTarget.ES2015);
|
||||
const parsedNodeList = flattenNodes(sourceFile.statements[0]);
|
||||
Debug.assert(nodeList.length === parsedNodeList.length);
|
||||
for (let i = 0; i < nodeList.length; i++) {
|
||||
const left = nodeList[i];
|
||||
const right = parsedNodeList[i];
|
||||
Debug.assert(left.pos === right.pos);
|
||||
Debug.assert(left.end === right.end);
|
||||
}
|
||||
|
||||
function flattenNodes(n: Node) {
|
||||
const data: (Node | NodeArray<any>)[] = [];
|
||||
walk(n);
|
||||
return data;
|
||||
|
||||
function walk(n: Node | Node[]): void {
|
||||
data.push(<any>n);
|
||||
return isArray(n) ? forEach(n, walk) : forEachChild(n, walk, walk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function runSingleFileTest(caption: string, setupFormatOptions: (opts: FormatCodeSettings) => void, text: string, validateNodes: boolean, testBlock: (sourceFile: SourceFile, changeTracker: textChanges.ChangeTracker) => void) {
|
||||
it(caption, () => {
|
||||
Harness.Baseline.runBaseline(`textChanges/${caption}.js`, () => {
|
||||
const sourceFile = createSourceFile("source.ts", text, ScriptTarget.ES2015, /*setParentNodes*/ true);
|
||||
const rulesProvider = getRuleProvider(setupFormatOptions);
|
||||
const changeTracker = new textChanges.ChangeTracker(printerOptions.newLine, rulesProvider, validateNodes ? verifyPositions : undefined);
|
||||
testBlock(sourceFile, changeTracker);
|
||||
const changes = changeTracker.getChanges();
|
||||
assert.equal(changes.length, 1);
|
||||
assert.equal(changes[0].fileName, sourceFile.fileName);
|
||||
const modified = textChanges.applyChanges(sourceFile.text, changes[0].textChanges);
|
||||
return `===ORIGINAL===${newLineCharacter}${text}${newLineCharacter}===MODIFIED===${newLineCharacter}${modified}`;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function setNewLineForOpenBraceInFunctions(opts: FormatCodeSettings) {
|
||||
opts.placeOpenBraceOnNewLineForFunctions = true;
|
||||
}
|
||||
|
||||
{
|
||||
const text = `
|
||||
namespace M
|
||||
{
|
||||
namespace M2
|
||||
{
|
||||
function foo() {
|
||||
// comment 1
|
||||
const x = 1;
|
||||
|
||||
/**
|
||||
* comment 2 line 1
|
||||
* comment 2 line 2
|
||||
*/
|
||||
function f() {
|
||||
return 100;
|
||||
}
|
||||
const y = 2; // comment 3
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}`;
|
||||
runSingleFileTest("extractMethodLike", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
|
||||
const statements = (<Block>(<FunctionDeclaration>findChild("foo", sourceFile)).body).statements.slice(1);
|
||||
const newFunction = createFunctionDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
/*asteriskToken*/ undefined,
|
||||
/*name*/ "bar",
|
||||
/*typeParameters*/ undefined,
|
||||
/*parameters*/ emptyArray,
|
||||
/*type*/ createKeywordTypeNode(SyntaxKind.AnyKeyword),
|
||||
/*body */ createBlock(statements)
|
||||
);
|
||||
|
||||
changeTracker.insertNodeBefore(sourceFile, /*before*/findChild("M2", sourceFile), newFunction, { suffix: newLineCharacter });
|
||||
|
||||
// replace statements with return statement
|
||||
const newStatement = createReturn(
|
||||
createCall(
|
||||
/*expression*/ newFunction.name,
|
||||
/*typeArguments*/ undefined,
|
||||
/*argumentsArray*/ emptyArray
|
||||
));
|
||||
changeTracker.replaceNodeRange(sourceFile, statements[0], lastOrUndefined(statements), newStatement, { suffix: newLineCharacter });
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
function foo() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
function bar() {
|
||||
return 2;
|
||||
}
|
||||
`;
|
||||
runSingleFileTest("deleteRange1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteRange(sourceFile, { pos: text.indexOf("function foo"), end: text.indexOf("function bar") });
|
||||
});
|
||||
}
|
||||
function findVariableStatementContaining(name: string, sourceFile: SourceFile) {
|
||||
const varDecl = findChild(name, sourceFile);
|
||||
assert.equal(varDecl.kind, SyntaxKind.VariableDeclaration);
|
||||
const varStatement = varDecl.parent.parent;
|
||||
assert.equal(varStatement.kind, SyntaxKind.VariableStatement);
|
||||
return varStatement;
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
var x = 1; // some comment - 1
|
||||
/**
|
||||
* comment 2
|
||||
*/
|
||||
var y = 2; // comment 3
|
||||
var z = 3; // comment 4
|
||||
`;
|
||||
runSingleFileTest("deleteNode1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNode(sourceFile, findVariableStatementContaining("y", sourceFile));
|
||||
});
|
||||
runSingleFileTest("deleteNode2", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNode(sourceFile, findVariableStatementContaining("y", sourceFile), { useNonAdjustedStartPosition: true });
|
||||
});
|
||||
runSingleFileTest("deleteNode3", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNode(sourceFile, findVariableStatementContaining("y", sourceFile), { useNonAdjustedEndPosition: true });
|
||||
});
|
||||
runSingleFileTest("deleteNode4", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNode(sourceFile, findVariableStatementContaining("y", sourceFile), { useNonAdjustedStartPosition: true, useNonAdjustedEndPosition: true });
|
||||
});
|
||||
runSingleFileTest("deleteNode5", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNode(sourceFile, findVariableStatementContaining("x", sourceFile));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
// comment 1
|
||||
var x = 1; // comment 2
|
||||
// comment 3
|
||||
var y = 2; // comment 4
|
||||
var z = 3; // comment 5
|
||||
// comment 6
|
||||
var a = 4; // comment 7
|
||||
`;
|
||||
runSingleFileTest("deleteNodeRange1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile));
|
||||
});
|
||||
runSingleFileTest("deleteNodeRange2", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile),
|
||||
{ useNonAdjustedStartPosition: true });
|
||||
});
|
||||
runSingleFileTest("deleteNodeRange3", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile),
|
||||
{ useNonAdjustedEndPosition: true });
|
||||
});
|
||||
runSingleFileTest("deleteNodeRange4", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile),
|
||||
{ useNonAdjustedStartPosition: true, useNonAdjustedEndPosition: true });
|
||||
});
|
||||
}
|
||||
function createTestVariableDeclaration(name: string) {
|
||||
return createVariableDeclaration(name, /*type*/ undefined, createObjectLiteral([createPropertyAssignment("p1", createLiteral(1))], /*multiline*/ true));
|
||||
}
|
||||
function createTestClass() {
|
||||
return createClassDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
[
|
||||
createToken(SyntaxKind.PublicKeyword)
|
||||
],
|
||||
"class1",
|
||||
/*typeParameters*/ undefined,
|
||||
[
|
||||
createHeritageClause(
|
||||
SyntaxKind.ImplementsKeyword,
|
||||
[
|
||||
createExpressionWithTypeArguments(/*typeArguments*/ undefined, createIdentifier("interface1"))
|
||||
]
|
||||
)
|
||||
],
|
||||
[
|
||||
createProperty(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
"property1",
|
||||
/*questionToken*/ undefined,
|
||||
createKeywordTypeNode(SyntaxKind.BooleanKeyword),
|
||||
/*initializer*/ undefined
|
||||
)
|
||||
]
|
||||
);
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
// comment 1
|
||||
var x = 1; // comment 2
|
||||
// comment 3
|
||||
var y = 2; // comment 4
|
||||
var z = 3; // comment 5
|
||||
// comment 6
|
||||
var a = 4; // comment 7`;
|
||||
runSingleFileTest("replaceRange", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
|
||||
changeTracker.replaceRange(sourceFile, { pos: text.indexOf("var y"), end: text.indexOf("var a") }, createTestClass(), { suffix: newLineCharacter });
|
||||
});
|
||||
runSingleFileTest("replaceRangeWithForcedIndentation", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
|
||||
changeTracker.replaceRange(sourceFile, { pos: text.indexOf("var y"), end: text.indexOf("var a") }, createTestClass(), { suffix: newLineCharacter, indentation: 8, delta: 0 });
|
||||
});
|
||||
|
||||
runSingleFileTest("replaceRangeNoLineBreakBefore", setNewLineForOpenBraceInFunctions, `const x = 1, y = "2";`, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
const newNode = createTestVariableDeclaration("z1");
|
||||
changeTracker.replaceRange(sourceFile, { pos: sourceFile.text.indexOf("y"), end: sourceFile.text.indexOf(";") }, newNode);
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
namespace A {
|
||||
const x = 1, y = "2";
|
||||
}
|
||||
`;
|
||||
runSingleFileTest("replaceNode1NoLineBreakBefore", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
const newNode = createTestVariableDeclaration("z1");
|
||||
changeTracker.replaceNode(sourceFile, findChild("y", sourceFile), newNode);
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
// comment 1
|
||||
var x = 1; // comment 2
|
||||
// comment 3
|
||||
var y = 2; // comment 4
|
||||
var z = 3; // comment 5
|
||||
// comment 6
|
||||
var a = 4; // comment 7`;
|
||||
runSingleFileTest("replaceNode1", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
|
||||
changeTracker.replaceNode(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { suffix: newLineCharacter });
|
||||
});
|
||||
runSingleFileTest("replaceNode2", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
|
||||
changeTracker.replaceNode(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { useNonAdjustedStartPosition: true, suffix: newLineCharacter, prefix: newLineCharacter });
|
||||
});
|
||||
runSingleFileTest("replaceNode3", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
|
||||
changeTracker.replaceNode(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { useNonAdjustedEndPosition: true, suffix: newLineCharacter });
|
||||
});
|
||||
runSingleFileTest("replaceNode4", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
|
||||
changeTracker.replaceNode(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { useNonAdjustedStartPosition: true, useNonAdjustedEndPosition: true });
|
||||
});
|
||||
runSingleFileTest("replaceNode5", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
|
||||
changeTracker.replaceNode(sourceFile, findVariableStatementContaining("x", sourceFile), createTestClass(), { useNonAdjustedStartPosition: true, useNonAdjustedEndPosition: true });
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
// comment 1
|
||||
var x = 1; // comment 2
|
||||
// comment 3
|
||||
var y = 2; // comment 4
|
||||
var z = 3; // comment 5
|
||||
// comment 6
|
||||
var a = 4; // comment 7`;
|
||||
runSingleFileTest("replaceNodeRange1", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
|
||||
changeTracker.replaceNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), createTestClass(), { suffix: newLineCharacter });
|
||||
});
|
||||
runSingleFileTest("replaceNodeRange2", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
|
||||
changeTracker.replaceNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), createTestClass(), { useNonAdjustedStartPosition: true, suffix: newLineCharacter, prefix: newLineCharacter });
|
||||
});
|
||||
runSingleFileTest("replaceNodeRange3", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
|
||||
changeTracker.replaceNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), createTestClass(), { useNonAdjustedEndPosition: true, suffix: newLineCharacter });
|
||||
});
|
||||
runSingleFileTest("replaceNodeRange4", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
|
||||
changeTracker.replaceNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), createTestClass(), { useNonAdjustedStartPosition: true, useNonAdjustedEndPosition: true });
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
// comment 1
|
||||
var x = 1; // comment 2
|
||||
// comment 3
|
||||
var y; // comment 4
|
||||
var z = 3; // comment 5
|
||||
// comment 6
|
||||
var a = 4; // comment 7`;
|
||||
runSingleFileTest("insertNodeAt1", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeAt(sourceFile, text.indexOf("var y"), createTestClass(), { suffix: newLineCharacter });
|
||||
});
|
||||
runSingleFileTest("insertNodeAt2", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeAt(sourceFile, text.indexOf("; // comment 4"), createTestVariableDeclaration("z1"));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
namespace M {
|
||||
// comment 1
|
||||
var x = 1; // comment 2
|
||||
// comment 3
|
||||
var y; // comment 4
|
||||
var z = 3; // comment 5
|
||||
// comment 6
|
||||
var a = 4; // comment 7
|
||||
}`;
|
||||
runSingleFileTest("insertNodeBefore1", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeBefore(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { suffix: newLineCharacter });
|
||||
});
|
||||
runSingleFileTest("insertNodeBefore2", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeBefore(sourceFile, findChild("M", sourceFile), createTestClass(), { suffix: newLineCharacter });
|
||||
});
|
||||
runSingleFileTest("insertNodeAfter1", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeAfter(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { suffix: newLineCharacter });
|
||||
});
|
||||
runSingleFileTest("insertNodeAfter2", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeAfter(sourceFile, findChild("M", sourceFile), createTestClass(), { prefix: newLineCharacter });
|
||||
});
|
||||
}
|
||||
{
|
||||
function findOpenBraceForConstructor(sourceFile: SourceFile) {
|
||||
const classDecl = <ClassDeclaration>sourceFile.statements[0];
|
||||
const constructorDecl = forEach(classDecl.members, m => m.kind === SyntaxKind.Constructor && (<ConstructorDeclaration>m).body && <ConstructorDeclaration>m);
|
||||
return constructorDecl.body.getFirstToken();
|
||||
}
|
||||
function createTestSuperCall() {
|
||||
const superCall = createCall(
|
||||
createSuper(),
|
||||
/*typeArguments*/ undefined,
|
||||
/*argumentsArray*/ emptyArray
|
||||
);
|
||||
return createStatement(superCall);
|
||||
}
|
||||
const text1 = `
|
||||
class A {
|
||||
constructor() {
|
||||
}
|
||||
}
|
||||
`;
|
||||
runSingleFileTest("insertNodeAfter3", noop, text1, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeAfter(sourceFile, findOpenBraceForConstructor(sourceFile), createTestSuperCall(), { suffix: newLineCharacter });
|
||||
});
|
||||
const text2 = `
|
||||
class A {
|
||||
constructor() {
|
||||
var x = 1;
|
||||
}
|
||||
}
|
||||
`;
|
||||
runSingleFileTest("insertNodeAfter4", noop, text2, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeAfter(sourceFile, findVariableStatementContaining("x", sourceFile), createTestSuperCall(), { suffix: newLineCharacter });
|
||||
});
|
||||
const text3 = `
|
||||
class A {
|
||||
constructor() {
|
||||
|
||||
}
|
||||
}
|
||||
`;
|
||||
runSingleFileTest("insertNodeAfter3-block with newline", noop, text3, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeAfter(sourceFile, findOpenBraceForConstructor(sourceFile), createTestSuperCall(), { suffix: newLineCharacter });
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `var a = 1, b = 2, c = 3;`;
|
||||
runSingleFileTest("deleteNodeInList1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("a", sourceFile));
|
||||
});
|
||||
runSingleFileTest("deleteNodeInList2", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("b", sourceFile));
|
||||
});
|
||||
runSingleFileTest("deleteNodeInList3", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("c", sourceFile));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `var a = 1,b = 2,c = 3;`;
|
||||
runSingleFileTest("deleteNodeInList1_1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("a", sourceFile));
|
||||
});
|
||||
runSingleFileTest("deleteNodeInList2_1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("b", sourceFile));
|
||||
});
|
||||
runSingleFileTest("deleteNodeInList3_1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("c", sourceFile));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
namespace M {
|
||||
var a = 1,
|
||||
b = 2,
|
||||
c = 3;
|
||||
}`;
|
||||
runSingleFileTest("deleteNodeInList4", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("a", sourceFile));
|
||||
});
|
||||
runSingleFileTest("deleteNodeInList5", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("b", sourceFile));
|
||||
});
|
||||
runSingleFileTest("deleteNodeInList6", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("c", sourceFile));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
namespace M {
|
||||
var a = 1, // comment 1
|
||||
// comment 2
|
||||
b = 2, // comment 3
|
||||
// comment 4
|
||||
c = 3; // comment 5
|
||||
}`;
|
||||
runSingleFileTest("deleteNodeInList4_1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("a", sourceFile));
|
||||
});
|
||||
runSingleFileTest("deleteNodeInList5_1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("b", sourceFile));
|
||||
});
|
||||
runSingleFileTest("deleteNodeInList6_1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("c", sourceFile));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
function foo(a: number, b: string, c = true) {
|
||||
return 1;
|
||||
}`;
|
||||
runSingleFileTest("deleteNodeInList7", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("a", sourceFile));
|
||||
});
|
||||
runSingleFileTest("deleteNodeInList8", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("b", sourceFile));
|
||||
});
|
||||
runSingleFileTest("deleteNodeInList9", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("c", sourceFile));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
function foo(a: number,b: string,c = true) {
|
||||
return 1;
|
||||
}`;
|
||||
runSingleFileTest("deleteNodeInList10", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("a", sourceFile));
|
||||
});
|
||||
runSingleFileTest("deleteNodeInList11", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("b", sourceFile));
|
||||
});
|
||||
runSingleFileTest("deleteNodeInList12", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("c", sourceFile));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
function foo(
|
||||
a: number,
|
||||
b: string,
|
||||
c = true) {
|
||||
return 1;
|
||||
}`;
|
||||
runSingleFileTest("deleteNodeInList13", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("a", sourceFile));
|
||||
});
|
||||
runSingleFileTest("deleteNodeInList14", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("b", sourceFile));
|
||||
});
|
||||
runSingleFileTest("deleteNodeInList15", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("c", sourceFile));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
const x = 1, y = 2;`;
|
||||
runSingleFileTest("insertNodeInListAfter1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1)));
|
||||
});
|
||||
runSingleFileTest("insertNodeInListAfter2", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1)));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
const /*x*/ x = 1, /*y*/ y = 2;`;
|
||||
runSingleFileTest("insertNodeInListAfter3", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1)));
|
||||
});
|
||||
runSingleFileTest("insertNodeInListAfter4", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1)));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
const x = 1;`;
|
||||
runSingleFileTest("insertNodeInListAfter5", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1)));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
const x = 1,
|
||||
y = 2;`;
|
||||
runSingleFileTest("insertNodeInListAfter6", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1)));
|
||||
});
|
||||
runSingleFileTest("insertNodeInListAfter7", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1)));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
const /*x*/ x = 1,
|
||||
/*y*/ y = 2;`;
|
||||
runSingleFileTest("insertNodeInListAfter8", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1)));
|
||||
});
|
||||
runSingleFileTest("insertNodeInListAfter9", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1)));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
import {
|
||||
x
|
||||
} from "bar"`;
|
||||
runSingleFileTest("insertNodeInListAfter10", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(createIdentifier("b"), createIdentifier("a")));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
import {
|
||||
x // this is x
|
||||
} from "bar"`;
|
||||
runSingleFileTest("insertNodeInListAfter11", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(createIdentifier("b"), createIdentifier("a")));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
import {
|
||||
x
|
||||
} from "bar"`;
|
||||
runSingleFileTest("insertNodeInListAfter12", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(undefined, createIdentifier("a")));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
import {
|
||||
x // this is x
|
||||
} from "bar"`;
|
||||
runSingleFileTest("insertNodeInListAfter13", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(undefined, createIdentifier("a")));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
import {
|
||||
x0,
|
||||
x
|
||||
} from "bar"`;
|
||||
runSingleFileTest("insertNodeInListAfter14", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(createIdentifier("b"), createIdentifier("a")));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
import {
|
||||
x0,
|
||||
x // this is x
|
||||
} from "bar"`;
|
||||
runSingleFileTest("insertNodeInListAfter15", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(createIdentifier("b"), createIdentifier("a")));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
import {
|
||||
x0,
|
||||
x
|
||||
} from "bar"`;
|
||||
runSingleFileTest("insertNodeInListAfter16", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(undefined, createIdentifier("a")));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
import {
|
||||
x0,
|
||||
x // this is x
|
||||
} from "bar"`;
|
||||
runSingleFileTest("insertNodeInListAfter17", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(undefined, createIdentifier("a")));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
import {
|
||||
x0, x
|
||||
} from "bar"`;
|
||||
runSingleFileTest("insertNodeInListAfter18", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(undefined, createIdentifier("a")));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
class A {
|
||||
x;
|
||||
}`;
|
||||
runSingleFileTest("insertNodeAfterMultipleNodes", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
const newNodes = [];
|
||||
for (let i = 0; i < 11 /*error doesn't occur with fewer nodes*/; ++i) {
|
||||
newNodes.push(
|
||||
createProperty(undefined, undefined, i + "", undefined, undefined, undefined));
|
||||
}
|
||||
const insertAfter = findChild("x", sourceFile);
|
||||
for (const newNode of newNodes) {
|
||||
changeTracker.insertNodeAfter(sourceFile, insertAfter, newNode, { suffix: newLineCharacter });
|
||||
}
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
class A {
|
||||
x
|
||||
}
|
||||
`;
|
||||
runSingleFileTest("insertNodeAfterInClass1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), createProperty(undefined, undefined, "a", undefined, createKeywordTypeNode(SyntaxKind.BooleanKeyword), undefined), { suffix: newLineCharacter });
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
class A {
|
||||
x;
|
||||
}
|
||||
`;
|
||||
runSingleFileTest("insertNodeAfterInClass2", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), createProperty(undefined, undefined, "a", undefined, createKeywordTypeNode(SyntaxKind.BooleanKeyword), undefined), { suffix: newLineCharacter });
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
class A {
|
||||
x;
|
||||
y = 1;
|
||||
}
|
||||
`;
|
||||
runSingleFileTest("deleteNodeAfterInClass1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNode(sourceFile, findChild("x", sourceFile));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
class A {
|
||||
x
|
||||
y = 1;
|
||||
}
|
||||
`;
|
||||
runSingleFileTest("deleteNodeAfterInClass2", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNode(sourceFile, findChild("x", sourceFile));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
class A {
|
||||
x = foo
|
||||
}
|
||||
`;
|
||||
runSingleFileTest("insertNodeInClassAfterNodeWithoutSeparator1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
const newNode = createProperty(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
createComputedPropertyName(createLiteral(1)),
|
||||
/*questionToken*/ undefined,
|
||||
createKeywordTypeNode(SyntaxKind.AnyKeyword),
|
||||
/*initializer*/ undefined);
|
||||
changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode, { suffix: newLineCharacter });
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
class A {
|
||||
x() {
|
||||
}
|
||||
}
|
||||
`;
|
||||
runSingleFileTest("insertNodeInClassAfterNodeWithoutSeparator2", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
const newNode = createProperty(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
createComputedPropertyName(createLiteral(1)),
|
||||
/*questionToken*/ undefined,
|
||||
createKeywordTypeNode(SyntaxKind.AnyKeyword),
|
||||
/*initializer*/ undefined);
|
||||
changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode, { suffix: newLineCharacter });
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
interface A {
|
||||
x
|
||||
}
|
||||
`;
|
||||
runSingleFileTest("insertNodeInInterfaceAfterNodeWithoutSeparator1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
const newNode = createProperty(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
createComputedPropertyName(createLiteral(1)),
|
||||
/*questionToken*/ undefined,
|
||||
createKeywordTypeNode(SyntaxKind.AnyKeyword),
|
||||
/*initializer*/ undefined);
|
||||
changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode, { suffix: newLineCharacter });
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
interface A {
|
||||
x()
|
||||
}
|
||||
`;
|
||||
runSingleFileTest("insertNodeInInterfaceAfterNodeWithoutSeparator2", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
const newNode = createProperty(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
createComputedPropertyName(createLiteral(1)),
|
||||
/*questionToken*/ undefined,
|
||||
createKeywordTypeNode(SyntaxKind.AnyKeyword),
|
||||
/*initializer*/ undefined);
|
||||
changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode, { suffix: newLineCharacter });
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
let x = foo
|
||||
`;
|
||||
runSingleFileTest("insertNodeInStatementListAfterNodeWithoutSeparator1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
const newNode = createStatement(createParen(createLiteral(1)));
|
||||
changeTracker.insertNodeAfter(sourceFile, findVariableStatementContaining("x", sourceFile), newNode, { suffix: newLineCharacter });
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/// <reference path="..\harness.ts" />
|
||||
/// <reference path="..\harness.ts" />
|
||||
/// <reference path="../../server/typingsInstaller/typingsInstaller.ts" />
|
||||
|
||||
namespace ts.projectSystem {
|
||||
@@ -3006,6 +3006,42 @@ namespace ts.projectSystem {
|
||||
const errorResult = <protocol.Diagnostic[]>session.executeCommand(dTsFileGetErrRequest).response;
|
||||
assert.isTrue(errorResult.length === 0);
|
||||
});
|
||||
|
||||
it("should be turned on for js-only external projects with skipLibCheck=false", () => {
|
||||
const jsFile = {
|
||||
path: "/a/b/file1.js",
|
||||
content: "let x =1;"
|
||||
};
|
||||
const dTsFile = {
|
||||
path: "/a/b/file2.d.ts",
|
||||
content: `
|
||||
interface T {
|
||||
name: string;
|
||||
};
|
||||
interface T {
|
||||
name: number;
|
||||
};`
|
||||
};
|
||||
const host = createServerHost([jsFile, dTsFile]);
|
||||
const session = createSession(host);
|
||||
|
||||
const openExternalProjectRequest = makeSessionRequest<protocol.OpenExternalProjectArgs>(
|
||||
CommandNames.OpenExternalProject,
|
||||
{
|
||||
projectFileName: "project1",
|
||||
rootFiles: toExternalFiles([jsFile.path, dTsFile.path]),
|
||||
options: { skipLibCheck: false }
|
||||
}
|
||||
);
|
||||
session.executeCommand(openExternalProjectRequest);
|
||||
|
||||
const dTsFileGetErrRequest = makeSessionRequest<protocol.SemanticDiagnosticsSyncRequestArgs>(
|
||||
CommandNames.SemanticDiagnosticsSync,
|
||||
{ file: dTsFile.path }
|
||||
);
|
||||
const errorResult = <protocol.Diagnostic[]>session.executeCommand(dTsFileGetErrRequest).response;
|
||||
assert.isTrue(errorResult.length === 0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("non-existing directories listed in config file input array", () => {
|
||||
@@ -3489,6 +3525,52 @@ namespace ts.projectSystem {
|
||||
});
|
||||
});
|
||||
|
||||
describe("occurence highlight on string", () => {
|
||||
it("should be marked if only on string values", () => {
|
||||
const file1: FileOrFolder = {
|
||||
path: "/a/b/file1.ts",
|
||||
content: `let t1 = "div";\nlet t2 = "div";\nlet t3 = { "div": 123 };\nlet t4 = t3["div"];`
|
||||
};
|
||||
|
||||
const host = createServerHost([file1]);
|
||||
const session = createSession(host);
|
||||
const projectService = session.getProjectService();
|
||||
|
||||
projectService.openClientFile(file1.path);
|
||||
{
|
||||
const highlightRequest = makeSessionRequest<protocol.FileLocationRequestArgs>(
|
||||
CommandNames.Occurrences,
|
||||
{ file: file1.path, line: 1, offset: 11 }
|
||||
);
|
||||
const highlightResponse = session.executeCommand(highlightRequest).response as protocol.OccurrencesResponseItem[];
|
||||
const firstOccurence = highlightResponse[0];
|
||||
assert.isTrue(firstOccurence.isInString, "Highlights should be marked with isInString");
|
||||
}
|
||||
|
||||
{
|
||||
const highlightRequest = makeSessionRequest<protocol.FileLocationRequestArgs>(
|
||||
CommandNames.Occurrences,
|
||||
{ file: file1.path, line: 3, offset: 13 }
|
||||
);
|
||||
const highlightResponse = session.executeCommand(highlightRequest).response as protocol.OccurrencesResponseItem[];
|
||||
assert.isTrue(highlightResponse.length === 2);
|
||||
const firstOccurence = highlightResponse[0];
|
||||
assert.isUndefined(firstOccurence.isInString, "Highlights should not be marked with isInString if on property name");
|
||||
}
|
||||
|
||||
{
|
||||
const highlightRequest = makeSessionRequest<protocol.FileLocationRequestArgs>(
|
||||
CommandNames.Occurrences,
|
||||
{ file: file1.path, line: 4, offset: 14 }
|
||||
);
|
||||
const highlightResponse = session.executeCommand(highlightRequest).response as protocol.OccurrencesResponseItem[];
|
||||
assert.isTrue(highlightResponse.length === 2);
|
||||
const firstOccurence = highlightResponse[0];
|
||||
assert.isUndefined(firstOccurence.isInString, "Highlights should not be marked with isInString if on indexer");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("maxNodeModuleJsDepth for inferred projects", () => {
|
||||
it("should be set to 2 if the project has js root files", () => {
|
||||
const file1: FileOrFolder = {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/// <reference path="../harness.ts" />
|
||||
/// <reference path="../harness.ts" />
|
||||
/// <reference path="./tsserverProjectSystem.ts" />
|
||||
/// <reference path="../../server/typingsInstaller/typingsInstaller.ts" />
|
||||
|
||||
|
||||
Vendored
+44
-2
@@ -5,9 +5,51 @@ interface DOMTokenList {
|
||||
}
|
||||
|
||||
interface NodeList {
|
||||
[Symbol.iterator](): IterableIterator<Node>
|
||||
/**
|
||||
* Returns an array of key, value pairs for every entry in the list
|
||||
*/
|
||||
entries(): IterableIterator<[number, Node]>;
|
||||
/**
|
||||
* Performs the specified action for each node in an list.
|
||||
* @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the list.
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
forEach(callbackfn: (value: Node, index: number, listObj: NodeList) => void, thisArg?: any): void;
|
||||
/**
|
||||
* Returns an list of keys in the list
|
||||
*/
|
||||
keys(): IterableIterator<number>;
|
||||
|
||||
/**
|
||||
* Returns an list of values in the list
|
||||
*/
|
||||
values(): IterableIterator<Node>;
|
||||
|
||||
|
||||
[Symbol.iterator](): IterableIterator<Node>;
|
||||
}
|
||||
|
||||
interface NodeListOf<TNode extends Node> {
|
||||
[Symbol.iterator](): IterableIterator<TNode>
|
||||
|
||||
/**
|
||||
* Returns an array of key, value pairs for every entry in the list
|
||||
*/
|
||||
entries(): IterableIterator<[number, TNode]>;
|
||||
|
||||
/**
|
||||
* Performs the specified action for each node in an list.
|
||||
* @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the list.
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
forEach(callbackfn: (value: TNode, index: number, listObj: NodeListOf<TNode>) => void, thisArg?: any): void;
|
||||
/**
|
||||
* Returns an list of keys in the list
|
||||
*/
|
||||
keys(): IterableIterator<number>;
|
||||
/**
|
||||
* Returns an list of values in the list
|
||||
*/
|
||||
values(): IterableIterator<TNode>;
|
||||
|
||||
[Symbol.iterator](): IterableIterator<TNode>;
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -17,7 +17,7 @@ declare var Map: MapConstructor;
|
||||
|
||||
interface ReadonlyMap<K, V> {
|
||||
forEach(callbackfn: (value: V, key: K, map: ReadonlyMap<K, V>) => void, thisArg?: any): void;
|
||||
get(key: K): V|undefined;
|
||||
get(key: K): V | undefined;
|
||||
has(key: K): boolean;
|
||||
readonly size: number;
|
||||
}
|
||||
|
||||
Vendored
+18
-8
@@ -10,7 +10,9 @@ interface Array<T> {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
find(predicate: (value: T, index: number, obj: Array<T>) => boolean, thisArg?: any): T | undefined;
|
||||
find(predicate: (this: undefined, value: T, index: number, obj: Array<T>) => boolean): T | undefined;
|
||||
find(predicate: (this: undefined, value: T, index: number, obj: Array<T>) => boolean, thisArg: undefined): T | undefined;
|
||||
find<Z>(predicate: (this: Z, value: T, index: number, obj: Array<T>) => boolean, thisArg: Z): T | undefined;
|
||||
|
||||
/**
|
||||
* Returns the index of the first element in the array where predicate is true, and -1
|
||||
@@ -21,7 +23,9 @@ interface Array<T> {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
findIndex(predicate: (value: T, index: number, obj: Array<T>) => boolean, thisArg?: any): number;
|
||||
findIndex(predicate: (this: undefined, value: T, index: number, obj: Array<T>) => boolean): number;
|
||||
findIndex(predicate: (this: undefined, value: T, index: number, obj: Array<T>) => boolean, thisArg: undefined): number;
|
||||
findIndex<Z>(predicate: (this: Z, value: T, index: number, obj: Array<T>) => boolean, thisArg: Z): number;
|
||||
|
||||
/**
|
||||
* Returns the this object after filling the section identified by start and end with value
|
||||
@@ -52,7 +56,9 @@ interface ArrayConstructor {
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from<T, U>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => U, thisArg?: any): Array<U>;
|
||||
from<T, U>(arrayLike: ArrayLike<T>, mapfn: (this: undefined, v: T, k: number) => U): Array<U>;
|
||||
from<T, U>(arrayLike: ArrayLike<T>, mapfn: (this: undefined, v: T, k: number) => U, thisArg: undefined): Array<U>;
|
||||
from<Z, T, U>(arrayLike: ArrayLike<T>, mapfn: (this: Z, v: T, k: number) => U, thisArg: Z): Array<U>;
|
||||
|
||||
|
||||
/**
|
||||
@@ -262,7 +268,7 @@ interface Object {
|
||||
* Determines whether an object has a property with the specified name.
|
||||
* @param v A property name.
|
||||
*/
|
||||
hasOwnProperty(v: PropertyKey): boolean
|
||||
hasOwnProperty(v: PropertyKey): boolean;
|
||||
|
||||
/**
|
||||
* Determines whether a specified property is enumerable.
|
||||
@@ -357,7 +363,9 @@ interface ReadonlyArray<T> {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
find(predicate: (value: T, index: number, obj: ReadonlyArray<T>) => boolean, thisArg?: any): T | undefined;
|
||||
find(predicate: (this: undefined, value: T, index: number, obj: ReadonlyArray<T>) => boolean): T | undefined;
|
||||
find(predicate: (this: undefined, value: T, index: number, obj: ReadonlyArray<T>) => boolean, thisArg: undefined): T | undefined;
|
||||
find<Z>(predicate: (this: Z, value: T, index: number, obj: ReadonlyArray<T>) => boolean, thisArg: Z): T | undefined;
|
||||
|
||||
/**
|
||||
* Returns the index of the first element in the array where predicate is true, and -1
|
||||
@@ -368,7 +376,9 @@ interface ReadonlyArray<T> {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
findIndex(predicate: (value: T, index: number, obj: Array<T>) => boolean, thisArg?: any): number;
|
||||
findIndex(predicate: (this: undefined, value: T, index: number, obj: Array<T>) => boolean): number;
|
||||
findIndex(predicate: (this: undefined, value: T, index: number, obj: Array<T>) => boolean, thisArg: undefined): number;
|
||||
findIndex<Z>(predicate: (this: Z, value: T, index: number, obj: Array<T>) => boolean, thisArg: Z): number;
|
||||
}
|
||||
|
||||
interface RegExp {
|
||||
@@ -476,10 +486,10 @@ interface String {
|
||||
bold(): string;
|
||||
|
||||
/** Returns a <tt> HTML element */
|
||||
fixed(): string
|
||||
fixed(): string;
|
||||
|
||||
/** Returns a <font> HTML element and sets the color attribute value */
|
||||
fontcolor(color: string): string
|
||||
fontcolor(color: string): string;
|
||||
|
||||
/** Returns a <font> HTML element and sets the size attribute value */
|
||||
fontsize(size: number): string;
|
||||
|
||||
Vendored
+49
-11
@@ -54,7 +54,9 @@ interface ArrayConstructor {
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from<T, U>(iterable: Iterable<T>, mapfn: (v: T, k: number) => U, thisArg?: any): Array<U>;
|
||||
from<T, U>(iterable: Iterable<T>, mapfn: (this: undefined, v: T, k: number) => U): Array<U>;
|
||||
from<T, U>(iterable: Iterable<T>, mapfn: (this: undefined, v: T, k: number) => U, thisArg: undefined): Array<U>;
|
||||
from<Z, T, U>(iterable: Iterable<T>, mapfn: (this: Z, v: T, k: number) => U, thisArg: Z): Array<U>;
|
||||
|
||||
/**
|
||||
* Creates an array from an iterable object.
|
||||
@@ -89,7 +91,7 @@ interface IArguments {
|
||||
}
|
||||
|
||||
interface Map<K, V> {
|
||||
[Symbol.iterator](): IterableIterator<[K,V]>;
|
||||
[Symbol.iterator](): IterableIterator<[K, V]>;
|
||||
entries(): IterableIterator<[K, V]>;
|
||||
keys(): IterableIterator<K>;
|
||||
values(): IterableIterator<V>;
|
||||
@@ -180,7 +182,11 @@ interface Int8ArrayConstructor {
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Int8Array;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number): Int8Array;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Int8Array;
|
||||
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Int8Array;
|
||||
|
||||
from(arrayLike: Iterable<number>): Int8Array;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -212,7 +218,11 @@ interface Uint8ArrayConstructor {
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint8Array;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number): Uint8Array;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Uint8Array;
|
||||
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Uint8Array;
|
||||
|
||||
from(arrayLike: Iterable<number>): Uint8Array;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -247,7 +257,11 @@ interface Uint8ClampedArrayConstructor {
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint8ClampedArray;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number): Uint8ClampedArray;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Uint8ClampedArray;
|
||||
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Uint8ClampedArray;
|
||||
|
||||
from(arrayLike: Iterable<number>): Uint8ClampedArray;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -281,7 +295,11 @@ interface Int16ArrayConstructor {
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Int16Array;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number): Int16Array;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Int16Array;
|
||||
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Int16Array;
|
||||
|
||||
from(arrayLike: Iterable<number>): Int16Array;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -313,7 +331,11 @@ interface Uint16ArrayConstructor {
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint16Array;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number): Uint16Array;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Uint16Array;
|
||||
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Uint16Array;
|
||||
|
||||
from(arrayLike: Iterable<number>): Uint16Array;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -345,7 +367,11 @@ interface Int32ArrayConstructor {
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Int32Array;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number): Int32Array;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Int32Array;
|
||||
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Int32Array;
|
||||
|
||||
from(arrayLike: Iterable<number>): Int32Array;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -377,7 +403,11 @@ interface Uint32ArrayConstructor {
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint32Array;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number): Uint32Array;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Uint32Array;
|
||||
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Uint32Array;
|
||||
|
||||
from(arrayLike: Iterable<number>): Uint32Array;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -409,7 +439,11 @@ interface Float32ArrayConstructor {
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Float32Array;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number): Float32Array;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Float32Array;
|
||||
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Float32Array;
|
||||
|
||||
from(arrayLike: Iterable<number>): Float32Array;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -441,5 +475,9 @@ interface Float64ArrayConstructor {
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Float64Array;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number): Float64Array;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Float64Array;
|
||||
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Float64Array;
|
||||
|
||||
from(arrayLike: Iterable<number>): Float64Array;
|
||||
}
|
||||
|
||||
Vendored
+2
-2
@@ -12,11 +12,11 @@ interface ProxyHandler<T> {
|
||||
enumerate? (target: T): PropertyKey[];
|
||||
ownKeys? (target: T): PropertyKey[];
|
||||
apply? (target: T, thisArg: any, argArray?: any): any;
|
||||
construct? (target: T, argArray: any, newTarget?: any): object
|
||||
construct? (target: T, argArray: any, newTarget?: any): object;
|
||||
}
|
||||
|
||||
interface ProxyConstructor {
|
||||
revocable<T>(target: T, handler: ProxyHandler<T>): { proxy: T; revoke: () => void; };
|
||||
new <T>(target: T, handler: ProxyHandler<T>): T
|
||||
new <T>(target: T, handler: ProxyHandler<T>): T;
|
||||
}
|
||||
declare var Proxy: ProxyConstructor;
|
||||
|
||||
Vendored
+5
-5
@@ -7,8 +7,8 @@ interface Symbol {
|
||||
}
|
||||
|
||||
interface SymbolConstructor {
|
||||
/**
|
||||
* A reference to the prototype.
|
||||
/**
|
||||
* A reference to the prototype.
|
||||
*/
|
||||
readonly prototype: Symbol;
|
||||
|
||||
@@ -16,17 +16,17 @@ interface SymbolConstructor {
|
||||
* Returns a new unique Symbol value.
|
||||
* @param description Description of the new Symbol object.
|
||||
*/
|
||||
(description?: string|number): symbol;
|
||||
(description?: string | number): symbol;
|
||||
|
||||
/**
|
||||
* Returns a Symbol object from the global symbol registry matching the given key if found.
|
||||
* Returns a Symbol object from the global symbol registry matching the given key if found.
|
||||
* Otherwise, returns a new symbol with this key.
|
||||
* @param key key to search for.
|
||||
*/
|
||||
for(key: string): symbol;
|
||||
|
||||
/**
|
||||
* Returns a key from the global symbol registry matching the given Symbol if found.
|
||||
* Returns a key from the global symbol registry matching the given Symbol if found.
|
||||
* Otherwise, returns a undefined.
|
||||
* @param sym Symbol to find the key for.
|
||||
*/
|
||||
|
||||
Vendored
+27
-27
@@ -1,55 +1,55 @@
|
||||
/// <reference path="lib.es2015.symbol.d.ts" />
|
||||
|
||||
interface SymbolConstructor {
|
||||
/**
|
||||
* A method that determines if a constructor object recognizes an object as one of the
|
||||
* constructor’s instances. Called by the semantics of the instanceof operator.
|
||||
/**
|
||||
* A method that determines if a constructor object recognizes an object as one of the
|
||||
* constructor’s instances. Called by the semantics of the instanceof operator.
|
||||
*/
|
||||
readonly hasInstance: symbol;
|
||||
|
||||
/**
|
||||
/**
|
||||
* A Boolean value that if true indicates that an object should flatten to its array elements
|
||||
* by Array.prototype.concat.
|
||||
*/
|
||||
readonly isConcatSpreadable: symbol;
|
||||
|
||||
/**
|
||||
* A regular expression method that matches the regular expression against a string. Called
|
||||
* by the String.prototype.match method.
|
||||
* A regular expression method that matches the regular expression against a string. Called
|
||||
* by the String.prototype.match method.
|
||||
*/
|
||||
readonly match: symbol;
|
||||
|
||||
/**
|
||||
* A regular expression method that replaces matched substrings of a string. Called by the
|
||||
/**
|
||||
* A regular expression method that replaces matched substrings of a string. Called by the
|
||||
* String.prototype.replace method.
|
||||
*/
|
||||
readonly replace: symbol;
|
||||
|
||||
/**
|
||||
* A regular expression method that returns the index within a string that matches the
|
||||
* A regular expression method that returns the index within a string that matches the
|
||||
* regular expression. Called by the String.prototype.search method.
|
||||
*/
|
||||
readonly search: symbol;
|
||||
|
||||
/**
|
||||
* A function valued property that is the constructor function that is used to create
|
||||
/**
|
||||
* A function valued property that is the constructor function that is used to create
|
||||
* derived objects.
|
||||
*/
|
||||
readonly species: symbol;
|
||||
|
||||
/**
|
||||
* A regular expression method that splits a string at the indices that match the regular
|
||||
* A regular expression method that splits a string at the indices that match the regular
|
||||
* expression. Called by the String.prototype.split method.
|
||||
*/
|
||||
readonly split: symbol;
|
||||
|
||||
/**
|
||||
/**
|
||||
* A method that converts an object to a corresponding primitive value.
|
||||
* Called by the ToPrimitive abstract operation.
|
||||
*/
|
||||
readonly toPrimitive: symbol;
|
||||
|
||||
/**
|
||||
/**
|
||||
* A String value that is used in the creation of the default string description of an object.
|
||||
* Called by the built-in method Object.prototype.toString.
|
||||
*/
|
||||
@@ -165,7 +165,7 @@ interface RegExp {
|
||||
* Replaces text in a string, using this regular expression.
|
||||
* @param string A String object or string literal whose contents matching against
|
||||
* this regular expression will be replaced
|
||||
* @param replaceValue A String object or string literal containing the text to replace for every
|
||||
* @param replaceValue A String object or string literal containing the text to replace for every
|
||||
* successful match of this regular expression.
|
||||
*/
|
||||
[Symbol.replace](string: string, replaceValue: string): string;
|
||||
@@ -241,10 +241,10 @@ interface String {
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a raw buffer of binary data, which is used to store data for the
|
||||
* different typed arrays. ArrayBuffers cannot be read from or written to directly,
|
||||
* but can be passed to a typed array or DataView Object to interpret the raw
|
||||
* buffer as needed.
|
||||
* Represents a raw buffer of binary data, which is used to store data for the
|
||||
* different typed arrays. ArrayBuffers cannot be read from or written to directly,
|
||||
* but can be passed to a typed array or DataView Object to interpret the raw
|
||||
* buffer as needed.
|
||||
*/
|
||||
interface ArrayBuffer {
|
||||
readonly [Symbol.toStringTag]: "ArrayBuffer";
|
||||
@@ -255,7 +255,7 @@ interface DataView {
|
||||
}
|
||||
|
||||
/**
|
||||
* A typed array of 8-bit integer values. The contents are initialized to 0. If the requested
|
||||
* A typed array of 8-bit integer values. The contents are initialized to 0. If the requested
|
||||
* number of bytes could not be allocated an exception is raised.
|
||||
*/
|
||||
interface Int8Array {
|
||||
@@ -263,7 +263,7 @@ interface Int8Array {
|
||||
}
|
||||
|
||||
/**
|
||||
* A typed array of 8-bit unsigned integer values. The contents are initialized to 0. If the
|
||||
* A typed array of 8-bit unsigned integer values. The contents are initialized to 0. If the
|
||||
* requested number of bytes could not be allocated an exception is raised.
|
||||
*/
|
||||
interface Uint8Array {
|
||||
@@ -271,7 +271,7 @@ interface Uint8Array {
|
||||
}
|
||||
|
||||
/**
|
||||
* A typed array of 8-bit unsigned integer (clamped) values. The contents are initialized to 0.
|
||||
* A typed array of 8-bit unsigned integer (clamped) values. The contents are initialized to 0.
|
||||
* If the requested number of bytes could not be allocated an exception is raised.
|
||||
*/
|
||||
interface Uint8ClampedArray {
|
||||
@@ -279,7 +279,7 @@ interface Uint8ClampedArray {
|
||||
}
|
||||
|
||||
/**
|
||||
* A typed array of 16-bit signed integer values. The contents are initialized to 0. If the
|
||||
* A typed array of 16-bit signed integer values. The contents are initialized to 0. If the
|
||||
* requested number of bytes could not be allocated an exception is raised.
|
||||
*/
|
||||
interface Int16Array {
|
||||
@@ -287,7 +287,7 @@ interface Int16Array {
|
||||
}
|
||||
|
||||
/**
|
||||
* A typed array of 16-bit unsigned integer values. The contents are initialized to 0. If the
|
||||
* A typed array of 16-bit unsigned integer values. The contents are initialized to 0. If the
|
||||
* requested number of bytes could not be allocated an exception is raised.
|
||||
*/
|
||||
interface Uint16Array {
|
||||
@@ -295,7 +295,7 @@ interface Uint16Array {
|
||||
}
|
||||
|
||||
/**
|
||||
* A typed array of 32-bit signed integer values. The contents are initialized to 0. If the
|
||||
* A typed array of 32-bit signed integer values. The contents are initialized to 0. If the
|
||||
* requested number of bytes could not be allocated an exception is raised.
|
||||
*/
|
||||
interface Int32Array {
|
||||
@@ -303,7 +303,7 @@ interface Int32Array {
|
||||
}
|
||||
|
||||
/**
|
||||
* A typed array of 32-bit unsigned integer values. The contents are initialized to 0. If the
|
||||
* A typed array of 32-bit unsigned integer values. The contents are initialized to 0. If the
|
||||
* requested number of bytes could not be allocated an exception is raised.
|
||||
*/
|
||||
interface Uint32Array {
|
||||
@@ -319,7 +319,7 @@ interface Float32Array {
|
||||
}
|
||||
|
||||
/**
|
||||
* A typed array of 64-bit float values. The contents are initialized to 0. If the requested
|
||||
* A typed array of 64-bit float values. The contents are initialized to 0. If the requested
|
||||
* number of bytes could not be allocated an exception is raised.
|
||||
*/
|
||||
interface Float64Array {
|
||||
|
||||
Vendored
+2
-2
@@ -13,8 +13,8 @@ interface SharedArrayBuffer {
|
||||
length: number;
|
||||
/**
|
||||
* Returns a section of an SharedArrayBuffer.
|
||||
*/
|
||||
slice(begin:number, end?:number): SharedArrayBuffer;
|
||||
*/
|
||||
slice(begin: number, end?: number): SharedArrayBuffer;
|
||||
readonly [Symbol.species]: SharedArrayBuffer;
|
||||
readonly [Symbol.toStringTag]: "SharedArrayBuffer";
|
||||
}
|
||||
|
||||
Vendored
+27
-27
@@ -1,27 +1,27 @@
|
||||
interface String {
|
||||
/**
|
||||
* Pads the current string with a given string (possibly repeated) so that the resulting string reaches a given length.
|
||||
* The padding is applied from the start (left) of the current string.
|
||||
*
|
||||
* @param maxLength The length of the resulting string once the current string has been padded.
|
||||
* If this parameter is smaller than the current string's length, the current string will be returned as it is.
|
||||
*
|
||||
* @param fillString The string to pad the current string with.
|
||||
* If this string is too long, it will be truncated and the left-most part will be applied.
|
||||
* The default value for this parameter is " " (U+0020).
|
||||
*/
|
||||
padStart(maxLength: number, fillString?: string): string;
|
||||
|
||||
/**
|
||||
* Pads the current string with a given string (possibly repeated) so that the resulting string reaches a given length.
|
||||
* The padding is applied from the end (right) of the current string.
|
||||
*
|
||||
* @param maxLength The length of the resulting string once the current string has been padded.
|
||||
* If this parameter is smaller than the current string's length, the current string will be returned as it is.
|
||||
*
|
||||
* @param fillString The string to pad the current string with.
|
||||
* If this string is too long, it will be truncated and the left-most part will be applied.
|
||||
* The default value for this parameter is " " (U+0020).
|
||||
*/
|
||||
padEnd(maxLength: number, fillString?: string): string;
|
||||
}
|
||||
interface String {
|
||||
/**
|
||||
* Pads the current string with a given string (possibly repeated) so that the resulting string reaches a given length.
|
||||
* The padding is applied from the start (left) of the current string.
|
||||
*
|
||||
* @param maxLength The length of the resulting string once the current string has been padded.
|
||||
* If this parameter is smaller than the current string's length, the current string will be returned as it is.
|
||||
*
|
||||
* @param fillString The string to pad the current string with.
|
||||
* If this string is too long, it will be truncated and the left-most part will be applied.
|
||||
* The default value for this parameter is " " (U+0020).
|
||||
*/
|
||||
padStart(maxLength: number, fillString?: string): string;
|
||||
|
||||
/**
|
||||
* Pads the current string with a given string (possibly repeated) so that the resulting string reaches a given length.
|
||||
* The padding is applied from the end (right) of the current string.
|
||||
*
|
||||
* @param maxLength The length of the resulting string once the current string has been padded.
|
||||
* If this parameter is smaller than the current string's length, the current string will be returned as it is.
|
||||
*
|
||||
* @param fillString The string to pad the current string with.
|
||||
* If this string is too long, it will be truncated and the left-most part will be applied.
|
||||
* The default value for this parameter is " " (U+0020).
|
||||
*/
|
||||
padEnd(maxLength: number, fillString?: string): string;
|
||||
}
|
||||
|
||||
Vendored
+302
-138
File diff suppressed because it is too large
Load Diff
Vendored
+1
-1
@@ -29,7 +29,7 @@ interface TextStreamBase {
|
||||
|
||||
/**
|
||||
* Closes a text stream.
|
||||
* It is not necessary to close standard streams; they close automatically when the process ends. If
|
||||
* It is not necessary to close standard streams; they close automatically when the process ends. If
|
||||
* you close a standard stream, be aware that any other pointers to that standard stream become invalid.
|
||||
*/
|
||||
Close(): void;
|
||||
|
||||
Vendored
+2
-2
@@ -1,6 +1,6 @@
|
||||
|
||||
/////////////////////////////
|
||||
/// WorkerGlobalScope APIs
|
||||
/// WorkerGlobalScope APIs
|
||||
/////////////////////////////
|
||||
// These are only available in a Web Worker
|
||||
// These are only available in a Web Worker
|
||||
declare function importScripts(...urls: string[]): void;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/// <reference path="..\compiler\commandLineParser.ts" />
|
||||
/// <reference path="..\compiler\commandLineParser.ts" />
|
||||
/// <reference path="..\services\services.ts" />
|
||||
/// <reference path="session.ts" />
|
||||
/// <reference types="node" />
|
||||
|
||||
namespace ts.server {
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ function createCancellationToken(args: string[]): ServerCancellationToken {
|
||||
// when client wants to signal cancellation it should create a named pipe with name=<cancellationPipeName>
|
||||
// server will synchronously check the presence of the pipe and treat its existance as indicator that current request should be canceled.
|
||||
// in case if client prefers to use more fine-grained schema than one name for all request it can add '*' to the end of cancelellationPipeName.
|
||||
// in this case pipe name will be build dynamically as <cancellationPipeName><request_seq>.
|
||||
// in this case pipe name will be build dynamically as <cancellationPipeName><request_seq>.
|
||||
if (cancellationPipeName.charAt(cancellationPipeName.length - 1) === "*") {
|
||||
const namePrefix = cancellationPipeName.slice(0, -1);
|
||||
if (namePrefix.length === 0 || namePrefix.indexOf("*") >= 0) {
|
||||
@@ -48,7 +48,7 @@ function createCancellationToken(args: string[]): ServerCancellationToken {
|
||||
return {
|
||||
isCancellationRequested: () => perRequestPipeName !== undefined && pipeExists(perRequestPipeName),
|
||||
setRequest(requestId: number) {
|
||||
currentRequestId = currentRequestId;
|
||||
currentRequestId = requestId;
|
||||
perRequestPipeName = namePrefix + requestId;
|
||||
},
|
||||
resetRequest(requestId: number) {
|
||||
@@ -67,4 +67,4 @@ function createCancellationToken(args: string[]): ServerCancellationToken {
|
||||
};
|
||||
}
|
||||
}
|
||||
export = createCancellationToken;
|
||||
export = createCancellationToken;
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
"module": "commonjs",
|
||||
"types": [
|
||||
"node"
|
||||
],
|
||||
"lib": [
|
||||
"es6"
|
||||
]
|
||||
},
|
||||
"files": [
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
export class SessionClient implements LanguageService {
|
||||
private sequence: number = 0;
|
||||
private sequence = 0;
|
||||
private lineMaps: ts.Map<number[]> = ts.createMap<number[]>();
|
||||
private messages: string[] = [];
|
||||
private lastRenameEntry: RenameEntry;
|
||||
@@ -382,7 +382,9 @@ namespace ts.server {
|
||||
const end = this.lineOffsetToPosition(fileName, entry.end);
|
||||
return {
|
||||
fileName,
|
||||
textSpan: ts.createTextSpanFromBounds(start, end)
|
||||
textSpan: ts.createTextSpanFromBounds(start, end),
|
||||
kind: ScriptElementKind.unknown,
|
||||
displayParts: []
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/// <reference path="..\compiler\commandLineParser.ts" />
|
||||
/// <reference path="..\compiler\commandLineParser.ts" />
|
||||
/// <reference path="..\services\services.ts" />
|
||||
/// <reference path="utilities.ts" />
|
||||
/// <reference path="session.ts" />
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/// <reference path="..\services\services.ts" />
|
||||
/// <reference path="..\services\services.ts" />
|
||||
/// <reference path="utilities.ts"/>
|
||||
/// <reference path="scriptInfo.ts"/>
|
||||
/// <reference path="lsHost.ts"/>
|
||||
|
||||
@@ -621,6 +621,11 @@ namespace ts.server.protocol {
|
||||
* True if the occurrence is a write location, false otherwise.
|
||||
*/
|
||||
isWriteAccess: boolean;
|
||||
|
||||
/**
|
||||
* True if the occurrence is in a string, undefined otherwise;
|
||||
*/
|
||||
isInString?: true;
|
||||
}
|
||||
|
||||
export interface OccurrencesResponse extends Response {
|
||||
@@ -2127,6 +2132,17 @@ namespace ts.server.protocol {
|
||||
payload: any;
|
||||
}
|
||||
|
||||
export type TypesInstallerInitializationFailedEventName = "typesInstallerInitializationFailed";
|
||||
|
||||
export interface TypesInstallerInitializationFailedEvent extends Event {
|
||||
event: TypesInstallerInitializationFailedEventName;
|
||||
body: TypesInstallerInitializationFailedEventBody;
|
||||
}
|
||||
|
||||
export interface TypesInstallerInitializationFailedEventBody {
|
||||
message: string;
|
||||
}
|
||||
|
||||
export type TypingsInstalledTelemetryEventName = "typingsInstalled";
|
||||
|
||||
export interface TypingsInstalledTelemetryEventBody extends TelemetryEventBody {
|
||||
|
||||
+51
-28
@@ -131,6 +131,14 @@ namespace ts.server {
|
||||
constructor(private readonly logFilename: string,
|
||||
private readonly traceToConsole: boolean,
|
||||
private readonly level: LogLevel) {
|
||||
if (this.logFilename) {
|
||||
try {
|
||||
this.fd = fs.openSync(this.logFilename, "w");
|
||||
}
|
||||
catch (_) {
|
||||
// swallow the error and keep logging disabled if file cannot be opened
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static padStringRight(str: string, padding: string) {
|
||||
@@ -175,11 +183,6 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
msg(s: string, type: Msg.Types = Msg.Err) {
|
||||
if (this.fd < 0) {
|
||||
if (this.logFilename) {
|
||||
this.fd = fs.openSync(this.logFilename, "w");
|
||||
}
|
||||
}
|
||||
if (this.fd >= 0 || this.traceToConsole) {
|
||||
s = s + "\n";
|
||||
const prefix = Logger.padStringRight(type + " " + this.seq.toString(), " ");
|
||||
@@ -301,11 +304,23 @@ namespace ts.server {
|
||||
});
|
||||
}
|
||||
|
||||
private handleMessage(response: SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes) {
|
||||
private handleMessage(response: SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes | InitializationFailedResponse) {
|
||||
if (this.logger.hasLevel(LogLevel.verbose)) {
|
||||
this.logger.info(`Received response: ${JSON.stringify(response)}`);
|
||||
}
|
||||
|
||||
if (response.kind === EventInitializationFailed) {
|
||||
if (!this.eventSender) {
|
||||
return;
|
||||
}
|
||||
const body: protocol.TypesInstallerInitializationFailedEventBody = {
|
||||
message: response.message
|
||||
};
|
||||
const eventName: protocol.TypesInstallerInitializationFailedEventName = "typesInstallerInitializationFailed";
|
||||
this.eventSender.event(body, eventName);
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.kind === EventBeginInstallTypes) {
|
||||
if (!this.eventSender) {
|
||||
return;
|
||||
@@ -410,6 +425,9 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
function parseLoggingEnvironmentString(logEnvStr: string): LogOptions {
|
||||
if (!logEnvStr) {
|
||||
return {};
|
||||
}
|
||||
const logEnv: LogOptions = { logToFile: true };
|
||||
const args = logEnvStr.split(" ");
|
||||
const len = args.length - 1;
|
||||
@@ -422,8 +440,8 @@ namespace ts.server {
|
||||
logEnv.file = stripQuotes(value);
|
||||
break;
|
||||
case "-level":
|
||||
const level: LogLevel = (<any>LogLevel)[value];
|
||||
logEnv.detailLevel = typeof level === "number" ? level : LogLevel.normal;
|
||||
const level = getLogLevel(value);
|
||||
logEnv.detailLevel = level !== undefined ? level : LogLevel.normal;
|
||||
break;
|
||||
case "-traceToConsole":
|
||||
logEnv.traceToConsole = value.toLowerCase() === "true";
|
||||
@@ -437,28 +455,32 @@ namespace ts.server {
|
||||
return logEnv;
|
||||
}
|
||||
|
||||
// TSS_LOG "{ level: "normal | verbose | terse", file?: string}"
|
||||
function createLoggerFromEnv() {
|
||||
let fileName: string = undefined;
|
||||
let detailLevel = LogLevel.normal;
|
||||
let traceToConsole = false;
|
||||
const logEnvStr = process.env["TSS_LOG"];
|
||||
if (logEnvStr) {
|
||||
const logEnv = parseLoggingEnvironmentString(logEnvStr);
|
||||
if (logEnv.logToFile) {
|
||||
if (logEnv.file) {
|
||||
fileName = logEnv.file;
|
||||
}
|
||||
else {
|
||||
fileName = __dirname + "/.log" + process.pid.toString();
|
||||
function getLogLevel(level: string) {
|
||||
if (level) {
|
||||
const l = level.toLowerCase();
|
||||
for (const name in LogLevel) {
|
||||
if (isNaN(+name) && l === name.toLowerCase()) {
|
||||
return <LogLevel><any>LogLevel[name];
|
||||
}
|
||||
}
|
||||
if (logEnv.detailLevel) {
|
||||
detailLevel = logEnv.detailLevel;
|
||||
}
|
||||
traceToConsole = logEnv.traceToConsole;
|
||||
}
|
||||
return new Logger(fileName, traceToConsole, detailLevel);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// TSS_LOG "{ level: "normal | verbose | terse", file?: string}"
|
||||
function createLogger() {
|
||||
const cmdLineLogFileName = findArgument("--logFile");
|
||||
const cmdLineVerbosity = getLogLevel(findArgument("--logVerbosity"));
|
||||
const envLogOptions = parseLoggingEnvironmentString(process.env["TSS_LOG"]);
|
||||
|
||||
const logFileName = cmdLineLogFileName
|
||||
? stripQuotes(cmdLineLogFileName)
|
||||
: envLogOptions.logToFile
|
||||
? envLogOptions.file || (__dirname + "/.log" + process.pid.toString())
|
||||
: undefined;
|
||||
|
||||
const logVerbosity = cmdLineVerbosity || envLogOptions.detailLevel;
|
||||
return new Logger(logFileName, envLogOptions.traceToConsole, logVerbosity);
|
||||
}
|
||||
// This places log file in the directory containing editorServices.js
|
||||
// TODO: check that this location is writable
|
||||
@@ -555,7 +577,6 @@ namespace ts.server {
|
||||
// to increase the chunk size or decrease the interval
|
||||
// time dynamically to match the large reference set?
|
||||
const pollingWatchedFileSet = createPollingWatchedFileSet();
|
||||
const logger = createLoggerFromEnv();
|
||||
|
||||
const pending: Buffer[] = [];
|
||||
let canWrite = true;
|
||||
@@ -607,6 +628,8 @@ namespace ts.server {
|
||||
return s.length > 2 && s.charCodeAt(0) === CharacterCodes.slash && s.charCodeAt(1) === CharacterCodes.slash;
|
||||
}
|
||||
|
||||
const logger = createLogger();
|
||||
|
||||
const sys = <ServerHost>ts.sys;
|
||||
// use watchGuard process on Windows when node version is 4 or later
|
||||
const useWatchGuard = process.platform === "win32" && getNodeMajorVersion() >= 4;
|
||||
|
||||
+10
-11
@@ -26,14 +26,7 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
function shouldSkipSematicCheck(project: Project) {
|
||||
if (project.getCompilerOptions().skipLibCheck !== undefined) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((project.projectKind === ProjectKind.Inferred || project.projectKind === ProjectKind.External) && project.isJsOnlyProject()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return (project.projectKind === ProjectKind.Inferred || project.projectKind === ProjectKind.External) && project.isJsOnlyProject();
|
||||
}
|
||||
|
||||
interface FileStart {
|
||||
@@ -651,16 +644,21 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
return occurrences.map(occurrence => {
|
||||
const { fileName, isWriteAccess, textSpan } = occurrence;
|
||||
const { fileName, isWriteAccess, textSpan, isInString } = occurrence;
|
||||
const scriptInfo = project.getScriptInfo(fileName);
|
||||
const start = scriptInfo.positionToLineOffset(textSpan.start);
|
||||
const end = scriptInfo.positionToLineOffset(ts.textSpanEnd(textSpan));
|
||||
return {
|
||||
const result: protocol.OccurrencesResponseItem = {
|
||||
start,
|
||||
end,
|
||||
file: fileName,
|
||||
isWriteAccess,
|
||||
};
|
||||
// no need to serialize the property if it is not true
|
||||
if (isInString) {
|
||||
result.isInString = isInString;
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1420,8 +1418,9 @@ namespace ts.server {
|
||||
const scriptInfo = project.getScriptInfoForNormalizedPath(file);
|
||||
const startPosition = getStartPosition();
|
||||
const endPosition = getEndPosition();
|
||||
const formatOptions = this.projectService.getFormatCodeOptions(file);
|
||||
|
||||
const codeActions = project.getLanguageService().getCodeFixesAtPosition(file, startPosition, endPosition, args.errorCodes);
|
||||
const codeActions = project.getLanguageService().getCodeFixesAtPosition(file, startPosition, endPosition, args.errorCodes, formatOptions);
|
||||
if (!codeActions) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace ts.server {
|
||||
export const ActionInvalidate: ActionInvalidate = "action::invalidate";
|
||||
export const EventBeginInstallTypes: EventBeginInstallTypes = "event::beginInstallTypes";
|
||||
export const EventEndInstallTypes: EventEndInstallTypes = "event::endInstallTypes";
|
||||
export const EventInitializationFailed: EventInitializationFailed = "event::initializationFailed";
|
||||
|
||||
export namespace Arguments {
|
||||
export const GlobalCacheLocation = "--globalTypingsCacheLocation";
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
"target": "es5",
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"declaration": true
|
||||
"declaration": true,
|
||||
"types": []
|
||||
},
|
||||
"files": [
|
||||
"editorServices.ts",
|
||||
|
||||
+7
-1
@@ -47,9 +47,15 @@ declare namespace ts.server {
|
||||
export type ActionInvalidate = "action::invalidate";
|
||||
export type EventBeginInstallTypes = "event::beginInstallTypes";
|
||||
export type EventEndInstallTypes = "event::endInstallTypes";
|
||||
export type EventInitializationFailed = "event::initializationFailed";
|
||||
|
||||
export interface TypingInstallerResponse {
|
||||
readonly kind: ActionSet | ActionInvalidate | EventBeginInstallTypes | EventEndInstallTypes;
|
||||
readonly kind: ActionSet | ActionInvalidate | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed;
|
||||
}
|
||||
|
||||
export interface InitializationFailedResponse extends TypingInstallerResponse {
|
||||
readonly kind: EventInitializationFailed;
|
||||
readonly message: string;
|
||||
}
|
||||
|
||||
export interface ProjectResponse extends TypingInstallerResponse {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/// <reference path="typingsInstaller.ts"/>
|
||||
/// <reference path="typingsInstaller.ts"/>
|
||||
/// <reference types="node" />
|
||||
|
||||
namespace ts.server.typingsInstaller {
|
||||
@@ -13,14 +13,20 @@ namespace ts.server.typingsInstaller {
|
||||
} = require("path");
|
||||
|
||||
class FileLog implements Log {
|
||||
private logEnabled = true;
|
||||
constructor(private readonly logFile?: string) {
|
||||
}
|
||||
|
||||
isEnabled() {
|
||||
return this.logFile !== undefined;
|
||||
return this.logEnabled && this.logFile !== undefined;
|
||||
}
|
||||
writeLine(text: string) {
|
||||
fs.appendFileSync(this.logFile, text + sys.newLine);
|
||||
try {
|
||||
fs.appendFileSync(this.logFile, text + sys.newLine);
|
||||
}
|
||||
catch (e) {
|
||||
this.logEnabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +74,8 @@ namespace ts.server.typingsInstaller {
|
||||
private readonly npmPath: string;
|
||||
readonly typesRegistry: Map<void>;
|
||||
|
||||
private delayedInitializationError: InitializationFailedResponse;
|
||||
|
||||
constructor(globalTypingsCacheLocation: string, throttleLimit: number, log: Log) {
|
||||
super(
|
||||
sys,
|
||||
@@ -93,6 +101,11 @@ namespace ts.server.typingsInstaller {
|
||||
if (this.log.isEnabled()) {
|
||||
this.log.writeLine(`Error updating ${TypesRegistryPackageName} package: ${(<Error>e).message}`);
|
||||
}
|
||||
// store error info to report it later when it is known that server is already listening to events from typings installer
|
||||
this.delayedInitializationError = {
|
||||
kind: "event::initializationFailed",
|
||||
message: (<Error>e).message
|
||||
};
|
||||
}
|
||||
|
||||
this.typesRegistry = loadTypesRegistryFile(getTypesRegistryFileLocation(globalTypingsCacheLocation), this.installTypingHost, this.log);
|
||||
@@ -100,6 +113,11 @@ namespace ts.server.typingsInstaller {
|
||||
|
||||
listen() {
|
||||
process.on("message", (req: DiscoverTypings | CloseProject) => {
|
||||
if (this.delayedInitializationError) {
|
||||
// report initializationFailed error
|
||||
this.sendResponse(this.delayedInitializationError);
|
||||
this.delayedInitializationError = undefined;
|
||||
}
|
||||
switch (req.kind) {
|
||||
case "discover":
|
||||
this.install(req);
|
||||
@@ -110,7 +128,7 @@ namespace ts.server.typingsInstaller {
|
||||
});
|
||||
}
|
||||
|
||||
protected sendResponse(response: SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes) {
|
||||
protected sendResponse(response: SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes | InitializationFailedResponse) {
|
||||
if (this.log.isEnabled()) {
|
||||
this.log.writeLine(`Sending response: ${JSON.stringify(response)}`);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
"outFile": "../../../built/local/typingsInstaller.js",
|
||||
"types": [
|
||||
"node"
|
||||
],
|
||||
"lib": [
|
||||
"es6",
|
||||
"scripthost"
|
||||
]
|
||||
},
|
||||
"files": [
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/// <reference path="../../compiler/core.ts" />
|
||||
/// <reference path="../../compiler/core.ts" />
|
||||
/// <reference path="../../compiler/moduleNameResolver.ts" />
|
||||
/// <reference path="../../services/jsTyping.ts"/>
|
||||
/// <reference path="../types.ts"/>
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
{
|
||||
"extends": "../../tsconfig-base",
|
||||
"extends": "../../tsconfig-base",
|
||||
"compilerOptions": {
|
||||
"removeComments": true,
|
||||
"outFile": "../../../built/local/watchGuard.js"
|
||||
"outFile": "../../../built/local/watchGuard.js",
|
||||
"types": [
|
||||
"node"
|
||||
],
|
||||
"lib": [
|
||||
"es6"
|
||||
]
|
||||
},
|
||||
"files": [
|
||||
"watchGuard.ts"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* @internal */
|
||||
/* @internal */
|
||||
namespace ts {
|
||||
export interface CodeFix {
|
||||
errorCodes: number[];
|
||||
@@ -13,6 +13,7 @@ namespace ts {
|
||||
newLineCharacter: string;
|
||||
host: LanguageServiceHost;
|
||||
cancellationToken: CancellationToken;
|
||||
rulesProvider: formatting.RulesProvider;
|
||||
}
|
||||
|
||||
export namespace codefix {
|
||||
|
||||
@@ -26,22 +26,13 @@ namespace ts.codefix {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const newPosition = getOpenBraceEnd(<ConstructorDeclaration>constructor, sourceFile);
|
||||
const changes = [{
|
||||
fileName: sourceFile.fileName, textChanges: [{
|
||||
newText: superCall.getText(sourceFile),
|
||||
span: { start: newPosition, length: 0 }
|
||||
},
|
||||
{
|
||||
newText: "",
|
||||
span: { start: superCall.getStart(sourceFile), length: superCall.getWidth(sourceFile) }
|
||||
}]
|
||||
}];
|
||||
const changeTracker = textChanges.ChangeTracker.fromCodeFixContext(context);
|
||||
changeTracker.insertNodeAfter(sourceFile, getOpenBrace(<ConstructorDeclaration>constructor, sourceFile), superCall, { suffix: context.newLineCharacter });
|
||||
changeTracker.deleteNode(sourceFile, superCall);
|
||||
|
||||
return [{
|
||||
description: getLocaleSpecificMessage(Diagnostics.Make_super_call_the_first_statement_in_the_constructor),
|
||||
changes
|
||||
changes: changeTracker.getChanges()
|
||||
}];
|
||||
|
||||
function findSuperCall(n: Node): ExpressionStatement {
|
||||
|
||||
@@ -10,10 +10,13 @@ namespace ts.codefix {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const newPosition = getOpenBraceEnd(<ConstructorDeclaration>token.parent, sourceFile);
|
||||
const changeTracker = textChanges.ChangeTracker.fromCodeFixContext(context);
|
||||
const superCall = createStatement(createCall(createSuper(), /*typeArguments*/ undefined, /*argumentsArray*/ emptyArray));
|
||||
changeTracker.insertNodeAfter(sourceFile, getOpenBrace(<ConstructorDeclaration>token.parent, sourceFile), superCall, { suffix: context.newLineCharacter });
|
||||
|
||||
return [{
|
||||
description: getLocaleSpecificMessage(Diagnostics.Add_missing_super_call),
|
||||
changes: [{ fileName: sourceFile.fileName, textChanges: [{ newText: "super();", span: { start: newPosition, length: 0 } }] }]
|
||||
changes: changeTracker.getChanges()
|
||||
}];
|
||||
}
|
||||
});
|
||||
|
||||
@@ -21,26 +21,20 @@ namespace ts.codefix {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let changeStart = extendsToken.getStart(sourceFile);
|
||||
let changeEnd = extendsToken.getEnd();
|
||||
const textChanges: TextChange[] = [{ newText: " implements", span: { start: changeStart, length: changeEnd - changeStart } }];
|
||||
const changeTracker = textChanges.ChangeTracker.fromCodeFixContext(context);
|
||||
changeTracker.replaceNode(sourceFile, extendsToken, createToken(SyntaxKind.ImplementsKeyword));
|
||||
|
||||
// We replace existing keywords with commas.
|
||||
for (let i = 1; i < heritageClauses.length; i++) {
|
||||
const keywordToken = heritageClauses[i].getFirstToken();
|
||||
if (keywordToken) {
|
||||
changeStart = keywordToken.getStart(sourceFile);
|
||||
changeEnd = keywordToken.getEnd();
|
||||
textChanges.push({ newText: ",", span: { start: changeStart, length: changeEnd - changeStart } });
|
||||
changeTracker.replaceNode(sourceFile, keywordToken, createToken(SyntaxKind.CommaToken));
|
||||
}
|
||||
}
|
||||
|
||||
const result = [{
|
||||
description: getLocaleSpecificMessage(Diagnostics.Change_extends_to_implements),
|
||||
changes: [{
|
||||
fileName: sourceFile.fileName,
|
||||
textChanges: textChanges
|
||||
}]
|
||||
changes: changeTracker.getChanges()
|
||||
}];
|
||||
|
||||
return result;
|
||||
|
||||
@@ -5,11 +5,15 @@ namespace ts.codefix {
|
||||
getCodeActions: (context: CodeFixContext) => {
|
||||
const sourceFile = context.sourceFile;
|
||||
const token = getTokenAtPosition(sourceFile, context.span.start);
|
||||
const start = token.getStart(sourceFile);
|
||||
if (token.kind !== SyntaxKind.Identifier) {
|
||||
return undefined;
|
||||
}
|
||||
const changeTracker = textChanges.ChangeTracker.fromCodeFixContext(context);
|
||||
changeTracker.replaceNode(sourceFile, token, createPropertyAccess(createThis(), <Identifier>token));
|
||||
|
||||
return [{
|
||||
description: getLocaleSpecificMessage(Diagnostics.Add_this_to_unresolved_variable),
|
||||
changes: [{ fileName: sourceFile.fileName, textChanges: [{ newText: "this.", span: { start, length: 0 } }] }]
|
||||
changes: changeTracker.getChanges()
|
||||
}];
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* @internal */
|
||||
/* @internal */
|
||||
namespace ts.codefix {
|
||||
|
||||
type ImportCodeActionKind = "CodeChange" | "InsertingIntoExistingImport" | "NewImport";
|
||||
@@ -130,7 +130,7 @@ namespace ts.codefix {
|
||||
|
||||
// this is a module id -> module import declaration map
|
||||
const cachedImportDeclarations: (ImportDeclaration | ImportEqualsDeclaration)[][] = [];
|
||||
let cachedNewImportInsertPosition: number;
|
||||
let lastImportDeclaration: Node;
|
||||
|
||||
const currentTokenMeaning = getMeaningFromLocation(token);
|
||||
if (context.errorCode === Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead.code) {
|
||||
@@ -138,14 +138,14 @@ namespace ts.codefix {
|
||||
return getCodeActionForImport(symbol, /*isDefault*/ false, /*isNamespaceImport*/ true);
|
||||
}
|
||||
|
||||
const allPotentialModules = checker.getAmbientModules();
|
||||
const candidateModules = checker.getAmbientModules();
|
||||
for (const otherSourceFile of allSourceFiles) {
|
||||
if (otherSourceFile !== sourceFile && isExternalOrCommonJsModule(otherSourceFile)) {
|
||||
allPotentialModules.push(otherSourceFile.symbol);
|
||||
candidateModules.push(otherSourceFile.symbol);
|
||||
}
|
||||
}
|
||||
|
||||
for (const moduleSymbol of allPotentialModules) {
|
||||
for (const moduleSymbol of candidateModules) {
|
||||
context.cancellationToken.throwIfCancellationRequested();
|
||||
|
||||
// check the default export
|
||||
@@ -277,14 +277,12 @@ namespace ts.codefix {
|
||||
* If the existing import declaration already has a named import list, just
|
||||
* insert the identifier into that list.
|
||||
*/
|
||||
const textChange = getTextChangeForImportClause(namedImportDeclaration.importClause);
|
||||
const fileTextChanges = getTextChangeForImportClause(namedImportDeclaration.importClause);
|
||||
const moduleSpecifierWithoutQuotes = stripQuotes(namedImportDeclaration.moduleSpecifier.getText());
|
||||
actions.push(createCodeAction(
|
||||
Diagnostics.Add_0_to_existing_import_declaration_from_1,
|
||||
[name, moduleSpecifierWithoutQuotes],
|
||||
textChange.newText,
|
||||
textChange.span,
|
||||
sourceFile.fileName,
|
||||
fileTextChanges,
|
||||
"InsertingIntoExistingImport",
|
||||
moduleSpecifierWithoutQuotes
|
||||
));
|
||||
@@ -302,49 +300,30 @@ namespace ts.codefix {
|
||||
return declaration.moduleReference.getText();
|
||||
}
|
||||
|
||||
function getTextChangeForImportClause(importClause: ImportClause): TextChange {
|
||||
const newImportText = isDefault ? `default as ${name}` : name;
|
||||
function getTextChangeForImportClause(importClause: ImportClause): FileTextChanges[] {
|
||||
const importList = <NamedImports>importClause.namedBindings;
|
||||
const newImportSpecifier = createImportSpecifier(/*propertyName*/ undefined, createIdentifier(name));
|
||||
// case 1:
|
||||
// original text: import default from "module"
|
||||
// change to: import default, { name } from "module"
|
||||
if (!importList && importClause.name) {
|
||||
const start = importClause.name.getEnd();
|
||||
return {
|
||||
newText: `, { ${newImportText} }`,
|
||||
span: { start, length: 0 }
|
||||
};
|
||||
}
|
||||
|
||||
// case 2:
|
||||
// original text: import {} from "module"
|
||||
// change to: import { name } from "module"
|
||||
if (importList.elements.length === 0) {
|
||||
const start = importList.getStart();
|
||||
return {
|
||||
newText: `{ ${newImportText} }`,
|
||||
span: { start, length: importList.getEnd() - start }
|
||||
};
|
||||
if (!importList || importList.elements.length === 0) {
|
||||
const newImportClause = createImportClause(importClause.name, createNamedImports([newImportSpecifier]));
|
||||
return createChangeTracker().replaceNode(sourceFile, importClause, newImportClause).getChanges();
|
||||
}
|
||||
|
||||
// case 3:
|
||||
// original text: import { foo, bar } from "module"
|
||||
// change to: import { foo, bar, name } from "module"
|
||||
const insertPoint = importList.elements[importList.elements.length - 1].getEnd();
|
||||
/**
|
||||
* If the import list has one import per line, preserve that. Otherwise, insert on same line as last element
|
||||
* import {
|
||||
* foo
|
||||
* } from "./module";
|
||||
*/
|
||||
const startLine = getLineOfLocalPosition(sourceFile, importList.getStart());
|
||||
const endLine = getLineOfLocalPosition(sourceFile, importList.getEnd());
|
||||
const oneImportPerLine = endLine - startLine > importList.elements.length;
|
||||
|
||||
return {
|
||||
newText: `,${oneImportPerLine ? context.newLineCharacter : " "}${newImportText}`,
|
||||
span: { start: insertPoint, length: 0 }
|
||||
};
|
||||
return createChangeTracker().insertNodeInListAfter(
|
||||
sourceFile,
|
||||
importList.elements[importList.elements.length - 1],
|
||||
newImportSpecifier).getChanges();
|
||||
}
|
||||
|
||||
function getCodeActionForNamespaceImport(declaration: ImportDeclaration | ImportEqualsDeclaration): ImportCodeAction {
|
||||
@@ -370,48 +349,47 @@ namespace ts.codefix {
|
||||
return createCodeAction(
|
||||
Diagnostics.Change_0_to_1,
|
||||
[name, `${namespacePrefix}.${name}`],
|
||||
`${namespacePrefix}.`,
|
||||
{ start: token.getStart(), length: 0 },
|
||||
sourceFile.fileName,
|
||||
createChangeTracker().replaceNode(sourceFile, token, createPropertyAccess(createIdentifier(namespacePrefix), name)).getChanges(),
|
||||
"CodeChange"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function getCodeActionForNewImport(moduleSpecifier?: string): ImportCodeAction {
|
||||
if (!cachedNewImportInsertPosition) {
|
||||
if (!lastImportDeclaration) {
|
||||
// insert after any existing imports
|
||||
let lastModuleSpecifierEnd = -1;
|
||||
for (const moduleSpecifier of sourceFile.imports) {
|
||||
const end = moduleSpecifier.getEnd();
|
||||
if (!lastModuleSpecifierEnd || end > lastModuleSpecifierEnd) {
|
||||
lastModuleSpecifierEnd = end;
|
||||
for (let i = sourceFile.statements.length - 1; i >= 0; i--) {
|
||||
const statement = sourceFile.statements[i];
|
||||
if (statement.kind === SyntaxKind.ImportEqualsDeclaration || statement.kind === SyntaxKind.ImportDeclaration) {
|
||||
lastImportDeclaration = statement;
|
||||
break;
|
||||
}
|
||||
}
|
||||
cachedNewImportInsertPosition = lastModuleSpecifierEnd > 0 ? sourceFile.getLineEndOfPosition(lastModuleSpecifierEnd) : sourceFile.getStart();
|
||||
}
|
||||
|
||||
const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames);
|
||||
const moduleSpecifierWithoutQuotes = stripQuotes(moduleSpecifier || getModuleSpecifierForNewImport());
|
||||
const importStatementText = isDefault
|
||||
? `import ${name} from "${moduleSpecifierWithoutQuotes}"`
|
||||
const changeTracker = createChangeTracker();
|
||||
const importClause = isDefault
|
||||
? createImportClause(createIdentifier(name), /*namedBindings*/ undefined)
|
||||
: isNamespaceImport
|
||||
? `import * as ${name} from "${moduleSpecifierWithoutQuotes}"`
|
||||
: `import { ${name} } from "${moduleSpecifierWithoutQuotes}"`;
|
||||
? createImportClause(/*name*/ undefined, createNamespaceImport(createIdentifier(name)))
|
||||
: createImportClause(/*name*/ undefined, createNamedImports([createImportSpecifier(/*propertyName*/ undefined, createIdentifier(name))]));
|
||||
const importDecl = createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, importClause, createLiteral(moduleSpecifierWithoutQuotes));
|
||||
if (!lastImportDeclaration) {
|
||||
changeTracker.insertNodeAt(sourceFile, sourceFile.getStart(), importDecl, { suffix: `${context.newLineCharacter}${context.newLineCharacter}` });
|
||||
}
|
||||
else {
|
||||
changeTracker.insertNodeAfter(sourceFile, lastImportDeclaration, importDecl, { suffix: context.newLineCharacter });
|
||||
}
|
||||
|
||||
// if this file doesn't have any import statements, insert an import statement and then insert a new line
|
||||
// between the only import statement and user code. Otherwise just insert the statement because chances
|
||||
// are there are already a new line seperating code and import statements.
|
||||
const newText = cachedNewImportInsertPosition === sourceFile.getStart()
|
||||
? `${importStatementText};${context.newLineCharacter}${context.newLineCharacter}`
|
||||
: `${context.newLineCharacter}${importStatementText};`;
|
||||
|
||||
return createCodeAction(
|
||||
Diagnostics.Import_0_from_1,
|
||||
[name, `"${moduleSpecifierWithoutQuotes}"`],
|
||||
newText,
|
||||
{ start: cachedNewImportInsertPosition, length: 0 },
|
||||
sourceFile.fileName,
|
||||
changeTracker.getChanges(),
|
||||
"NewImport",
|
||||
moduleSpecifierWithoutQuotes
|
||||
);
|
||||
@@ -576,17 +554,19 @@ namespace ts.codefix {
|
||||
|
||||
}
|
||||
|
||||
function createChangeTracker() {
|
||||
return textChanges.ChangeTracker.fromCodeFixContext(context);
|
||||
}
|
||||
|
||||
function createCodeAction(
|
||||
description: DiagnosticMessage,
|
||||
diagnosticArgs: string[],
|
||||
newText: string,
|
||||
span: TextSpan,
|
||||
fileName: string,
|
||||
changes: FileTextChanges[],
|
||||
kind: ImportCodeActionKind,
|
||||
moduleSpecifier?: string): ImportCodeAction {
|
||||
return {
|
||||
description: formatMessage.apply(undefined, [undefined, description].concat(<any[]>diagnosticArgs)),
|
||||
changes: [{ fileName, textChanges: [{ newText, span }] }],
|
||||
changes,
|
||||
kind,
|
||||
moduleSpecifier
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* @internal */
|
||||
/* @internal */
|
||||
namespace ts.codefix {
|
||||
registerCodeFix({
|
||||
errorCodes: [
|
||||
@@ -25,17 +25,17 @@ namespace ts.codefix {
|
||||
const forStatement = <ForStatement>token.parent.parent.parent;
|
||||
const forInitializer = <VariableDeclarationList>forStatement.initializer;
|
||||
if (forInitializer.declarations.length === 1) {
|
||||
return createCodeFixToRemoveNode(forInitializer);
|
||||
return deleteNode(forInitializer);
|
||||
}
|
||||
else {
|
||||
return removeSingleItem(forInitializer.declarations, token);
|
||||
return deleteNodeInList(token.parent);
|
||||
}
|
||||
|
||||
case SyntaxKind.ForOfStatement:
|
||||
const forOfStatement = <ForOfStatement>token.parent.parent.parent;
|
||||
if (forOfStatement.initializer.kind === SyntaxKind.VariableDeclarationList) {
|
||||
const forOfInitializer = <VariableDeclarationList>forOfStatement.initializer;
|
||||
return createCodeFix("{}", forOfInitializer.declarations[0].getStart(), forOfInitializer.declarations[0].getWidth());
|
||||
return replaceNode(forOfInitializer.declarations[0], createObjectLiteral());
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -47,51 +47,59 @@ namespace ts.codefix {
|
||||
case SyntaxKind.CatchClause:
|
||||
const catchClause = <CatchClause>token.parent.parent;
|
||||
const parameter = catchClause.variableDeclaration.getChildren()[0];
|
||||
return createCodeFixToRemoveNode(parameter);
|
||||
return deleteNode(parameter);
|
||||
|
||||
default:
|
||||
const variableStatement = <VariableStatement>token.parent.parent.parent;
|
||||
if (variableStatement.declarationList.declarations.length === 1) {
|
||||
return createCodeFixToRemoveNode(variableStatement);
|
||||
return deleteNode(variableStatement);
|
||||
}
|
||||
else {
|
||||
const declarations = variableStatement.declarationList.declarations;
|
||||
return removeSingleItem(declarations, token);
|
||||
return deleteNodeInList(token.parent);
|
||||
}
|
||||
}
|
||||
|
||||
case SyntaxKind.TypeParameter:
|
||||
const typeParameters = (<DeclarationWithTypeParameters>token.parent.parent).typeParameters;
|
||||
if (typeParameters.length === 1) {
|
||||
return createCodeFix("", token.parent.pos - 1, token.parent.end - token.parent.pos + 2);
|
||||
const previousToken = getTokenAtPosition(sourceFile, typeParameters.pos - 1);
|
||||
if (!previousToken || previousToken.kind !== SyntaxKind.LessThanToken) {
|
||||
return deleteRange(typeParameters);
|
||||
}
|
||||
const nextToken = getTokenAtPosition(sourceFile, typeParameters.end);
|
||||
if (!nextToken || nextToken.kind !== SyntaxKind.GreaterThanToken) {
|
||||
return deleteRange(typeParameters);
|
||||
}
|
||||
return deleteNodeRange(previousToken, nextToken);
|
||||
}
|
||||
else {
|
||||
return removeSingleItem(typeParameters, token);
|
||||
return deleteNodeInList(token.parent);
|
||||
}
|
||||
|
||||
case ts.SyntaxKind.Parameter:
|
||||
const functionDeclaration = <FunctionDeclaration>token.parent.parent;
|
||||
if (functionDeclaration.parameters.length === 1) {
|
||||
return createCodeFixToRemoveNode(token.parent);
|
||||
return deleteNode(token.parent);
|
||||
}
|
||||
else {
|
||||
return removeSingleItem(functionDeclaration.parameters, token);
|
||||
return deleteNodeInList(token.parent);
|
||||
}
|
||||
|
||||
// handle case where 'import a = A;'
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
const importEquals = findImportDeclaration(token);
|
||||
return createCodeFixToRemoveNode(importEquals);
|
||||
const importEquals = getAncestor(token, SyntaxKind.ImportEqualsDeclaration);
|
||||
return deleteNode(importEquals);
|
||||
|
||||
case SyntaxKind.ImportSpecifier:
|
||||
const namedImports = <NamedImports>token.parent.parent;
|
||||
if (namedImports.elements.length === 1) {
|
||||
// Only 1 import and it is unused. So the entire declaration should be removed.
|
||||
const importSpec = findImportDeclaration(token);
|
||||
return createCodeFixToRemoveNode(importSpec);
|
||||
const importSpec = getAncestor(token, SyntaxKind.ImportDeclaration);
|
||||
return deleteNode(importSpec);
|
||||
}
|
||||
else {
|
||||
return removeSingleItem(namedImports.elements, token);
|
||||
// delete import specifier
|
||||
return deleteNodeInList(token.parent);
|
||||
}
|
||||
|
||||
// handle case where "import d, * as ns from './file'"
|
||||
@@ -99,98 +107,79 @@ namespace ts.codefix {
|
||||
case SyntaxKind.ImportClause: // this covers both 'import |d|' and 'import |d,| *'
|
||||
const importClause = <ImportClause>token.parent;
|
||||
if (!importClause.namedBindings) { // |import d from './file'| or |import * as ns from './file'|
|
||||
const importDecl = findImportDeclaration(importClause);
|
||||
return createCodeFixToRemoveNode(importDecl);
|
||||
const importDecl = getAncestor(importClause, SyntaxKind.ImportDeclaration);
|
||||
return deleteNode(importDecl);
|
||||
}
|
||||
else {
|
||||
// import |d,| * as ns from './file'
|
||||
const start = importClause.name.getStart();
|
||||
let end = findFirstNonSpaceCharPosStarting(importClause.name.end);
|
||||
if (sourceFile.text.charCodeAt(end) === CharacterCodes.comma) {
|
||||
end = findFirstNonSpaceCharPosStarting(end + 1);
|
||||
const start = importClause.name.getStart(sourceFile);
|
||||
const nextToken = getTokenAtPosition(sourceFile, importClause.name.end);
|
||||
if (nextToken && nextToken.kind === SyntaxKind.CommaToken) {
|
||||
// shift first non-whitespace position after comma to the start position of the node
|
||||
return deleteRange({ pos: start, end: skipTrivia(sourceFile.text, nextToken.end, /*stopAfterLineBreaks*/ false, /*stopAtComments*/true) });
|
||||
}
|
||||
else {
|
||||
return deleteNode(importClause.name);
|
||||
}
|
||||
|
||||
return createCodeFix("", start, end - start);
|
||||
}
|
||||
|
||||
case SyntaxKind.NamespaceImport:
|
||||
const namespaceImport = <NamespaceImport>token.parent;
|
||||
if (namespaceImport.name == token && !(<ImportClause>namespaceImport.parent).name) {
|
||||
const importDecl = findImportDeclaration(namespaceImport);
|
||||
return createCodeFixToRemoveNode(importDecl);
|
||||
const importDecl = getAncestor(namespaceImport, SyntaxKind.ImportDeclaration);
|
||||
return deleteNode(importDecl);
|
||||
}
|
||||
else {
|
||||
const start = (<ImportClause>namespaceImport.parent).name.end;
|
||||
return createCodeFix("", start, (<ImportClause>namespaceImport.parent).namedBindings.end - start);
|
||||
const previousToken = getTokenAtPosition(sourceFile, namespaceImport.pos - 1);
|
||||
if (previousToken && previousToken.kind === SyntaxKind.CommaToken) {
|
||||
const startPosition = textChanges.getAdjustedStartPosition(sourceFile, previousToken, {}, textChanges.Position.FullStart);
|
||||
return deleteRange({ pos: startPosition, end: namespaceImport.end });
|
||||
}
|
||||
return deleteRange(namespaceImport);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
case SyntaxKind.NamespaceImport:
|
||||
return createCodeFixToRemoveNode(token.parent);
|
||||
return deleteNode(token.parent);
|
||||
}
|
||||
if (isDeclarationName(token)) {
|
||||
return createCodeFixToRemoveNode(token.parent);
|
||||
return deleteNode(token.parent);
|
||||
}
|
||||
else if (isLiteralComputedPropertyDeclarationName(token)) {
|
||||
return createCodeFixToRemoveNode(token.parent.parent);
|
||||
return deleteNode(token.parent.parent);
|
||||
}
|
||||
else {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function findImportDeclaration(token: Node): Node {
|
||||
let importDecl = token;
|
||||
while (importDecl.kind != SyntaxKind.ImportDeclaration && importDecl.parent) {
|
||||
importDecl = importDecl.parent;
|
||||
}
|
||||
|
||||
return importDecl;
|
||||
function deleteNode(n: Node) {
|
||||
return makeChange(textChanges.ChangeTracker.fromCodeFixContext(context).deleteNode(sourceFile, n));
|
||||
}
|
||||
|
||||
function createCodeFixToRemoveNode(node: Node) {
|
||||
let end = node.getEnd();
|
||||
const endCharCode = sourceFile.text.charCodeAt(end);
|
||||
const afterEndCharCode = sourceFile.text.charCodeAt(end + 1);
|
||||
if (isLineBreak(endCharCode)) {
|
||||
end += 1;
|
||||
}
|
||||
// in the case of CR LF, you could have two consecutive new line characters for one new line.
|
||||
// this needs to be differenciated from two LF LF chars that actually mean two new lines.
|
||||
if (isLineBreak(afterEndCharCode) && endCharCode !== afterEndCharCode) {
|
||||
end += 1;
|
||||
}
|
||||
|
||||
const start = node.getStart();
|
||||
return createCodeFix("", start, end - start);
|
||||
function deleteRange(range: TextRange) {
|
||||
return makeChange(textChanges.ChangeTracker.fromCodeFixContext(context).deleteRange(sourceFile, range));
|
||||
}
|
||||
|
||||
function findFirstNonSpaceCharPosStarting(start: number) {
|
||||
while (isWhiteSpace(sourceFile.text.charCodeAt(start))) {
|
||||
start += 1;
|
||||
}
|
||||
return start;
|
||||
function deleteNodeInList(n: Node) {
|
||||
return makeChange(textChanges.ChangeTracker.fromCodeFixContext(context).deleteNodeInList(sourceFile, n));
|
||||
}
|
||||
|
||||
function createCodeFix(newText: string, start: number, length: number): CodeAction[] {
|
||||
function deleteNodeRange(start: Node, end: Node) {
|
||||
return makeChange(textChanges.ChangeTracker.fromCodeFixContext(context).deleteNodeRange(sourceFile, start, end));
|
||||
}
|
||||
|
||||
function replaceNode(n: Node, newNode: Node) {
|
||||
return makeChange(textChanges.ChangeTracker.fromCodeFixContext(context).replaceNode(sourceFile, n, newNode));
|
||||
}
|
||||
|
||||
function makeChange(changeTracker: textChanges.ChangeTracker) {
|
||||
return [{
|
||||
description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Remove_declaration_for_Colon_0), { 0: token.getText() }),
|
||||
changes: [{
|
||||
fileName: sourceFile.fileName,
|
||||
textChanges: [{ newText, span: { start, length } }]
|
||||
}]
|
||||
changes: changeTracker.getChanges()
|
||||
}];
|
||||
}
|
||||
|
||||
function removeSingleItem<T extends Node>(elements: NodeArray<T>, token: T): CodeAction[] {
|
||||
if (elements[0] === token.parent) {
|
||||
return createCodeFix("", token.parent.pos, token.parent.end - token.parent.pos + 1);
|
||||
}
|
||||
else {
|
||||
return createCodeFix("", token.parent.pos - 1, token.parent.end - token.parent.pos + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -447,8 +447,8 @@ namespace ts.Completions {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const { parent, kind } = contextToken;
|
||||
if (kind === SyntaxKind.DotToken) {
|
||||
let parent = contextToken.parent;
|
||||
if (contextToken.kind === SyntaxKind.DotToken) {
|
||||
if (parent.kind === SyntaxKind.PropertyAccessExpression) {
|
||||
node = (<PropertyAccessExpression>contextToken.parent).expression;
|
||||
isRightOfDot = true;
|
||||
@@ -464,16 +464,24 @@ namespace ts.Completions {
|
||||
}
|
||||
}
|
||||
else if (sourceFile.languageVariant === LanguageVariant.JSX) {
|
||||
switch (contextToken.parent.kind) {
|
||||
// <UI.Test /* completion position */ />
|
||||
// If the tagname is a property access expression, we will then walk up to the top most of property access expression.
|
||||
// Then, try to get a JSX container and its associated attributes type.
|
||||
if (parent && parent.kind === SyntaxKind.PropertyAccessExpression) {
|
||||
contextToken = parent;
|
||||
parent = parent.parent;
|
||||
}
|
||||
|
||||
switch (parent.kind) {
|
||||
case SyntaxKind.JsxClosingElement:
|
||||
if (kind === SyntaxKind.SlashToken) {
|
||||
if (contextToken.kind === SyntaxKind.SlashToken) {
|
||||
isStartingCloseTag = true;
|
||||
location = contextToken;
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.BinaryExpression:
|
||||
if (!((contextToken.parent as BinaryExpression).left.flags & NodeFlags.ThisNodeHasError)) {
|
||||
if (!((parent as BinaryExpression).left.flags & NodeFlags.ThisNodeHasError)) {
|
||||
// It has a left-hand side, so we're not in an opening JSX tag.
|
||||
break;
|
||||
}
|
||||
@@ -482,7 +490,7 @@ namespace ts.Completions {
|
||||
case SyntaxKind.JsxSelfClosingElement:
|
||||
case SyntaxKind.JsxElement:
|
||||
case SyntaxKind.JsxOpeningElement:
|
||||
if (kind === SyntaxKind.LessThanToken) {
|
||||
if (contextToken.kind === SyntaxKind.LessThanToken) {
|
||||
isRightOfOpenTag = true;
|
||||
location = contextToken;
|
||||
}
|
||||
@@ -950,6 +958,7 @@ namespace ts.Completions {
|
||||
case SyntaxKind.LessThanSlashToken:
|
||||
case SyntaxKind.SlashToken:
|
||||
case SyntaxKind.Identifier:
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
case SyntaxKind.JsxAttributes:
|
||||
case SyntaxKind.JsxAttribute:
|
||||
case SyntaxKind.JsxSpreadAttribute:
|
||||
|
||||
@@ -17,7 +17,8 @@ namespace ts.DocumentHighlights {
|
||||
}
|
||||
|
||||
function getSemanticDocumentHighlights(node: Node, typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFilesToSearch: SourceFile[]): DocumentHighlights[] {
|
||||
const referencedSymbols = FindAllReferences.getReferencedSymbolsForNode(typeChecker, cancellationToken, node, sourceFilesToSearch);
|
||||
const context = new FindAllReferences.DefaultFindReferencesContext(typeChecker, cancellationToken);
|
||||
const referencedSymbols = FindAllReferences.getReferencedSymbolsForNode(context, node, sourceFilesToSearch);
|
||||
return referencedSymbols && convertReferencedSymbols(referencedSymbols);
|
||||
}
|
||||
|
||||
@@ -37,7 +38,8 @@ namespace ts.DocumentHighlights {
|
||||
|
||||
documentHighlights.highlightSpans.push({
|
||||
textSpan: referenceEntry.textSpan,
|
||||
kind: referenceEntry.isWriteAccess ? HighlightSpanKind.writtenReference : HighlightSpanKind.reference
|
||||
kind: referenceEntry.isWriteAccess ? HighlightSpanKind.writtenReference : HighlightSpanKind.reference,
|
||||
isInString: referenceEntry.isInString
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace ts {
|
||||
namespace ts {
|
||||
/**
|
||||
* The document registry represents a store of SourceFile objects that can be shared between
|
||||
* multiple LanguageService instances. A LanguageService instance holds on the SourceFile (AST)
|
||||
|
||||
@@ -1,21 +1,75 @@
|
||||
/* @internal */
|
||||
/* @internal */
|
||||
namespace ts.FindAllReferences {
|
||||
|
||||
export interface FindReferencesContext<T extends DocumentSpan> {
|
||||
readonly typeChecker: TypeChecker;
|
||||
readonly cancellationToken: CancellationToken;
|
||||
getReferenceEntryFromNode(node: Node, isInString?: boolean): T;
|
||||
getReferenceEntryForSpanInFile(fileName: string, span: TextSpan): T;
|
||||
}
|
||||
|
||||
export class DefaultFindReferencesContext implements FindReferencesContext<ReferenceEntry> {
|
||||
constructor(readonly typeChecker: TypeChecker, readonly cancellationToken: CancellationToken) {
|
||||
}
|
||||
getReferenceEntryFromNode(node: Node, isInString?: boolean): ReferenceEntry {
|
||||
const reference = getReferenceEntryFromNode(node);
|
||||
if (isInString) {
|
||||
reference.isInString = true;
|
||||
}
|
||||
return reference;
|
||||
}
|
||||
getReferenceEntryForSpanInFile(fileName: string, textSpan: TextSpan): ReferenceEntry {
|
||||
return { textSpan, fileName, isWriteAccess: false, isDefinition: false };
|
||||
}
|
||||
}
|
||||
|
||||
export class FindImplementationsContext implements FindReferencesContext<ImplementationLocation> {
|
||||
constructor(readonly typeChecker: TypeChecker, readonly cancellationToken: CancellationToken) {
|
||||
}
|
||||
getReferenceEntryFromNode(node: Node): ImplementationLocation {
|
||||
const entry = <ImplementationLocation><any>getReferenceEntryFromNode(node);
|
||||
const symbol = this.typeChecker.getSymbolAtLocation(isDeclaration(node) && node.name ? node.name : node);
|
||||
if (symbol) {
|
||||
const def = getDefinition(symbol, node, this.typeChecker);
|
||||
entry.kind = def.kind;
|
||||
entry.displayParts = def.displayParts;
|
||||
}
|
||||
else if (node.kind === SyntaxKind.ObjectLiteralExpression) {
|
||||
entry.kind = ScriptElementKind.interfaceElement;
|
||||
entry.displayParts = [punctuationPart(SyntaxKind.OpenParenToken), textPart("object literal"), punctuationPart(SyntaxKind.CloseParenToken)];
|
||||
}
|
||||
else if (node.kind === SyntaxKind.ClassExpression) {
|
||||
entry.kind = ScriptElementKind.localClassElement;
|
||||
entry.displayParts = [punctuationPart(SyntaxKind.OpenParenToken), textPart("anonymous local class"), punctuationPart(SyntaxKind.CloseParenToken)];
|
||||
}
|
||||
else {
|
||||
entry.kind = getNodeKind(node);
|
||||
entry.displayParts = [];
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
getReferenceEntryForSpanInFile(fileName: string, textSpan: TextSpan): ImplementationLocation {
|
||||
return { textSpan, fileName, kind: ScriptElementKind.unknown, displayParts: [] };
|
||||
}
|
||||
}
|
||||
|
||||
export function findReferencedSymbols(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFiles: SourceFile[], sourceFile: SourceFile, position: number, findInStrings: boolean, findInComments: boolean, isForRename: boolean): ReferencedSymbol[] | undefined {
|
||||
const node = getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true);
|
||||
return getReferencedSymbolsForNode(typeChecker, cancellationToken, node, sourceFiles, findInStrings, findInComments, isForRename);
|
||||
return getReferencedSymbolsForNode(new DefaultFindReferencesContext(typeChecker, cancellationToken), node, sourceFiles, findInStrings, findInComments, isForRename);
|
||||
}
|
||||
|
||||
export function convertReferences(referenceSymbols: ReferencedSymbol[]): ReferenceEntry[] {
|
||||
return referenceSymbols && flatMap(referenceSymbols, r => r.references);
|
||||
}
|
||||
|
||||
export function getReferencedSymbolsForNode(typeChecker: TypeChecker, cancellationToken: CancellationToken, node: Node, sourceFiles: SourceFile[], findInStrings?: boolean, findInComments?: boolean, isForRename?: boolean, implementations?: boolean): ReferencedSymbol[] | undefined {
|
||||
export function getReferencedSymbolsForNode<T extends DocumentSpan>(context: FindReferencesContext<T>, node: Node, sourceFiles: SourceFile[], findInStrings?: boolean, findInComments?: boolean, isForRename?: boolean, implementations?: boolean): ReferencedSymbolOf<T>[] | undefined {
|
||||
if (!implementations) {
|
||||
const special = getReferencedSymbolsSpecial(node, sourceFiles, typeChecker, cancellationToken);
|
||||
const special = getReferencedSymbolsSpecial(node, sourceFiles, context);
|
||||
if (special) {
|
||||
return special;
|
||||
}
|
||||
}
|
||||
const { typeChecker, cancellationToken } = context;
|
||||
|
||||
// `getSymbolAtLocation` normally returns the symbol of the class when given the constructor keyword,
|
||||
// so we have to specify that we want the constructor symbol.
|
||||
@@ -24,7 +78,7 @@ namespace ts.FindAllReferences {
|
||||
// Could not find a symbol e.g. unknown identifier
|
||||
if (!symbol) {
|
||||
if (!implementations && node.kind === SyntaxKind.StringLiteral) {
|
||||
return getReferencesForStringLiteral(<StringLiteral>node, sourceFiles, typeChecker, cancellationToken);
|
||||
return getReferencesForStringLiteral(<StringLiteral>node, sourceFiles, context);
|
||||
}
|
||||
// Can't have references to something that we have no symbol for.
|
||||
return undefined;
|
||||
@@ -49,7 +103,7 @@ namespace ts.FindAllReferences {
|
||||
// Compute the meaning from the location and the symbol it references
|
||||
const searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(node), declarations);
|
||||
|
||||
const result: ReferencedSymbol[] = [];
|
||||
const result: ReferencedSymbolOf<T>[] = [];
|
||||
// Maps from a symbol ID to the ReferencedSymbol entry in 'result'.
|
||||
const symbolToIndex: number[] = [];
|
||||
const inheritsFromCache: Map<boolean> = createMap<boolean>();
|
||||
@@ -81,14 +135,14 @@ namespace ts.FindAllReferences {
|
||||
|
||||
function getRefs(scope: ts.Node, searchName: string): void {
|
||||
getReferencesInNode(scope, symbol, searchName, node, searchMeaning, findInStrings, findInComments, result,
|
||||
symbolToIndex, implementations, typeChecker, cancellationToken, searchSymbols, inheritsFromCache);
|
||||
symbolToIndex, implementations, context, searchSymbols, inheritsFromCache);
|
||||
}
|
||||
}
|
||||
|
||||
/** getReferencedSymbols for special node kinds. */
|
||||
function getReferencedSymbolsSpecial(node: Node, sourceFiles: SourceFile[], typeChecker: TypeChecker, cancellationToken: CancellationToken): ReferencedSymbol[] | undefined {
|
||||
function getReferencedSymbolsSpecial<T extends DocumentSpan>(node: Node, sourceFiles: SourceFile[], context: FindReferencesContext<T>): ReferencedSymbolOf<T>[] | undefined {
|
||||
if (isTypeKeyword(node.kind)) {
|
||||
return getAllReferencesForKeyword(sourceFiles, node.kind, cancellationToken);
|
||||
return getAllReferencesForKeyword(context, sourceFiles, node.kind);
|
||||
}
|
||||
|
||||
// Labels
|
||||
@@ -97,20 +151,20 @@ namespace ts.FindAllReferences {
|
||||
const labelDefinition = getTargetLabel((<BreakOrContinueStatement>node.parent), (<Identifier>node).text);
|
||||
// if we have a label definition, look within its statement for references, if not, then
|
||||
// the label is undefined and we have no results..
|
||||
return labelDefinition && getLabelReferencesInNode(labelDefinition.parent, labelDefinition, cancellationToken);
|
||||
return labelDefinition && getLabelReferencesInNode(labelDefinition.parent, labelDefinition, context);
|
||||
}
|
||||
else {
|
||||
// it is a label definition and not a target, search within the parent labeledStatement
|
||||
return getLabelReferencesInNode(node.parent, <Identifier>node, cancellationToken);
|
||||
return getLabelReferencesInNode(node.parent, <Identifier>node, context);
|
||||
}
|
||||
}
|
||||
|
||||
if (isThis(node)) {
|
||||
return getReferencesForThisKeyword(node, sourceFiles, typeChecker, cancellationToken);
|
||||
return getReferencesForThisKeyword(node, sourceFiles, context);
|
||||
}
|
||||
|
||||
if (node.kind === SyntaxKind.SuperKeyword) {
|
||||
return getReferencesForSuperKeyword(node, typeChecker, cancellationToken);
|
||||
return getReferencesForSuperKeyword(node, context);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
@@ -281,7 +335,7 @@ namespace ts.FindAllReferences {
|
||||
|
||||
// if this symbol is visible from its parent container, e.g. exported, then bail out
|
||||
// if symbol correspond to the union property - bail out
|
||||
if (symbol.parent || (symbol.flags & SymbolFlags.Transient && (<TransientSymbol>symbol).checkFlags & CheckFlags.SyntheticProperty)) {
|
||||
if (symbol.parent || (symbol.flags & SymbolFlags.Transient && (<TransientSymbol>symbol).checkFlags & CheckFlags.Synthetic)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -352,10 +406,11 @@ namespace ts.FindAllReferences {
|
||||
return positions;
|
||||
}
|
||||
|
||||
function getLabelReferencesInNode(container: Node, targetLabel: Identifier, cancellationToken: CancellationToken): ReferencedSymbol[] {
|
||||
const references: ReferenceEntry[] = [];
|
||||
function getLabelReferencesInNode<T extends DocumentSpan>(container: Node, targetLabel: Identifier, context: FindReferencesContext<T>): ReferencedSymbolOf<T>[] {
|
||||
const references: T[] = [];
|
||||
const sourceFile = container.getSourceFile();
|
||||
const labelName = targetLabel.text;
|
||||
const { cancellationToken } = context;
|
||||
const possiblePositions = getPossibleSymbolReferencePositions(sourceFile, labelName, container.getStart(), container.getEnd(), cancellationToken);
|
||||
forEach(possiblePositions, position => {
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
@@ -368,7 +423,7 @@ namespace ts.FindAllReferences {
|
||||
// Only pick labels that are either the target label, or have a target that is the target label
|
||||
if (node === targetLabel ||
|
||||
(isJumpStatementTarget(node) && getTargetLabel(node, labelName) === targetLabel)) {
|
||||
references.push(getReferenceEntryFromNode(node));
|
||||
references.push(context.getReferenceEntryFromNode(node));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -404,12 +459,13 @@ namespace ts.FindAllReferences {
|
||||
}
|
||||
}
|
||||
|
||||
function getAllReferencesForKeyword(sourceFiles: SourceFile[], keywordKind: ts.SyntaxKind, cancellationToken: CancellationToken): ReferencedSymbol[] {
|
||||
function getAllReferencesForKeyword<T extends DocumentSpan>(context: FindReferencesContext<T>, sourceFiles: SourceFile[], keywordKind: ts.SyntaxKind): ReferencedSymbolOf<T>[] {
|
||||
const { cancellationToken } = context;
|
||||
const name = tokenToString(keywordKind);
|
||||
const references: ReferenceEntry[] = [];
|
||||
const references: T[] = [];
|
||||
for (const sourceFile of sourceFiles) {
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
addReferencesForKeywordInFile(sourceFile, keywordKind, name, cancellationToken, references);
|
||||
addReferencesForKeywordInFile(sourceFile, keywordKind, name, context, references);
|
||||
}
|
||||
|
||||
if (!references.length) return undefined;
|
||||
@@ -427,18 +483,14 @@ namespace ts.FindAllReferences {
|
||||
return [{ definition, references }];
|
||||
}
|
||||
|
||||
function addReferencesForKeywordInFile(sourceFile: SourceFile, kind: SyntaxKind, searchText: string, cancellationToken: CancellationToken, references: Push<ReferenceEntry>): void {
|
||||
function addReferencesForKeywordInFile<T extends DocumentSpan>(sourceFile: SourceFile, kind: SyntaxKind, searchText: string, context: FindReferencesContext<T>, references: Push<T>): void {
|
||||
const { cancellationToken } = context;
|
||||
const possiblePositions = getPossibleSymbolReferencePositions(sourceFile, searchText, sourceFile.getStart(), sourceFile.getEnd(), cancellationToken);
|
||||
for (const position of possiblePositions) {
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
const referenceLocation = getTouchingPropertyName(sourceFile, position);
|
||||
if (referenceLocation.kind === kind) {
|
||||
references.push({
|
||||
textSpan: createTextSpanFromNode(referenceLocation),
|
||||
fileName: sourceFile.fileName,
|
||||
isWriteAccess: false,
|
||||
isDefinition: false,
|
||||
});
|
||||
references.push(context.getReferenceEntryForSpanInFile(sourceFile.fileName, createTextSpanFromNode(referenceLocation)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -447,22 +499,22 @@ namespace ts.FindAllReferences {
|
||||
* tuple of(searchSymbol, searchText, searchLocation, and searchMeaning).
|
||||
* searchLocation: a node where the search value
|
||||
*/
|
||||
function getReferencesInNode(container: Node,
|
||||
function getReferencesInNode<T extends DocumentSpan>(container: Node,
|
||||
searchSymbol: Symbol,
|
||||
searchText: string,
|
||||
searchLocation: Node,
|
||||
searchMeaning: SemanticMeaning,
|
||||
findInStrings: boolean,
|
||||
findInComments: boolean,
|
||||
result: ReferencedSymbol[],
|
||||
result: ReferencedSymbolOf<T>[],
|
||||
symbolToIndex: number[],
|
||||
implementations: boolean,
|
||||
typeChecker: TypeChecker,
|
||||
cancellationToken: CancellationToken,
|
||||
context: FindReferencesContext<T>,
|
||||
searchSymbols: Symbol[],
|
||||
inheritsFromCache: Map<boolean>): void {
|
||||
|
||||
const sourceFile = container.getSourceFile();
|
||||
const { typeChecker, cancellationToken } = context;
|
||||
|
||||
const start = findInComments ? container.getFullStart() : container.getStart();
|
||||
const possiblePositions = getPossibleSymbolReferencePositions(sourceFile, searchText, start, container.getEnd(), cancellationToken);
|
||||
@@ -486,12 +538,7 @@ namespace ts.FindAllReferences {
|
||||
// 'FindReferences' will just filter out these results.
|
||||
result.push({
|
||||
definition: undefined,
|
||||
references: [{
|
||||
fileName: sourceFile.fileName,
|
||||
textSpan: createTextSpan(position, searchText.length),
|
||||
isWriteAccess: false,
|
||||
isDefinition: false
|
||||
}]
|
||||
references: [context.getReferenceEntryForSpanInFile(sourceFile.fileName, createTextSpan(position, searchText.length))]
|
||||
});
|
||||
}
|
||||
continue;
|
||||
@@ -571,11 +618,11 @@ namespace ts.FindAllReferences {
|
||||
function addReferences(references: Node[]): void {
|
||||
if (references.length) {
|
||||
const referencedSymbol = getReferencedSymbol(searchSymbol);
|
||||
addRange(referencedSymbol.references, map(references, getReferenceEntryFromNode));
|
||||
addRange(referencedSymbol.references, map(references, n => context.getReferenceEntryFromNode(n)));
|
||||
}
|
||||
}
|
||||
|
||||
function getReferencedSymbol(symbol: Symbol): ReferencedSymbol {
|
||||
function getReferencedSymbol(symbol: Symbol): ReferencedSymbolOf<T> {
|
||||
const symbolId = getSymbolId(symbol);
|
||||
let index = symbolToIndex[symbolId];
|
||||
if (index === undefined) {
|
||||
@@ -594,10 +641,10 @@ namespace ts.FindAllReferences {
|
||||
function addReferenceToRelatedSymbol(node: Node, relatedSymbol: Symbol) {
|
||||
const references = getReferencedSymbol(relatedSymbol).references;
|
||||
if (implementations) {
|
||||
getImplementationReferenceEntryForNode(node, references, typeChecker);
|
||||
getImplementationReferenceEntryForNode(node, references, context);
|
||||
}
|
||||
else {
|
||||
references.push(getReferenceEntryFromNode(node));
|
||||
references.push(context.getReferenceEntryFromNode(node));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -658,21 +705,21 @@ namespace ts.FindAllReferences {
|
||||
return result;
|
||||
}
|
||||
|
||||
function getImplementationReferenceEntryForNode(refNode: Node, result: ReferenceEntry[], typeChecker: TypeChecker): void {
|
||||
function getImplementationReferenceEntryForNode<T extends DocumentSpan>(refNode: Node, result: T[], context: FindReferencesContext<T>): void {
|
||||
// Check if we found a function/propertyAssignment/method with an implementation or initializer
|
||||
if (isDeclarationName(refNode) && isImplementation(refNode.parent)) {
|
||||
result.push(getReferenceEntryFromNode(refNode.parent));
|
||||
result.push(context.getReferenceEntryFromNode(refNode.parent));
|
||||
}
|
||||
else if (refNode.kind === SyntaxKind.Identifier) {
|
||||
if (refNode.parent.kind === SyntaxKind.ShorthandPropertyAssignment) {
|
||||
// Go ahead and dereference the shorthand assignment by going to its definition
|
||||
getReferenceEntriesForShorthandPropertyAssignment(refNode, typeChecker, result);
|
||||
getReferenceEntriesForShorthandPropertyAssignment(refNode, context, result);
|
||||
}
|
||||
|
||||
// Check if the node is within an extends or implements clause
|
||||
const containingClass = getContainingClassIfInHeritageClause(refNode);
|
||||
if (containingClass) {
|
||||
result.push(getReferenceEntryFromNode(containingClass));
|
||||
result.push(context.getReferenceEntryFromNode(containingClass));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -681,22 +728,22 @@ namespace ts.FindAllReferences {
|
||||
if (containingTypeReference) {
|
||||
const parent = containingTypeReference.parent;
|
||||
if (isVariableLike(parent) && parent.type === containingTypeReference && parent.initializer && isImplementationExpression(parent.initializer)) {
|
||||
maybeAdd(getReferenceEntryFromNode(parent.initializer));
|
||||
maybeAdd(context.getReferenceEntryFromNode(parent.initializer));
|
||||
}
|
||||
else if (isFunctionLike(parent) && parent.type === containingTypeReference && parent.body) {
|
||||
if (parent.body.kind === SyntaxKind.Block) {
|
||||
forEachReturnStatement(<Block>parent.body, returnStatement => {
|
||||
if (returnStatement.expression && isImplementationExpression(returnStatement.expression)) {
|
||||
maybeAdd(getReferenceEntryFromNode(returnStatement.expression));
|
||||
maybeAdd(context.getReferenceEntryFromNode(returnStatement.expression));
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (isImplementationExpression(<Expression>parent.body)) {
|
||||
maybeAdd(getReferenceEntryFromNode(parent.body));
|
||||
maybeAdd(context.getReferenceEntryFromNode(parent.body));
|
||||
}
|
||||
}
|
||||
else if (isAssertionExpression(parent) && isImplementationExpression(parent.expression)) {
|
||||
maybeAdd(getReferenceEntryFromNode(parent.expression));
|
||||
maybeAdd(context.getReferenceEntryFromNode(parent.expression));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -706,7 +753,7 @@ namespace ts.FindAllReferences {
|
||||
// Because we are returning the implementation locations and not the identifier locations,
|
||||
// duplicate entries would be returned here as each of the type references is part of
|
||||
// the same implementation. For that reason, check before we add a new entry
|
||||
function maybeAdd(a: ReferenceEntry) {
|
||||
function maybeAdd(a: T) {
|
||||
if (!forEach(result, b => a.fileName === b.fileName && a.textSpan.start === b.textSpan.start && a.textSpan.length === b.textSpan.length)) {
|
||||
result.push(a);
|
||||
}
|
||||
@@ -845,7 +892,7 @@ namespace ts.FindAllReferences {
|
||||
}
|
||||
}
|
||||
|
||||
function getReferencesForSuperKeyword(superKeyword: Node, typeChecker: TypeChecker, cancellationToken: CancellationToken): ReferencedSymbol[] {
|
||||
function getReferencesForSuperKeyword<T extends DocumentSpan>(superKeyword: Node, context: FindReferencesContext<T>): ReferencedSymbolOf<T>[] {
|
||||
let searchSpaceNode = getSuperContainer(superKeyword, /*stopOnFunctions*/ false);
|
||||
if (!searchSpaceNode) {
|
||||
return undefined;
|
||||
@@ -868,7 +915,8 @@ namespace ts.FindAllReferences {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const references: ReferenceEntry[] = [];
|
||||
const references: T[] = [];
|
||||
const { typeChecker, cancellationToken } = context;
|
||||
|
||||
const sourceFile = searchSpaceNode.getSourceFile();
|
||||
const possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "super", searchSpaceNode.getStart(), searchSpaceNode.getEnd(), cancellationToken);
|
||||
@@ -887,7 +935,7 @@ namespace ts.FindAllReferences {
|
||||
// Now make sure the owning class is the same as the search-space
|
||||
// and has the same static qualifier as the original 'super's owner.
|
||||
if (container && (ModifierFlags.Static & getModifierFlags(container)) === staticFlag && container.parent.symbol === searchSpaceNode.symbol) {
|
||||
references.push(getReferenceEntryFromNode(node));
|
||||
references.push(context.getReferenceEntryFromNode(node));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -895,8 +943,9 @@ namespace ts.FindAllReferences {
|
||||
return [{ definition, references }];
|
||||
}
|
||||
|
||||
function getReferencesForThisKeyword(thisOrSuperKeyword: Node, sourceFiles: SourceFile[], typeChecker: TypeChecker, cancellationToken: CancellationToken): ReferencedSymbol[] {
|
||||
function getReferencesForThisKeyword<T extends DocumentSpan>(thisOrSuperKeyword: Node, sourceFiles: SourceFile[], context: FindReferencesContext<T>): ReferencedSymbolOf<T>[] {
|
||||
let searchSpaceNode = getThisContainer(thisOrSuperKeyword, /* includeArrowFunctions */ false);
|
||||
const { typeChecker, cancellationToken } = context;
|
||||
|
||||
// Whether 'this' occurs in a static context within a class.
|
||||
let staticFlag = ModifierFlags.Static;
|
||||
@@ -930,7 +979,7 @@ namespace ts.FindAllReferences {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const references: ReferenceEntry[] = [];
|
||||
const references: T[] = [];
|
||||
|
||||
let possiblePositions: number[];
|
||||
if (searchSpaceNode.kind === SyntaxKind.SourceFile) {
|
||||
@@ -963,7 +1012,7 @@ namespace ts.FindAllReferences {
|
||||
references: references
|
||||
}];
|
||||
|
||||
function getThisReferencesInFile(sourceFile: SourceFile, searchSpaceNode: Node, possiblePositions: number[], result: ReferenceEntry[]): void {
|
||||
function getThisReferencesInFile(sourceFile: SourceFile, searchSpaceNode: Node, possiblePositions: number[], result: T[]): void {
|
||||
forEach(possiblePositions, position => {
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
|
||||
@@ -978,13 +1027,13 @@ namespace ts.FindAllReferences {
|
||||
case SyntaxKind.FunctionExpression:
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
if (searchSpaceNode.symbol === container.symbol) {
|
||||
result.push(getReferenceEntryFromNode(node));
|
||||
result.push(context.getReferenceEntryFromNode(node));
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.MethodSignature:
|
||||
if (isObjectLiteralMethod(searchSpaceNode) && searchSpaceNode.symbol === container.symbol) {
|
||||
result.push(getReferenceEntryFromNode(node));
|
||||
result.push(context.getReferenceEntryFromNode(node));
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.ClassExpression:
|
||||
@@ -992,12 +1041,12 @@ namespace ts.FindAllReferences {
|
||||
// Make sure the container belongs to the same class
|
||||
// and has the appropriate static modifier from the original container.
|
||||
if (container.parent && searchSpaceNode.symbol === container.parent.symbol && (getModifierFlags(container) & ModifierFlags.Static) === staticFlag) {
|
||||
result.push(getReferenceEntryFromNode(node));
|
||||
result.push(context.getReferenceEntryFromNode(node));
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.SourceFile:
|
||||
if (container.kind === SyntaxKind.SourceFile && !isExternalModule(<SourceFile>container)) {
|
||||
result.push(getReferenceEntryFromNode(node));
|
||||
result.push(context.getReferenceEntryFromNode(node));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1005,7 +1054,8 @@ namespace ts.FindAllReferences {
|
||||
}
|
||||
}
|
||||
|
||||
function getReferencesForStringLiteral(node: StringLiteral, sourceFiles: SourceFile[], typeChecker: TypeChecker, cancellationToken: CancellationToken): ReferencedSymbol[] {
|
||||
function getReferencesForStringLiteral<T extends DocumentSpan>(node: StringLiteral, sourceFiles: SourceFile[], context: FindReferencesContext<T>): ReferencedSymbolOf<T>[] {
|
||||
const { typeChecker, cancellationToken } = context;
|
||||
const type = getStringLiteralTypeForNode(node, typeChecker);
|
||||
|
||||
if (!type) {
|
||||
@@ -1013,7 +1063,7 @@ namespace ts.FindAllReferences {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const references: ReferenceEntry[] = [];
|
||||
const references: T[] = [];
|
||||
|
||||
for (const sourceFile of sourceFiles) {
|
||||
const possiblePositions = getPossibleSymbolReferencePositions(sourceFile, type.text, sourceFile.getStart(), sourceFile.getEnd(), cancellationToken);
|
||||
@@ -1033,7 +1083,7 @@ namespace ts.FindAllReferences {
|
||||
references: references
|
||||
}];
|
||||
|
||||
function getReferencesForStringLiteralInFile(sourceFile: SourceFile, searchType: Type, possiblePositions: number[], references: ReferenceEntry[]): void {
|
||||
function getReferencesForStringLiteralInFile(sourceFile: SourceFile, searchType: Type, possiblePositions: number[], references: T[]): void {
|
||||
for (const position of possiblePositions) {
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
|
||||
@@ -1044,7 +1094,7 @@ namespace ts.FindAllReferences {
|
||||
|
||||
const type = getStringLiteralTypeForNode(<StringLiteral>node, typeChecker);
|
||||
if (type === searchType) {
|
||||
references.push(getReferenceEntryFromNode(node));
|
||||
references.push(context.getReferenceEntryFromNode(node, /*isInString*/ true));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1357,14 +1407,15 @@ namespace ts.FindAllReferences {
|
||||
}
|
||||
}
|
||||
|
||||
export function getReferenceEntriesForShorthandPropertyAssignment(node: Node, typeChecker: TypeChecker, result: ReferenceEntry[]): void {
|
||||
export function getReferenceEntriesForShorthandPropertyAssignment<T extends DocumentSpan>(node: Node, context: FindReferencesContext<T>, result: T[]): void {
|
||||
const { typeChecker } = context;
|
||||
const refSymbol = typeChecker.getSymbolAtLocation(node);
|
||||
const shorthandSymbol = typeChecker.getShorthandAssignmentValueSymbol(refSymbol.valueDeclaration);
|
||||
|
||||
if (shorthandSymbol) {
|
||||
for (const declaration of shorthandSymbol.getDeclarations()) {
|
||||
if (getMeaningFromDeclaration(declaration) & SemanticMeaning.Value) {
|
||||
result.push(getReferenceEntryFromNode(declaration));
|
||||
result.push(context.getReferenceEntryFromNode(declaration));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -314,24 +314,55 @@ namespace ts.formatting {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function formatNode(node: Node, sourceFileLike: SourceFileLike, languageVariant: LanguageVariant, initialIndentation: number, delta: number, rulesProvider: RulesProvider): TextChange[] {
|
||||
const range = { pos: 0, end: sourceFileLike.text.length };
|
||||
return formatSpanWorker(
|
||||
range,
|
||||
node,
|
||||
initialIndentation,
|
||||
delta,
|
||||
getFormattingScanner(sourceFileLike.text, languageVariant, range.pos, range.end),
|
||||
rulesProvider.getFormatOptions(),
|
||||
rulesProvider,
|
||||
FormattingRequestKind.FormatSelection,
|
||||
_ => false, // assume that node does not have any errors
|
||||
sourceFileLike);
|
||||
}
|
||||
|
||||
function formatSpan(originalRange: TextRange,
|
||||
sourceFile: SourceFile,
|
||||
options: FormatCodeSettings,
|
||||
rulesProvider: RulesProvider,
|
||||
requestKind: FormattingRequestKind): TextChange[] {
|
||||
// find the smallest node that fully wraps the range and compute the initial indentation for the node
|
||||
const enclosingNode = findEnclosingNode(originalRange, sourceFile);
|
||||
return formatSpanWorker(
|
||||
originalRange,
|
||||
enclosingNode,
|
||||
SmartIndenter.getIndentationForNode(enclosingNode, originalRange, sourceFile, options),
|
||||
getOwnOrInheritedDelta(enclosingNode, options, sourceFile),
|
||||
getFormattingScanner(sourceFile.text, sourceFile.languageVariant, getScanStartPosition(enclosingNode, originalRange, sourceFile), originalRange.end),
|
||||
options,
|
||||
rulesProvider,
|
||||
requestKind,
|
||||
prepareRangeContainsErrorFunction(sourceFile.parseDiagnostics, originalRange),
|
||||
sourceFile);
|
||||
}
|
||||
|
||||
const rangeContainsError = prepareRangeContainsErrorFunction(sourceFile.parseDiagnostics, originalRange);
|
||||
function formatSpanWorker(originalRange: TextRange,
|
||||
enclosingNode: Node,
|
||||
initialIndentation: number,
|
||||
delta: number,
|
||||
formattingScanner: FormattingScanner,
|
||||
options: FormatCodeSettings,
|
||||
rulesProvider: RulesProvider,
|
||||
requestKind: FormattingRequestKind,
|
||||
rangeContainsError: (r: TextRange) => boolean,
|
||||
sourceFile: SourceFileLike): TextChange[] {
|
||||
|
||||
// formatting context is used by rules provider
|
||||
const formattingContext = new FormattingContext(sourceFile, requestKind);
|
||||
|
||||
// find the smallest node that fully wraps the range and compute the initial indentation for the node
|
||||
const enclosingNode = findEnclosingNode(originalRange, sourceFile);
|
||||
|
||||
const formattingScanner = getFormattingScanner(sourceFile, getScanStartPosition(enclosingNode, originalRange, sourceFile), originalRange.end);
|
||||
|
||||
const initialIndentation = SmartIndenter.getIndentationForNode(enclosingNode, originalRange, sourceFile, options);
|
||||
|
||||
let previousRangeHasError: boolean;
|
||||
let previousRange: TextRangeWithKind;
|
||||
let previousParent: Node;
|
||||
@@ -351,7 +382,6 @@ namespace ts.formatting {
|
||||
undecoratedStartLine = sourceFile.getLineAndCharacterOfPosition(getNonDecoratorTokenPosOfNode(enclosingNode, sourceFile)).line;
|
||||
}
|
||||
|
||||
const delta = getOwnOrInheritedDelta(enclosingNode, options, sourceFile);
|
||||
processNode(enclosingNode, enclosingNode, startLine, undecoratedStartLine, initialIndentation, delta);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace ts.formatting {
|
||||
private contextNodeBlockIsOnOneLine: boolean;
|
||||
private nextNodeBlockIsOnOneLine: boolean;
|
||||
|
||||
constructor(public sourceFile: SourceFile, public formattingRequestKind: FormattingRequestKind) {
|
||||
constructor(public readonly sourceFile: SourceFileLike, public formattingRequestKind: FormattingRequestKind) {
|
||||
}
|
||||
|
||||
public updateContext(currentRange: TextRangeWithKind, currentTokenParent: Node, nextRange: TextRangeWithKind, nextTokenParent: Node, commonParent: Node) {
|
||||
|
||||
@@ -30,11 +30,11 @@ namespace ts.formatting {
|
||||
RescanJsxText,
|
||||
}
|
||||
|
||||
export function getFormattingScanner(sourceFile: SourceFile, startPos: number, endPos: number): FormattingScanner {
|
||||
export function getFormattingScanner(text: string, languageVariant: LanguageVariant, startPos: number, endPos: number): FormattingScanner {
|
||||
Debug.assert(scanner === undefined, "Scanner should be undefined");
|
||||
scanner = sourceFile.languageVariant === LanguageVariant.JSX ? jsxScanner : standardScanner;
|
||||
scanner = languageVariant === LanguageVariant.JSX ? jsxScanner : standardScanner;
|
||||
|
||||
scanner.setText(sourceFile.text);
|
||||
scanner.setText(text);
|
||||
scanner.setTextPos(startPos);
|
||||
|
||||
let wasNewLine = true;
|
||||
@@ -276,8 +276,8 @@ namespace ts.formatting {
|
||||
function isOnToken(): boolean {
|
||||
Debug.assert(scanner !== undefined);
|
||||
|
||||
const current = (lastTokenInfo && lastTokenInfo.token.kind) || scanner.getToken();
|
||||
const startPos = (lastTokenInfo && lastTokenInfo.token.pos) || scanner.getStartPos();
|
||||
const current = lastTokenInfo ? lastTokenInfo.token.kind : scanner.getToken();
|
||||
const startPos = lastTokenInfo ? lastTokenInfo.token.pos : scanner.getStartPos();
|
||||
return startPos < endPos && current !== SyntaxKind.EndOfFileToken && !isTrivia(current);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,10 @@ namespace ts.formatting {
|
||||
return this.rulesMap;
|
||||
}
|
||||
|
||||
public getFormatOptions(): Readonly<ts.FormatCodeSettings> {
|
||||
return this.options;
|
||||
}
|
||||
|
||||
public ensureUpToDate(options: ts.FormatCodeSettings) {
|
||||
if (!this.options || !ts.compareDataObjects(this.options, options)) {
|
||||
const activeRules = this.createActiveRules(options);
|
||||
|
||||
@@ -8,7 +8,19 @@ namespace ts.formatting {
|
||||
Unknown = -1
|
||||
}
|
||||
|
||||
export function getIndentation(position: number, sourceFile: SourceFile, options: EditorSettings): number {
|
||||
/**
|
||||
* Computed indentation for a given position in source file
|
||||
* @param position - position in file
|
||||
* @param sourceFile - target source file
|
||||
* @param options - set of editor options that control indentation
|
||||
* @param assumeNewLineBeforeCloseBrace - false when getIndentation is called on the text from the real source file.
|
||||
* true - when we need to assume that position is on the newline. This is usefult for codefixes, i.e.
|
||||
* function f() {
|
||||
* |}
|
||||
* when inserting some text after open brace we would like to get the value of indentation as if newline was already there.
|
||||
* However by default indentation at position | will be 0 so 'assumeNewLineBeforeCloseBrace' allows to override this behavior,
|
||||
*/
|
||||
export function getIndentation(position: number, sourceFile: SourceFile, options: EditorSettings, assumeNewLineBeforeCloseBrace = false): number {
|
||||
if (position > sourceFile.text.length) {
|
||||
return getBaseIndentation(options); // past EOF
|
||||
}
|
||||
@@ -71,13 +83,14 @@ namespace ts.formatting {
|
||||
if (positionBelongsToNode(current, position, sourceFile) && shouldIndentChildNode(current, previous)) {
|
||||
currentStart = getStartLineAndCharacterForNode(current, sourceFile);
|
||||
|
||||
if (nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile)) {
|
||||
indentationDelta = 0;
|
||||
const nextTokenKind = nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile);
|
||||
if (nextTokenKind !== NextTokenKind.Unknown) {
|
||||
// handle cases when codefix is about to be inserted before the close brace
|
||||
indentationDelta = assumeNewLineBeforeCloseBrace && nextTokenKind === NextTokenKind.CloseBrace ? options.indentSize : 0;
|
||||
}
|
||||
else {
|
||||
indentationDelta = lineAtPosition !== currentStart.line ? options.indentSize : 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -218,15 +231,21 @@ namespace ts.formatting {
|
||||
return findColumnForFirstNonWhitespaceCharacterInLine(currentLineAndChar, sourceFile, options);
|
||||
}
|
||||
|
||||
function nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken: Node, current: Node, lineAtPosition: number, sourceFile: SourceFile): boolean {
|
||||
const enum NextTokenKind {
|
||||
Unknown,
|
||||
OpenBrace,
|
||||
CloseBrace
|
||||
}
|
||||
|
||||
function nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken: Node, current: Node, lineAtPosition: number, sourceFile: SourceFile): NextTokenKind {
|
||||
const nextToken = findNextToken(precedingToken, current);
|
||||
if (!nextToken) {
|
||||
return false;
|
||||
return NextTokenKind.Unknown;
|
||||
}
|
||||
|
||||
if (nextToken.kind === SyntaxKind.OpenBraceToken) {
|
||||
// open braces are always indented at the parent level
|
||||
return true;
|
||||
return NextTokenKind.OpenBrace;
|
||||
}
|
||||
else if (nextToken.kind === SyntaxKind.CloseBraceToken) {
|
||||
// close braces are indented at the parent level if they are located on the same line with cursor
|
||||
@@ -239,17 +258,17 @@ namespace ts.formatting {
|
||||
// $}
|
||||
|
||||
const nextTokenStartLine = getStartLineAndCharacterForNode(nextToken, sourceFile).line;
|
||||
return lineAtPosition === nextTokenStartLine;
|
||||
return lineAtPosition === nextTokenStartLine ? NextTokenKind.CloseBrace : NextTokenKind.Unknown;
|
||||
}
|
||||
|
||||
return false;
|
||||
return NextTokenKind.Unknown;
|
||||
}
|
||||
|
||||
function getStartLineAndCharacterForNode(n: Node, sourceFile: SourceFile): LineAndCharacter {
|
||||
function getStartLineAndCharacterForNode(n: Node, sourceFile: SourceFileLike): LineAndCharacter {
|
||||
return sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile));
|
||||
}
|
||||
|
||||
export function childStartsOnTheSameLineWithElseInIfStatement(parent: Node, child: TextRangeWithKind, childStartLine: number, sourceFile: SourceFile): boolean {
|
||||
export function childStartsOnTheSameLineWithElseInIfStatement(parent: Node, child: TextRangeWithKind, childStartLine: number, sourceFile: SourceFileLike): boolean {
|
||||
if (parent.kind === SyntaxKind.IfStatement && (<IfStatement>parent).elseStatement === child) {
|
||||
const elseKeyword = findChildOfKind(parent, SyntaxKind.ElseKeyword, sourceFile);
|
||||
Debug.assert(elseKeyword !== undefined);
|
||||
@@ -261,15 +280,15 @@ namespace ts.formatting {
|
||||
return false;
|
||||
}
|
||||
|
||||
function getContainingList(node: Node, sourceFile: SourceFile): NodeArray<Node> {
|
||||
function getListIfStartEndIsInListRange(list: NodeArray<Node>, start: number, end: number) {
|
||||
return list && rangeContainsStartEnd(list, start, end) ? list : undefined;
|
||||
}
|
||||
|
||||
export function getContainingList(node: Node, sourceFile: SourceFile): NodeArray<Node> {
|
||||
if (node.parent) {
|
||||
switch (node.parent.kind) {
|
||||
case SyntaxKind.TypeReference:
|
||||
if ((<TypeReferenceNode>node.parent).typeArguments &&
|
||||
rangeContainsStartEnd((<TypeReferenceNode>node.parent).typeArguments, node.getStart(sourceFile), node.getEnd())) {
|
||||
return (<TypeReferenceNode>node.parent).typeArguments;
|
||||
}
|
||||
break;
|
||||
return getListIfStartEndIsInListRange((<TypeReferenceNode>node.parent).typeArguments, node.getStart(sourceFile), node.getEnd());
|
||||
case SyntaxKind.ObjectLiteralExpression:
|
||||
return (<ObjectLiteralExpression>node.parent).properties;
|
||||
case SyntaxKind.ArrayLiteralExpression:
|
||||
@@ -280,30 +299,26 @@ namespace ts.formatting {
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.MethodSignature:
|
||||
case SyntaxKind.CallSignature:
|
||||
case SyntaxKind.Constructor:
|
||||
case SyntaxKind.ConstructorType:
|
||||
case SyntaxKind.ConstructSignature: {
|
||||
const start = node.getStart(sourceFile);
|
||||
if ((<SignatureDeclaration>node.parent).typeParameters &&
|
||||
rangeContainsStartEnd((<SignatureDeclaration>node.parent).typeParameters, start, node.getEnd())) {
|
||||
return (<SignatureDeclaration>node.parent).typeParameters;
|
||||
}
|
||||
if (rangeContainsStartEnd((<SignatureDeclaration>node.parent).parameters, start, node.getEnd())) {
|
||||
return (<SignatureDeclaration>node.parent).parameters;
|
||||
}
|
||||
break;
|
||||
return getListIfStartEndIsInListRange((<SignatureDeclaration>node.parent).typeParameters, start, node.getEnd()) ||
|
||||
getListIfStartEndIsInListRange((<SignatureDeclaration>node.parent).parameters, start, node.getEnd());
|
||||
}
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
return getListIfStartEndIsInListRange((<ClassDeclaration>node.parent).typeParameters, node.getStart(sourceFile), node.getEnd());
|
||||
case SyntaxKind.NewExpression:
|
||||
case SyntaxKind.CallExpression: {
|
||||
const start = node.getStart(sourceFile);
|
||||
if ((<CallExpression>node.parent).typeArguments &&
|
||||
rangeContainsStartEnd((<CallExpression>node.parent).typeArguments, start, node.getEnd())) {
|
||||
return (<CallExpression>node.parent).typeArguments;
|
||||
}
|
||||
if ((<CallExpression>node.parent).arguments &&
|
||||
rangeContainsStartEnd((<CallExpression>node.parent).arguments, start, node.getEnd())) {
|
||||
return (<CallExpression>node.parent).arguments;
|
||||
}
|
||||
break;
|
||||
return getListIfStartEndIsInListRange((<CallExpression>node.parent).typeArguments, start, node.getEnd()) ||
|
||||
getListIfStartEndIsInListRange((<CallExpression>node.parent).arguments, start, node.getEnd());
|
||||
}
|
||||
case SyntaxKind.VariableDeclarationList:
|
||||
return getListIfStartEndIsInListRange((<VariableDeclarationList>node.parent).declarations, node.getStart(sourceFile), node.getEnd());
|
||||
case SyntaxKind.NamedImports:
|
||||
case SyntaxKind.NamedExports:
|
||||
return getListIfStartEndIsInListRange((<NamedImportsOrExports>node.parent).elements, node.getStart(sourceFile), node.getEnd());
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
@@ -400,7 +415,7 @@ namespace ts.formatting {
|
||||
value of 'character' for '$' is 3
|
||||
value of 'column' for '$' is 6 (assuming that tab size is 4)
|
||||
*/
|
||||
export function findFirstNonWhitespaceCharacterAndColumn(startPos: number, endPos: number, sourceFile: SourceFile, options: EditorSettings) {
|
||||
export function findFirstNonWhitespaceCharacterAndColumn(startPos: number, endPos: number, sourceFile: SourceFileLike, options: EditorSettings) {
|
||||
let character = 0;
|
||||
let column = 0;
|
||||
for (let pos = startPos; pos < endPos; pos++) {
|
||||
@@ -421,7 +436,7 @@ namespace ts.formatting {
|
||||
return { column, character };
|
||||
}
|
||||
|
||||
export function findFirstNonWhitespaceColumn(startPos: number, endPos: number, sourceFile: SourceFile, options: EditorSettings): number {
|
||||
export function findFirstNonWhitespaceColumn(startPos: number, endPos: number, sourceFile: SourceFileLike, options: EditorSettings): number {
|
||||
return findFirstNonWhitespaceCharacterAndColumn(startPos, endPos, sourceFile, options).column;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* @internal */
|
||||
/* @internal */
|
||||
namespace ts.GoToDefinition {
|
||||
export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile, position: number): DefinitionInfo[] {
|
||||
/// Triple slash reference comments
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
/* @internal */
|
||||
namespace ts.GoToImplementation {
|
||||
export function getImplementationAtPosition(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFiles: SourceFile[], node: Node): ImplementationLocation[] {
|
||||
const context = new FindAllReferences.FindImplementationsContext(typeChecker, cancellationToken);
|
||||
// If invoked directly on a shorthand property assignment, then return
|
||||
// the declaration of the symbol being assigned (not the symbol being assigned to).
|
||||
if (node.parent.kind === SyntaxKind.ShorthandPropertyAssignment) {
|
||||
const result: ReferenceEntry[] = [];
|
||||
FindAllReferences.getReferenceEntriesForShorthandPropertyAssignment(node, typeChecker, result);
|
||||
const result: ImplementationLocation[] = [];
|
||||
FindAllReferences.getReferenceEntriesForShorthandPropertyAssignment(node, context, result);
|
||||
return result.length > 0 ? result : undefined;
|
||||
}
|
||||
else if (node.kind === SyntaxKind.SuperKeyword || isSuperProperty(node.parent)) {
|
||||
// References to and accesses on the super keyword only have one possible implementation, so no
|
||||
// need to "Find all References"
|
||||
const symbol = typeChecker.getSymbolAtLocation(node);
|
||||
return symbol.valueDeclaration && [FindAllReferences.getReferenceEntryFromNode(symbol.valueDeclaration)];
|
||||
return symbol.valueDeclaration && [context.getReferenceEntryFromNode(symbol.valueDeclaration)];
|
||||
}
|
||||
else {
|
||||
// Perform "Find all References" and retrieve only those that are implementations
|
||||
const referencedSymbols = FindAllReferences.getReferencedSymbolsForNode(typeChecker, cancellationToken,
|
||||
const referencedSymbols = FindAllReferences.getReferencedSymbolsForNode(context,
|
||||
node, sourceFiles, /*findInStrings*/false, /*findInComments*/false, /*isForRename*/false, /*implementations*/true);
|
||||
const result = flatMap(referencedSymbols, symbol =>
|
||||
map(symbol.references, ({ textSpan, fileName }) => ({ textSpan, fileName })));
|
||||
const result = flatMap(referencedSymbols, symbol => symbol.references);
|
||||
|
||||
return result && result.length > 0 ? result : undefined;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* @internal */
|
||||
/* @internal */
|
||||
namespace ts.JsDoc {
|
||||
const jsDocTagNames = [
|
||||
"augments",
|
||||
@@ -178,7 +178,8 @@ namespace ts.JsDoc {
|
||||
const posLineAndChar = sourceFile.getLineAndCharacterOfPosition(position);
|
||||
const lineStart = sourceFile.getLineStarts()[posLineAndChar.line];
|
||||
|
||||
const indentationStr = sourceFile.text.substr(lineStart, posLineAndChar.character);
|
||||
// replace non-whitespace characters in prefix with spaces.
|
||||
const indentationStr = sourceFile.text.substr(lineStart, posLineAndChar.character).replace(/\S/i, () => " ");
|
||||
const isJavaScriptFile = hasJavaScriptFileExtension(sourceFile.fileName);
|
||||
|
||||
let docParams = "";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
|
||||
// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
|
||||
// See LICENSE.txt in the project root for complete license information.
|
||||
|
||||
/// <reference path='../compiler/types.ts' />
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* @internal */
|
||||
/* @internal */
|
||||
namespace ts.NavigateTo {
|
||||
type RawNavigateToItem = { name: string; fileName: string; matchKind: PatternMatchKind; isCaseSensitive: boolean; declaration: Declaration };
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/// <reference path="..\compiler\program.ts"/>
|
||||
/// <reference path="..\compiler\program.ts"/>
|
||||
/// <reference path="..\compiler\commandLineParser.ts"/>
|
||||
|
||||
/// <reference path='types.ts' />
|
||||
@@ -24,6 +24,7 @@
|
||||
/// <reference path='transpile.ts' />
|
||||
/// <reference path='formatting\formatting.ts' />
|
||||
/// <reference path='formatting\smartIndenter.ts' />
|
||||
/// <reference path='textChanges.ts' />
|
||||
/// <reference path='codeFixProvider.ts' />
|
||||
/// <reference path='codefixes\fixes.ts' />
|
||||
|
||||
@@ -63,7 +64,7 @@ namespace ts {
|
||||
return getSourceFileOfNode(this);
|
||||
}
|
||||
|
||||
public getStart(sourceFile?: SourceFile, includeJsDocComment?: boolean): number {
|
||||
public getStart(sourceFile?: SourceFileLike, includeJsDocComment?: boolean): number {
|
||||
return getTokenPosOfNode(this, sourceFile, includeJsDocComment);
|
||||
}
|
||||
|
||||
@@ -129,7 +130,7 @@ namespace ts {
|
||||
return list;
|
||||
}
|
||||
|
||||
private createChildren(sourceFile?: SourceFile) {
|
||||
private createChildren(sourceFile?: SourceFileLike) {
|
||||
let children: Node[];
|
||||
if (this.kind >= SyntaxKind.FirstNode) {
|
||||
scanner.setText((sourceFile || this.getSourceFile()).text);
|
||||
@@ -182,7 +183,7 @@ namespace ts {
|
||||
return this._children[index];
|
||||
}
|
||||
|
||||
public getChildren(sourceFile?: SourceFile): Node[] {
|
||||
public getChildren(sourceFile?: SourceFileLike): Node[] {
|
||||
if (!this._children) this.createChildren(sourceFile);
|
||||
return this._children;
|
||||
}
|
||||
@@ -209,6 +210,10 @@ namespace ts {
|
||||
|
||||
return child.kind < SyntaxKind.FirstNode ? child : child.getLastToken(sourceFile);
|
||||
}
|
||||
|
||||
public forEachChild<T>(cbNode: (node: Node) => T, cbNodeArray?: (nodes: Node[]) => T): T {
|
||||
return forEachChild(this, cbNode, cbNodeArray);
|
||||
}
|
||||
}
|
||||
|
||||
class TokenOrIdentifierObject implements Node {
|
||||
@@ -231,7 +236,7 @@ namespace ts {
|
||||
return getSourceFileOfNode(this);
|
||||
}
|
||||
|
||||
public getStart(sourceFile?: SourceFile, includeJsDocComment?: boolean): number {
|
||||
public getStart(sourceFile?: SourceFileLike, includeJsDocComment?: boolean): number {
|
||||
return getTokenPosOfNode(this, sourceFile, includeJsDocComment);
|
||||
}
|
||||
|
||||
@@ -282,6 +287,10 @@ namespace ts {
|
||||
public getLastToken(): Node {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
public forEachChild<T>(): T {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
class SymbolObject implements Symbol {
|
||||
@@ -1395,7 +1404,8 @@ namespace ts {
|
||||
fileName: entry.fileName,
|
||||
textSpan: highlightSpan.textSpan,
|
||||
isWriteAccess: highlightSpan.kind === HighlightSpanKind.writtenReference,
|
||||
isDefinition: false
|
||||
isDefinition: false,
|
||||
isInString: highlightSpan.isInString,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1682,7 +1692,7 @@ namespace ts {
|
||||
return [];
|
||||
}
|
||||
|
||||
function getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: number[]): CodeAction[] {
|
||||
function getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: number[], formatOptions: FormatCodeSettings): CodeAction[] {
|
||||
synchronizeHostData();
|
||||
const sourceFile = getValidSourceFile(fileName);
|
||||
const span = { start, length: end - start };
|
||||
@@ -1700,7 +1710,8 @@ namespace ts {
|
||||
program: program,
|
||||
newLineCharacter: newLineChar,
|
||||
host: host,
|
||||
cancellationToken: cancellationToken
|
||||
cancellationToken: cancellationToken,
|
||||
rulesProvider: getRuleProvider(formatOptions)
|
||||
};
|
||||
|
||||
const fixes = codefix.getFixes(context);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user