Merge branch 'master' into incrementalBuildInfo

This commit is contained in:
Sheetal Nandi
2019-03-08 11:42:19 -08:00
117 changed files with 4728 additions and 5649 deletions
-2
View File
@@ -5,8 +5,6 @@ node_js:
- '10'
- '8'
sudo: false
env:
- workerCount=3 timeout=600000
+1 -50
View File
@@ -12,10 +12,9 @@ const merge2 = require("merge2");
const mkdirp = require("mkdirp");
const { src, dest, task, parallel, series, watch } = require("gulp");
const { append, transform } = require("gulp-insert");
const { browserify } = require("./scripts/build/browserify");
const { prependFile } = require("./scripts/build/prepend");
const { exec, readJson, needsUpdate, getDiffTool, getDirSize, rm } = require("./scripts/build/utils");
const { runConsoleTests, cleanTestDirs, writeTestConfigFile, refBaseline, localBaseline, refRwcBaseline, localRwcBaseline } = require("./scripts/build/tests");
const { runConsoleTests, refBaseline, localBaseline, refRwcBaseline, localRwcBaseline } = require("./scripts/build/tests");
const { buildProject, cleanProject, watchProject } = require("./scripts/build/projects");
const cmdLineOptions = require("./scripts/build/options");
@@ -432,44 +431,6 @@ task("runtests-parallel").flags = {
" --built": "Compile using the built version of the compiler.",
};
const buildWebTestServer = () => buildProject("tests/webTestServer.tsconfig.json");
const cleanWebTestServer = () => cleanProject("tests/webTestServer.tsconfig.json");
cleanTasks.push(cleanWebTestServer);
const browserifyTests = () => src(["built/local/run.js"], { base: "built/local" })
.pipe(newer("built/local/bundle.js"))
.pipe(sourcemaps.init({ loadMaps: true }))
.pipe(browserify())
.pipe(rename("bundle.js"))
.pipe(sourcemaps.write(".", /**@type {*}*/({ includeContent: false, destPath: "built/local" })))
.pipe(dest("built/local"));
const runtestsBrowser = async () => {
await cleanTestDirs();
const { tests, runners, light } = cmdLineOptions;
const testConfigFile = "test.config";
await del([testConfigFile]);
if (tests || runners || light) {
writeTestConfigFile(tests, runners, light);
}
const args = ["tests/webTestServer.js"];
if (cmdLineOptions.browser) {
args.push(cmdLineOptions.browser);
}
if (tests) {
args.push(JSON.stringify(tests));
}
await exec(process.execPath, args);
};
task("runtests-browser", series(preBuild, parallel(buildTests, buildServices, buildLssl, buildWebTestServer), browserifyTests, runtestsBrowser));
task("runtests-browser").description = "Runs the tests using the built run.js file like 'gulp runtests'.";
task("runtests-browser").flags = {
"-t --tests=<regex>": "pattern for tests to run",
"-b --browser=<browser>": "Either 'IE' or 'chrome'",
" --built": "Compile using the built version of the compiler.",
};
task("diff", () => exec(getDiffTool(), [refBaseline, localBaseline], { ignoreExitCode: true }));
task("diff").description = "Diffs the compiler baselines using the diff tool specified by the 'DIFF' environment variable";
@@ -503,16 +464,6 @@ cleanTasks.push(cleanWebHost);
task("clean-webhost", cleanWebHost);
task("clean-webhost").description = "Cleans the outputs of the tsc web host";
// TODO(rbuckton): Determine if 'perftsc' is still in use.
const buildPerfTsc = () => buildProject("tests/perftsc.tsconfig.json");
task("perftsc", series(lkgPreBuild, buildPerfTsc));
task("perftsc").description = "Builds augmented version of the compiler for perf tests";
const cleanPerfTsc = () => cleanProject("tests/perftsc.tsconfig.json");
cleanTasks.push(cleanPerfTsc);
task("clean-perftsc", cleanPerfTsc);
task("clean-perftsc").description = "Cleans the outputs of the perftsc project";
const buildLoggedIO = async () => {
mkdirp.sync("built/local/temp");
await exec(process.execPath, ["lib/tsc", "--types", "--target", "es5", "--lib", "es5", "--outdir", "built/local/temp", "src/harness/loggedIO.ts"]);
-24
View File
@@ -1,24 +0,0 @@
// simple script to optionally elide source-map-support (or other optional modules) when running browserify.
var stream = require("stream"),
Transform = stream.Transform,
resolve = require("browser-resolve");
var requirePattern = /require\s*\(\s*['"](source-map-support)['"]\s*\)/;
module.exports = function (file) {
return new Transform({
transform: function (data, encoding, cb) {
var text = encoding === "buffer" ? data.toString("utf8") : data;
this.push(new Buffer(text.replace(requirePattern, function (originalText, moduleName) {
try {
resolve.sync(moduleName, { filename: file });
return originalText;
}
catch (e) {
return "(function () { throw new Error(\"module '" + moduleName + "' not found.\"); })()";
}
}), "utf8"));
cb();
}
});
};
-33
View File
@@ -1,33 +0,0 @@
// @ts-check
const browserify = require("browserify");
const Vinyl = require("vinyl");
const { Transform } = require("stream");
const { streamFromFile } = require("./utils");
const { replaceContents } = require("./sourcemaps");
/**
* @param {import("browserify").Options} [opts]
*/
function browserifyFile(opts) {
return new Transform({
objectMode: true,
/**
* @param {string | Buffer | Vinyl} input
*/
transform(input, _, cb) {
if (typeof input === "string" || Buffer.isBuffer(input)) return cb(new Error("Only Vinyl files are supported."));
try {
browserify(Object.assign({}, opts, { debug: !!input.sourceMap, basedir: input.base }))
.add(streamFromFile(input), { file: input.path, basedir: input.base })
.bundle((err, contents) => {
if (err) return cb(err);
cb(null, replaceContents(input, contents));
});
}
catch (e) {
cb(e);
}
}
});
}
exports.browserify = browserifyFile;
-98
View File
@@ -1,102 +1,4 @@
// @ts-check
/// <reference path="../types/ambient.d.ts" />
const path = require("path");
const convertMap = require("convert-source-map");
const applySourceMap = require("vinyl-sourcemaps-apply");
const through2 = require("through2");
/**
* @param {import("vinyl")} input
* @param {string | Buffer} contents
* @param {string | RawSourceMap} [sourceMap]
*/
function replaceContents(input, contents, sourceMap) {
const output = input.clone();
output.contents = typeof contents === "string" ? Buffer.from(contents, "utf8") : contents;
if (input.sourceMap) {
output.sourceMap = typeof input.sourceMap === "string" ? /**@type {RawSourceMap}*/(JSON.parse(input.sourceMap)) : input.sourceMap;
if (typeof sourceMap === "string") {
sourceMap = /** @type {RawSourceMap} */(JSON.parse(sourceMap));
}
else if (sourceMap === undefined) {
const stringContents = typeof contents === "string" ? contents : contents.toString("utf8");
const newSourceMapConverter = convertMap.fromSource(stringContents);
if (newSourceMapConverter) {
sourceMap = /** @type {RawSourceMap} */(newSourceMapConverter.toObject());
output.contents = new Buffer(convertMap.removeMapFileComments(stringContents), "utf8");
}
}
if (sourceMap) {
const cwd = input.cwd || process.cwd();
const base = input.base || cwd;
const sourceRoot = output.sourceMap.sourceRoot;
makeAbsoluteSourceMap(cwd, base, output.sourceMap);
makeAbsoluteSourceMap(cwd, base, /** @type {RawSourceMap} */(sourceMap));
applySourceMap(output, sourceMap);
makeRelativeSourceMap(cwd, base, sourceRoot, output.sourceMap);
}
else {
output.sourceMap = undefined;
}
}
return output;
}
exports.replaceContents = replaceContents;
function removeSourceMaps() {
return through2.obj((/**@type {import("vinyl")}*/file, _, cb) => {
if (file.isBuffer()) {
file.contents = Buffer.from(convertMap.removeMapFileComments(file.contents.toString("utf8")), "utf8");
if (file.sourceMap) {
file.sourceMap = undefined;
}
}
cb(null, file);
});
}
exports.removeSourceMaps = removeSourceMaps;
/**
* @param {string | undefined} cwd
* @param {string | undefined} base
* @param {RawSourceMap} sourceMap
*
* @typedef {object} RawSourceMap
* @property {string} version
* @property {string} file
* @property {string} [sourceRoot]
* @property {string[]} sources
* @property {string[]} [sourcesContent]
* @property {string} mappings
* @property {string[]} [names]
*/
function makeAbsoluteSourceMap(cwd = process.cwd(), base = "", sourceMap) {
const sourceRoot = sourceMap.sourceRoot || "";
const resolvedBase = path.resolve(cwd, base);
const resolvedSourceRoot = path.resolve(resolvedBase, sourceRoot);
sourceMap.file = path.resolve(resolvedBase, sourceMap.file).replace(/\\/g, "/");
sourceMap.sources = sourceMap.sources.map(source => path.resolve(resolvedSourceRoot, source).replace(/\\/g, "/"));
sourceMap.sourceRoot = "";
}
exports.makeAbsoluteSourceMap = makeAbsoluteSourceMap;
/**
* @param {string | undefined} cwd
* @param {string | undefined} base
* @param {string} sourceRoot
* @param {RawSourceMap} sourceMap
*/
function makeRelativeSourceMap(cwd = process.cwd(), base = "", sourceRoot, sourceMap) {
makeAbsoluteSourceMap(cwd, base, sourceMap);
const resolvedBase = path.resolve(cwd, base);
const resolvedSourceRoot = path.resolve(resolvedBase, sourceRoot);
sourceMap.file = path.relative(resolvedBase, sourceMap.file).replace(/\\/g, "/");
sourceMap.sources = sourceMap.sources.map(source => path.relative(resolvedSourceRoot, source).replace(/\\/g, "/"));
sourceMap.sourceRoot = sourceRoot;
}
exports.makeRelativeSourceMap = makeRelativeSourceMap;
/**
* @param {string} message
* @returns {never}
-124
View File
@@ -1,124 +0,0 @@
/// <reference path="../src/harness/external/node.d.ts" />
/// <reference path="../built/local/typescript.d.ts" />
import * as fs from "fs";
import * as path from "path";
import * as typescript from "typescript";
declare var ts: typeof typescript;
var tsSourceDir = "../src";
var tsBuildDir = "../built/local";
var testOutputDir = "../built/benchmark";
var sourceFiles = [
"compiler/types.ts",
"compiler/core.ts",
"compiler/sys.ts",
"compiler/diagnosticInformationMap.generated.ts",
"compiler/scanner.ts",
"compiler/binder.ts",
"compiler/utilities.ts",
"compiler/parser.ts",
"compiler/checker.ts",
"compiler/declarationEmitter.ts",
"compiler/emitter.ts",
"compiler/program.ts",
"compiler/commandLineParser.ts",
"compiler/tsc.ts"];
// .ts sources for the compiler, used as a test input
var rawCompilerSources = "";
sourceFiles.forEach(f=> {
rawCompilerSources += "\r\n" + fs.readFileSync(path.join(tsSourceDir, f)).toString();
});
var compilerSources = `var compilerSources = ${JSON.stringify(rawCompilerSources) };`;
// .js code for the compiler, what we are actually testing
var rawCompilerJavaScript = fs.readFileSync(path.join(tsBuildDir, "tsc.js")).toString();
rawCompilerJavaScript = rawCompilerJavaScript.replace("ts.executeCommandLine(ts.sys.args);", "");
// lib.d.ts sources
var rawLibSources = fs.readFileSync(path.join(tsBuildDir, "lib.d.ts")).toString();
var libSources = `var libSources = ${JSON.stringify(rawLibSources) };`;
// write test output
if (!fs.existsSync(testOutputDir)) {
fs.mkdirSync(testOutputDir);
}
// 1. compiler ts sources, used to test
fs.writeFileSync(
path.join(testOutputDir, "compilerSources.js"),
`${ compilerSources } \r\n ${ libSources }`);
// 2. the compiler js sources + a call the compiler
fs.writeFileSync(
path.join(testOutputDir, "benchmarktsc.js"),
`${ rawCompilerJavaScript }\r\n${ compile.toString() }\r\ncompile(compilerSources, libSources);`);
// 3. test html file to drive the test
fs.writeFileSync(
path.join(testOutputDir, "benchmarktsc.html"),
`<!DOCTYPE HTML>
<html>
<head>
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<title>Typescript 1.1 Compiler</title>
<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">
</head>
<body>
<div><span>Status: </span><span id="status">Running</span></div>
<div id="main"><span>End-to-End Time: </span><span id="totalTime">N/A</span></div>
<script>
var startTime = performance.now();
</script>
<script src="compilerSources.js"></script>
<script src="benchmarktsc.js"></script>
<script>
var endTime = performance.now();
document.getElementById("totalTime").innerHTML = parseInt(endTime - startTime, 10);
document.getElementById("status").innerHTML = "DONE";
</script>
</body>
</html>`);
function compile(compilerSources, librarySources) {
var program = ts.createProgram(
["lib.d.ts", "compiler.ts"],
{
noResolve: true,
out: "compiler.js",
removeComments: true,
target: ts.ScriptTarget.ES3
}, {
getDefaultLibFileName: () => "lib.d.ts",
getSourceFile: (filename, languageVersion) => {
var source: string;
if (filename === "lib.d.ts") source = librarySources;
else if (filename === "compiler.ts") source = compilerSources;
else console.error("Unexpected read file request: " + filename);
return ts.createSourceFile(filename, source, languageVersion);
},
writeFile: (filename, data, writeByteOrderMark) => {
if (filename !== "compiler.js")
console.error("Unexpected write file request: " + filename);
// console.log(data);
},
getCurrentDirectory: () => "",
getCanonicalFileName: (filename) => filename,
useCaseSensitiveFileNames: () => false,
getNewLine: () => "\r\n"
});
var emitOutput = program.emit();
var errors = program.getSyntacticDiagnostics()
.concat(program.getSemanticDiagnostics())
.concat(program.getGlobalDiagnostics())
.concat(emitOutput.diagnostics);
if (errors.length) {
console.error("Unexpected errors.");
errors.forEach(e=> console.log(`${e.code}: ${e.messageText}`))
}
}
-125
View File
@@ -1,125 +0,0 @@
/// <reference types="node"/>
import fs = require('fs');
import path = require('path');
interface IOLog {
filesRead: {
path: string;
result: { contents: string; };
}[];
arguments: string[];
}
module Commands {
export function dir(obj: IOLog) {
obj.filesRead.filter(f => f.result !== undefined).forEach(f => {
console.log(f.path);
});
}
dir['description'] = ': displays a list of files';
export function find(obj: IOLog, str: string) {
obj.filesRead.filter(f => f.result !== undefined).forEach(f => {
var lines = f.result.contents.split('\n');
var printedHeader = false;
lines.forEach(line => {
if (line.indexOf(str) >= 0) {
if (!printedHeader) {
console.log(' === ' + f.path + ' ===');
printedHeader = true;
}
console.log(line);
}
});
});
}
find['description'] = ' string: finds text in files';
export function grab(obj: IOLog, filename: string) {
obj.filesRead.filter(f => f.result !== undefined).forEach(f => {
if (path.basename(f.path) === filename) {
fs.writeFile(filename, f.result.contents);
}
});
}
grab['description'] = ' filename.ts: writes out the specified file to disk';
export function extract(obj: IOLog, outputFolder: string) {
var directorySeparator = "/";
function directoryExists(path: string): boolean {
return fs.existsSync(path) && fs.statSync(path).isDirectory();
}
function getDirectoryPath(path: string) {
return path.substr(0, Math.max(getRootLength(path), path.lastIndexOf(directorySeparator)));
}
function getRootLength(path: string): number {
if (path.charAt(0) === directorySeparator) {
if (path.charAt(1) !== directorySeparator) return 1;
var p1 = path.indexOf(directorySeparator, 2);
if (p1 < 0) return 2;
var p2 = path.indexOf(directorySeparator, p1 + 1);
if (p2 < 0) return p1 + 1;
return p2 + 1;
}
if (path.charAt(1) === ":") {
if (path.charAt(2) === directorySeparator) return 3;
}
return 0;
}
function ensureDirectoriesExist(directoryPath: string) {
if (directoryPath.length > getRootLength(directoryPath) && !directoryExists(directoryPath)) {
var parentDirectory = getDirectoryPath(directoryPath);
ensureDirectoriesExist(parentDirectory);
console.log("creating directory: " + directoryPath);
fs.mkdirSync(directoryPath);
}
}
function normalizeSlashes(path: string): string {
return path.replace(/\\/g, "/");
}
function transalatePath(outputFolder:string, path: string): string {
return normalizeSlashes(outputFolder + directorySeparator + path.replace(":", ""));
}
function fileExists(path: string): boolean {
return fs.existsSync(path);
}
obj.filesRead.forEach(f => {
var filename = transalatePath(outputFolder, f.path);
ensureDirectoriesExist(getDirectoryPath(filename));
console.log("writing filename: " + filename);
fs.writeFileSync(filename, f.result.contents);
});
console.log("Command: tsc ");
obj.arguments.forEach(a => {
if (getRootLength(a) > 0) {
console.log(transalatePath(outputFolder, a));
}
else {
console.log(a);
}
console.log(" ");
});
}
extract['description'] = ' outputFolder: extract all input files to <outputFolder>';
}
var args = process.argv.slice(2);
if (args.length < 2) {
console.log('Usage: node ior.js path_to_file.json [command]');
console.log('List of commands: ');
Object.keys(Commands).forEach(k => console.log(' ' + k + Commands[k]['description']));
} else {
var cmd: Function = Commands[args[1]];
if (cmd === undefined) {
console.log('Unknown command ' + args[1]);
} else {
fs.readFile(args[0], 'utf-8', (err, data) => {
if (err) throw err;
var json = JSON.parse(data);
cmd.apply(undefined, [json].concat(args.slice(2)));
});
}
}
-50
View File
@@ -1,50 +0,0 @@
var tslint = require("tslint");
var fs = require("fs");
var path = require("path");
function getLinterOptions() {
return {
formatter: "prose",
formattersDirectory: undefined,
rulesDirectory: "built/local/tslint"
};
}
function getLinterConfiguration() {
return tslint.Configuration.loadConfigurationFromPath(path.join(__dirname, "../tslint.json"));
}
function lintFileContents(options, configuration, path, contents) {
var ll = new tslint.Linter(options);
ll.lint(path, contents, configuration);
return ll.getResult();
}
function lintFileAsync(options, configuration, path, cb) {
fs.readFile(path, "utf8", function (err, contents) {
if (err) {
return cb(err);
}
var result = lintFileContents(options, configuration, path, contents);
cb(undefined, result);
});
}
process.on("message", function (data) {
switch (data.kind) {
case "file":
var target = data.name;
var lintOptions = getLinterOptions();
var lintConfiguration = getLinterConfiguration();
lintFileAsync(lintOptions, lintConfiguration, target, function (err, result) {
if (err) {
process.send({ kind: "error", error: err.toString() });
return;
}
process.send({ kind: "result", failures: result.failureCount, output: result.output });
});
break;
case "close":
process.exit(0);
break;
}
});
-8
View File
@@ -1,13 +1,5 @@
import { TaskFunction } from "gulp";
declare module "gulp-clone" {
function Clone(): NodeJS.ReadWriteStream;
namespace Clone {
export function sink() : NodeJS.ReadWriteStream & {tap: () => NodeJS.ReadWriteStream};
}
export = Clone;
}
declare module "gulp-insert" {
export function append(text: string | Buffer): NodeJS.ReadWriteStream;
export function prepend(text: string | Buffer): NodeJS.ReadWriteStream;
-21
View File
@@ -1,21 +0,0 @@
MIT License
Copyright (c) Microsoft Corporation. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE
-2856
View File
File diff suppressed because it is too large Load Diff
-109
View File
@@ -1,109 +0,0 @@
import Mocha = require("../../");
export = common;
declare function common(suites: Mocha.Suite[], context: Mocha.MochaGlobals, mocha: Mocha): common.CommonFunctions;
declare namespace common {
export interface CommonFunctions {
/**
* This is only present if flag --delay is passed into Mocha. It triggers
* root suite execution.
*/
runWithSuite(suite: Mocha.Suite): () => void;
/**
* Execute before running tests.
*/
before(fn?: Mocha.Func | Mocha.AsyncFunc): void;
/**
* Execute before running tests.
*/
before(name: string, fn?: Mocha.Func | Mocha.AsyncFunc): void;
/**
* Execute after running tests.
*/
after(fn?: Mocha.Func | Mocha.AsyncFunc): void;
/**
* Execute after running tests.
*/
after(name: string, fn?: Mocha.Func | Mocha.AsyncFunc): void;
/**
* Execute before each test case.
*/
beforeEach(fn?: Mocha.Func | Mocha.AsyncFunc): void;
/**
* Execute before each test case.
*/
beforeEach(name: string, fn?: Mocha.Func | Mocha.AsyncFunc): void;
/**
* Execute after each test case.
*/
afterEach(fn?: Mocha.Func | Mocha.AsyncFunc): void;
/**
* Execute after each test case.
*/
afterEach(name: string, fn?: Mocha.Func | Mocha.AsyncFunc): void;
suite: SuiteFunctions;
test: TestFunctions;
}
export interface CreateOptions {
/** Title of suite */
title: string;
/** Suite function */
fn?: (this: Mocha.Suite) => void;
/** Is suite pending? */
pending?: boolean;
/** Filepath where this Suite resides */
file?: string;
/** Is suite exclusive? */
isOnly?: boolean;
}
export interface SuiteFunctions {
/**
* Create an exclusive Suite; convenience function
*/
only(opts: CreateOptions): Mocha.Suite;
/**
* Create a Suite, but skip it; convenience function
*/
skip(opts: CreateOptions): Mocha.Suite;
/**
* Creates a suite.
*/
create(opts: CreateOptions): Mocha.Suite;
}
export interface TestFunctions {
/**
* Exclusive test-case.
*/
only(mocha: Mocha, test: Mocha.Test): Mocha.Test;
/**
* Pending test case.
*/
skip(title: string): void;
/**
* Number of retry attempts
*/
retries(n: number): void;
}
}
-17
View File
@@ -1,17 +0,0 @@
export = milliseconds;
/**
* Parse the given `str` and return milliseconds.
*
* @see {@link https://mochajs.org/api/module-milliseconds.html}
* @see {@link https://mochajs.org/api/module-milliseconds.html#~parse}
*/
declare function milliseconds(val: string): number;
/**
* Format for `ms`.
*
* @see {@link https://mochajs.org/api/module-milliseconds.html}
* @see {@link https://mochajs.org/api/module-milliseconds.html#~format}
*/
declare function milliseconds(val: number): string;
-5
View File
@@ -1,5 +0,0 @@
{
"name": "@types/mocha",
"private": true,
"version": "5.2.1"
}
+242 -107
View File
@@ -228,9 +228,9 @@ namespace ts {
isContextSensitive,
getFullyQualifiedName,
getResolvedSignature: (node, candidatesOutArray, agumentCount) =>
getResolvedSignatureWorker(node, candidatesOutArray, agumentCount, /*isForSignatureHelp*/ false),
getResolvedSignatureWorker(node, candidatesOutArray, agumentCount, CheckMode.Normal),
getResolvedSignatureForSignatureHelp: (node, candidatesOutArray, agumentCount) =>
getResolvedSignatureWorker(node, candidatesOutArray, agumentCount, /*isForSignatureHelp*/ true),
getResolvedSignatureWorker(node, candidatesOutArray, agumentCount, CheckMode.IsForSignatureHelp),
getConstantValue: nodeIn => {
const node = getParseTreeNode(nodeIn, canHaveConstantValue);
return node ? getConstantValue(node) : undefined;
@@ -374,10 +374,10 @@ namespace ts {
getLocalTypeParametersOfClassOrInterfaceOrTypeAlias,
};
function getResolvedSignatureWorker(nodeIn: CallLikeExpression, candidatesOutArray: Signature[] | undefined, argumentCount: number | undefined, isForSignatureHelp: boolean): Signature | undefined {
function getResolvedSignatureWorker(nodeIn: CallLikeExpression, candidatesOutArray: Signature[] | undefined, argumentCount: number | undefined, checkMode: CheckMode): Signature | undefined {
const node = getParseTreeNode(nodeIn, isCallLikeExpression);
apparentArgumentCount = argumentCount;
const res = node ? getResolvedSignature(node, candidatesOutArray, isForSignatureHelp) : undefined;
const res = node ? getResolvedSignature(node, candidatesOutArray, checkMode) : undefined;
apparentArgumentCount = undefined;
return res;
}
@@ -688,10 +688,12 @@ namespace ts {
}
const enum CheckMode {
Normal = 0, // Normal type checking
SkipContextSensitive = 1, // Skip context sensitive function expressions
Inferential = 2, // Inferential typing
Contextual = 3, // Normal type checking informed by a contextual type, therefore not cacheable
Normal = 0, // Normal type checking
Contextual = 1 << 0, // Explicitly assigned contextual type, therefore not cacheable
Inferential = 1 << 1, // Inferential typing
SkipContextSensitive = 1 << 2, // Skip context sensitive function expressions
SkipGenericFunctions = 1 << 3, // Skip single signature generic functions
IsForSignatureHelp = 1 << 4, // Call resolution for purposes of signature help
}
const enum CallbackCheck {
@@ -3981,7 +3983,7 @@ namespace ts {
context.flags &= ~NodeBuilderFlags.WriteTypeParametersInQualifiedName; // Avoids potential infinite loop when building for a claimspace with a generic
const shouldUseGeneratedName =
context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams &&
type.symbol.declarations[0] &&
type.symbol.declarations && type.symbol.declarations[0] &&
isTypeParameterDeclaration(type.symbol.declarations[0]) &&
typeParameterShadowsNameInScope(type, context);
const name = shouldUseGeneratedName
@@ -8373,9 +8375,23 @@ namespace ts {
return undefined;
}
function getSignatureInstantiation(signature: Signature, typeArguments: Type[] | undefined, isJavascript: boolean): Signature {
return getSignatureInstantiationWithoutFillingInTypeArguments(signature, fillMissingTypeArguments(typeArguments, signature.typeParameters, getMinTypeArgumentCount(signature.typeParameters), isJavascript));
function getSignatureInstantiation(signature: Signature, typeArguments: Type[] | undefined, isJavascript: boolean, inferredTypeParameters?: ReadonlyArray<TypeParameter>): Signature {
const instantiatedSignature = getSignatureInstantiationWithoutFillingInTypeArguments(signature, fillMissingTypeArguments(typeArguments, signature.typeParameters, getMinTypeArgumentCount(signature.typeParameters), isJavascript));
if (inferredTypeParameters) {
const returnSignature = getSingleCallSignature(getReturnTypeOfSignature(instantiatedSignature));
if (returnSignature) {
const newReturnSignature = cloneSignature(returnSignature);
newReturnSignature.typeParameters = inferredTypeParameters;
newReturnSignature.target = returnSignature.target;
newReturnSignature.mapper = returnSignature.mapper;
const newInstantiatedSignature = cloneSignature(instantiatedSignature);
newInstantiatedSignature.resolvedReturnType = getOrCreateTypeFromSignature(newReturnSignature);
return newInstantiatedSignature;
}
}
return instantiatedSignature;
}
function getSignatureInstantiationWithoutFillingInTypeArguments(signature: Signature, typeArguments: ReadonlyArray<Type> | undefined): Signature {
const instantiations = signature.instantiations || (signature.instantiations = createMap<Signature>());
const id = getTypeListId(typeArguments);
@@ -8389,6 +8405,7 @@ namespace ts {
function createSignatureInstantiation(signature: Signature, typeArguments: ReadonlyArray<Type> | undefined): Signature {
return instantiateSignature(signature, createSignatureTypeMapper(signature, typeArguments), /*eraseTypeParameters*/ true);
}
function createSignatureTypeMapper(signature: Signature, typeArguments: ReadonlyArray<Type> | undefined): TypeMapper {
return createTypeMapper(signature.typeParameters!, typeArguments);
}
@@ -8790,7 +8807,7 @@ namespace ts {
function getTypeReferenceTypeWorker(node: NodeWithTypeArguments, symbol: Symbol, typeArguments: Type[] | undefined): Type | undefined {
if (symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
if (symbol.valueDeclaration && isBinaryExpression(symbol.valueDeclaration.parent)) {
if (symbol.valueDeclaration && symbol.valueDeclaration.parent && isBinaryExpression(symbol.valueDeclaration.parent)) {
const jsdocType = getJSDocTypeReference(node, symbol, typeArguments);
if (jsdocType) {
return jsdocType;
@@ -20035,27 +20052,36 @@ namespace ts {
// Instantiate a generic signature in the context of a non-generic signature (section 3.8.5 in TypeScript spec)
function instantiateSignatureInContextOf(signature: Signature, contextualSignature: Signature, contextualMapper?: TypeMapper, compareTypes?: TypeComparer): Signature {
const context = createInferenceContext(signature.typeParameters!, signature, InferenceFlags.None, compareTypes);
const sourceSignature = contextualMapper ? instantiateSignature(contextualSignature, contextualMapper) : contextualSignature;
// We clone the contextualMapper to avoid fixing. For example, when the source signature is <T>(x: T) => T[] and
// the contextual signature is (...args: A) => B, we want to infer the element type of A's constraint (say 'any')
// for T but leave it possible to later infer '[any]' back to A.
const restType = getEffectiveRestType(contextualSignature);
const mapper = contextualMapper && restType && restType.flags & TypeFlags.TypeParameter ? cloneTypeMapper(contextualMapper) : contextualMapper;
const sourceSignature = mapper ? instantiateSignature(contextualSignature, mapper) : contextualSignature;
forEachMatchingParameterType(sourceSignature, signature, (source, target) => {
// Type parameters from outer context referenced by source type are fixed by instantiation of the source type
inferTypes(context.inferences, source, target);
});
if (!contextualMapper) {
inferTypes(context.inferences, getReturnTypeOfSignature(contextualSignature), getReturnTypeOfSignature(signature), InferencePriority.ReturnType);
const signaturePredicate = getTypePredicateOfSignature(signature);
const contextualPredicate = getTypePredicateOfSignature(sourceSignature);
if (signaturePredicate && contextualPredicate && signaturePredicate.kind === contextualPredicate.kind &&
(signaturePredicate.kind === TypePredicateKind.This || signaturePredicate.parameterIndex === (contextualPredicate as IdentifierTypePredicate).parameterIndex)) {
inferTypes(context.inferences, contextualPredicate.type, signaturePredicate.type, InferencePriority.ReturnType);
}
}
return getSignatureInstantiation(signature, getInferredTypes(context), isInJSFile(contextualSignature.declaration));
}
function inferJsxTypeArguments(node: JsxOpeningLikeElement, signature: Signature, excludeArgument: ReadonlyArray<boolean> | undefined, context: InferenceContext): Type[] {
function inferJsxTypeArguments(node: JsxOpeningLikeElement, signature: Signature, checkMode: CheckMode, context: InferenceContext): Type[] {
const paramType = getEffectiveFirstArgumentForJsxSignature(signature, node);
const checkAttrType = checkExpressionWithContextualType(node.attributes, paramType, excludeArgument && excludeArgument[0] !== undefined ? identityMapper : context);
const checkAttrType = checkExpressionWithContextualType(node.attributes, paramType, context, checkMode);
inferTypes(context.inferences, checkAttrType, paramType);
return getInferredTypes(context);
}
function inferTypeArguments(node: CallLikeExpression, signature: Signature, args: ReadonlyArray<Expression>, excludeArgument: ReadonlyArray<boolean> | undefined, context: InferenceContext): Type[] {
function inferTypeArguments(node: CallLikeExpression, signature: Signature, args: ReadonlyArray<Expression>, checkMode: CheckMode, context: InferenceContext): Type[] {
// Clear out all the inference results from the last time inferTypeArguments was called on this context
for (const inference of context.inferences) {
// As an optimization, we don't have to clear (and later recompute) inferred types
@@ -20068,7 +20094,7 @@ namespace ts {
}
if (isJsxOpeningLikeElement(node)) {
return inferJsxTypeArguments(node, signature, excludeArgument, context);
return inferJsxTypeArguments(node, signature, checkMode, context);
}
// If a contextual type is available, infer from that type to the return type of the call expression. For
@@ -20115,10 +20141,7 @@ namespace ts {
const arg = args[i];
if (arg.kind !== SyntaxKind.OmittedExpression) {
const paramType = getTypeAtPosition(signature, i);
// For context sensitive arguments we pass the identityMapper, which is a signal to treat all
// context sensitive function expressions as wildcards
const mapper = excludeArgument && excludeArgument[i] !== undefined ? identityMapper : context;
const argType = checkExpressionWithContextualType(arg, paramType, mapper);
const argType = checkExpressionWithContextualType(arg, paramType, context, checkMode);
inferTypes(context.inferences, argType, paramType);
}
}
@@ -20146,7 +20169,7 @@ namespace ts {
// and the argument are ...x forms.
return arg.kind === SyntaxKind.SyntheticExpression ?
createArrayType((<SyntheticExpression>arg).type) :
getArrayifiedType(checkExpressionWithContextualType((<SpreadElement>arg).expression, restType, context));
getArrayifiedType(checkExpressionWithContextualType((<SpreadElement>arg).expression, restType, context, CheckMode.Normal));
}
}
const contextualType = getIndexTypeOfType(restType, IndexKind.Number) || anyType;
@@ -20154,7 +20177,7 @@ namespace ts {
const types = [];
let spreadIndex = -1;
for (let i = index; i < argCount; i++) {
const argType = checkExpressionWithContextualType(args[i], contextualType, context);
const argType = checkExpressionWithContextualType(args[i], contextualType, context, CheckMode.Normal);
if (spreadIndex < 0 && isSpreadArgument(args[i])) {
spreadIndex = i - index;
}
@@ -20212,14 +20235,13 @@ namespace ts {
* @param node a JSX opening-like element we are trying to figure its call signature
* @param signature a candidate signature we are trying whether it is a call signature
* @param relation a relationship to check parameter and argument type
* @param excludeArgument
*/
function checkApplicableSignatureForJsxOpeningLikeElement(node: JsxOpeningLikeElement, signature: Signature, relation: Map<RelationComparisonResult>, excludeArgument: boolean[] | undefined, reportErrors: boolean) {
function checkApplicableSignatureForJsxOpeningLikeElement(node: JsxOpeningLikeElement, signature: Signature, relation: Map<RelationComparisonResult>, checkMode: CheckMode, reportErrors: boolean) {
// Stateless function components can have maximum of three arguments: "props", "context", and "updater".
// However "context" and "updater" are implicit and can't be specify by users. Only the first parameter, props,
// can be specified by users through attributes property.
const paramType = getEffectiveFirstArgumentForJsxSignature(signature, node);
const attributesType = checkExpressionWithContextualType(node.attributes, paramType, excludeArgument && excludeArgument[0] ? identityMapper : undefined);
const attributesType = checkExpressionWithContextualType(node.attributes, paramType, /*contextualMapper*/ undefined, checkMode);
return checkTypeRelatedToAndOptionallyElaborate(attributesType, paramType, relation, reportErrors ? node.tagName : undefined, node.attributes);
}
@@ -20228,10 +20250,10 @@ namespace ts {
args: ReadonlyArray<Expression>,
signature: Signature,
relation: Map<RelationComparisonResult>,
excludeArgument: boolean[] | undefined,
checkMode: CheckMode,
reportErrors: boolean) {
if (isJsxOpeningLikeElement(node)) {
return checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, excludeArgument, reportErrors);
return checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, checkMode, reportErrors);
}
const thisType = getThisTypeOfSignature(signature);
if (thisType && thisType !== voidType && node.kind !== SyntaxKind.NewExpression) {
@@ -20253,11 +20275,11 @@ namespace ts {
const arg = args[i];
if (arg.kind !== SyntaxKind.OmittedExpression) {
const paramType = getTypeAtPosition(signature, i);
const argType = checkExpressionWithContextualType(arg, paramType, excludeArgument && excludeArgument[i] ? identityMapper : undefined);
// If one or more arguments are still excluded (as indicated by a non-null excludeArgument parameter),
const argType = checkExpressionWithContextualType(arg, paramType, /*contextualMapper*/ undefined, checkMode);
// If one or more arguments are still excluded (as indicated by CheckMode.SkipContextSensitive),
// we obtain the regular type of any object literal arguments because we may not have inferred complete
// parameter types yet and therefore excess property checks may yield false positives (see #17041).
const checkArgType = excludeArgument ? getRegularTypeOfObjectLiteral(argType) : argType;
const checkArgType = checkMode & CheckMode.SkipContextSensitive ? getRegularTypeOfObjectLiteral(argType) : argType;
if (!checkTypeRelatedToAndOptionallyElaborate(checkArgType, paramType, relation, reportErrors ? arg : undefined, arg, headMessage)) {
return false;
}
@@ -20473,7 +20495,7 @@ namespace ts {
return createDiagnosticForNodeArray(getSourceFileOfNode(node), typeArguments, Diagnostics.Expected_0_type_arguments_but_got_1, belowArgCount === -Infinity ? aboveArgCount : belowArgCount, argCount);
}
function resolveCall(node: CallLikeExpression, signatures: ReadonlyArray<Signature>, candidatesOutArray: Signature[] | undefined, isForSignatureHelp: boolean, fallbackError?: DiagnosticMessage): Signature {
function resolveCall(node: CallLikeExpression, signatures: ReadonlyArray<Signature>, candidatesOutArray: Signature[] | undefined, checkMode: CheckMode, fallbackError?: DiagnosticMessage): Signature {
const isTaggedTemplate = node.kind === SyntaxKind.TaggedTemplateExpression;
const isDecorator = node.kind === SyntaxKind.Decorator;
const isJsxOpeningOrSelfClosingElement = isJsxOpeningLikeElement(node);
@@ -20515,7 +20537,7 @@ namespace ts {
// For a decorator, no arguments are susceptible to contextual typing due to the fact
// decorators are applied to a declaration by the emitter, and not to an expression.
const isSingleNonGenericCandidate = candidates.length === 1 && !candidates[0].typeParameters;
let excludeArgument = !isDecorator && !isSingleNonGenericCandidate ? getExcludeArgument(args) : undefined;
let argCheckMode = !isDecorator && !isSingleNonGenericCandidate && some(args, isContextSensitive) ? CheckMode.SkipContextSensitive : CheckMode.Normal;
// The following variables are captured and modified by calls to chooseOverload.
// If overload resolution or type argument inference fails, we want to report the
@@ -20546,7 +20568,7 @@ namespace ts {
// If we are in signature help, a trailing comma indicates that we intend to provide another argument,
// so we will only accept overloads with arity at least 1 higher than the current number of provided arguments.
const signatureHelpTrailingComma =
isForSignatureHelp && node.kind === SyntaxKind.CallExpression && node.arguments.hasTrailingComma;
!!(checkMode & CheckMode.IsForSignatureHelp) && node.kind === SyntaxKind.CallExpression && node.arguments.hasTrailingComma;
// Section 4.12.1:
// if the candidate list contains one or more signatures for which the type of each argument
@@ -20574,12 +20596,7 @@ namespace ts {
// skip the checkApplicableSignature check.
if (reportErrors) {
if (candidateForArgumentError) {
// excludeArgument is undefined, in this case also equivalent to [undefined, undefined, ...]
// The importance of excludeArgument is to prevent us from typing function expression parameters
// in arguments too early. If possible, we'd like to only type them once we know the correct
// overload. However, this matters for the case where the call is correct. When the call is
// an error, we don't need to exclude any arguments, although it would cause no harm to do so.
checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, /*excludeArgument*/ undefined, /*reportErrors*/ true);
checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, CheckMode.Normal, /*reportErrors*/ true);
}
else if (candidateForArgumentArityError) {
diagnostics.add(getArgumentArityError(node, [candidateForArgumentArityError], args));
@@ -20613,7 +20630,7 @@ namespace ts {
if (typeArguments || !hasCorrectArity(node, args, candidate, signatureHelpTrailingComma)) {
return undefined;
}
if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, /*reportErrors*/ false)) {
if (!checkApplicableSignature(node, args, candidate, relation, CheckMode.Normal, /*reportErrors*/ false)) {
candidateForArgumentError = candidate;
return undefined;
}
@@ -20640,9 +20657,10 @@ namespace ts {
}
else {
inferenceContext = createInferenceContext(candidate.typeParameters, candidate, /*flags*/ isInJSFile(node) ? InferenceFlags.AnyDefault : InferenceFlags.None);
typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext);
typeArgumentTypes = inferTypeArguments(node, candidate, args, argCheckMode | CheckMode.SkipGenericFunctions, inferenceContext);
argCheckMode |= inferenceContext.flags & InferenceFlags.SkippedGenericFunction ? CheckMode.SkipGenericFunctions : CheckMode.Normal;
}
checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJSFile(candidate.declaration));
checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJSFile(candidate.declaration), inferenceContext && inferenceContext.inferredTypeParameters);
// If the original signature has a generic rest type, instantiation may produce a
// signature with different arity and we need to perform another arity check.
if (getNonArrayRestType(candidate) && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma)) {
@@ -20653,21 +20671,21 @@ namespace ts {
else {
checkCandidate = candidate;
}
if (!checkApplicableSignature(node, args, checkCandidate, relation, excludeArgument, /*reportErrors*/ false)) {
if (!checkApplicableSignature(node, args, checkCandidate, relation, argCheckMode, /*reportErrors*/ false)) {
// Give preference to error candidates that have no rest parameters (as they are more specific)
if (!candidateForArgumentError || getEffectiveRestType(candidateForArgumentError) || !getEffectiveRestType(checkCandidate)) {
candidateForArgumentError = checkCandidate;
}
continue;
}
if (excludeArgument) {
if (argCheckMode) {
// If one or more context sensitive arguments were excluded, we start including
// them now (and keeping do so for any subsequent candidates) and perform a second
// round of type inference and applicability checking for this particular candidate.
excludeArgument = undefined;
argCheckMode = CheckMode.Normal;
if (inferenceContext) {
const typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext);
checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJSFile(candidate.declaration));
const typeArgumentTypes = inferTypeArguments(node, candidate, args, argCheckMode, inferenceContext);
checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJSFile(candidate.declaration), inferenceContext && inferenceContext.inferredTypeParameters);
// If the original signature has a generic rest type, instantiation may produce a
// signature with different arity and we need to perform another arity check.
if (getNonArrayRestType(candidate) && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma)) {
@@ -20675,7 +20693,7 @@ namespace ts {
continue;
}
}
if (!checkApplicableSignature(node, args, checkCandidate, relation, excludeArgument, /*reportErrors*/ false)) {
if (!checkApplicableSignature(node, args, checkCandidate, relation, argCheckMode, /*reportErrors*/ false)) {
// Give preference to error candidates that have no rest parameters (as they are more specific)
if (!candidateForArgumentError || getEffectiveRestType(candidateForArgumentError) || !getEffectiveRestType(checkCandidate)) {
candidateForArgumentError = checkCandidate;
@@ -20691,21 +20709,6 @@ namespace ts {
}
}
function getExcludeArgument(args: ReadonlyArray<Expression>): boolean[] | undefined {
let excludeArgument: boolean[] | undefined;
// We do not need to call `getEffectiveArgumentCount` here as it only
// applies when calculating the number of arguments for a decorator.
for (let i = 0; i < args.length; i++) {
if (isContextSensitive(args[i])) {
if (!excludeArgument) {
excludeArgument = new Array(args.length);
}
excludeArgument[i] = true;
}
}
return excludeArgument;
}
// No signature was applicable. We have already reported the errors for the invalid signature.
// If this is a type resolution session, e.g. Language Service, try to get better information than anySignature.
function getCandidateForOverloadFailure(
@@ -20805,7 +20808,7 @@ namespace ts {
function inferSignatureInstantiationForOverloadFailure(node: CallLikeExpression, typeParameters: ReadonlyArray<TypeParameter>, candidate: Signature, args: ReadonlyArray<Expression>): Signature {
const inferenceContext = createInferenceContext(typeParameters, candidate, /*flags*/ isInJSFile(node) ? InferenceFlags.AnyDefault : InferenceFlags.None);
const typeArgumentTypes = inferTypeArguments(node, candidate, args, getExcludeArgument(args), inferenceContext);
const typeArgumentTypes = inferTypeArguments(node, candidate, args, CheckMode.SkipContextSensitive | CheckMode.SkipGenericFunctions, inferenceContext);
return createSignatureInstantiation(candidate, typeArgumentTypes);
}
@@ -20828,7 +20831,7 @@ namespace ts {
return maxParamsIndex;
}
function resolveCallExpression(node: CallExpression, candidatesOutArray: Signature[] | undefined, isForSignatureHelp: boolean): Signature {
function resolveCallExpression(node: CallExpression, candidatesOutArray: Signature[] | undefined, checkMode: CheckMode): Signature {
if (node.expression.kind === SyntaxKind.SuperKeyword) {
const superType = checkSuperExpression(node.expression);
if (isTypeAny(superType)) {
@@ -20843,7 +20846,7 @@ namespace ts {
const baseTypeNode = getEffectiveBaseTypeNode(getContainingClass(node)!);
if (baseTypeNode) {
const baseConstructors = getInstantiatedConstructorsForTypeArguments(superType, baseTypeNode.typeArguments, baseTypeNode);
return resolveCall(node, baseConstructors, candidatesOutArray, isForSignatureHelp);
return resolveCall(node, baseConstructors, candidatesOutArray, checkMode);
}
}
return resolveUntypedCall(node);
@@ -20903,12 +20906,32 @@ namespace ts {
}
return resolveErrorCall(node);
}
// When a call to a generic function is an argument to an outer call to a generic function for which
// inference is in process, we have a choice to make. If the inner call relies on inferences made from
// its contextual type to its return type, deferring the inner call processing allows the best possible
// contextual type to accumulate. But if the outer call relies on inferences made from the return type of
// the inner call, the inner call should be processed early. There's no sure way to know which choice is
// right (only a full unification algorithm can determine that), so we resort to the following heuristic:
// If no type arguments are specified in the inner call and at least one call signature is generic and
// returns a function type, we choose to defer processing. This narrowly permits function composition
// operators to flow inferences through return types, but otherwise processes calls right away. We
// use the resolvingSignature singleton to indicate that we deferred processing. This result will be
// propagated out and eventually turned into silentNeverType (a type that is assignable to anything and
// from which we never make inferences).
if (checkMode & CheckMode.SkipGenericFunctions && !node.typeArguments && callSignatures.some(isGenericFunctionReturningFunction)) {
skippedGenericFunction(node, checkMode);
return resolvingSignature;
}
// If the function is explicitly marked with `@class`, then it must be constructed.
if (callSignatures.some(sig => isInJSFile(sig.declaration) && !!getJSDocClassTag(sig.declaration!))) {
error(node, Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(funcType));
return resolveErrorCall(node);
}
return resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp);
return resolveCall(node, callSignatures, candidatesOutArray, checkMode);
}
function isGenericFunctionReturningFunction(signature: Signature) {
return !!(signature.typeParameters && isFunctionType(getReturnTypeOfSignature(signature)));
}
/**
@@ -20922,7 +20945,7 @@ namespace ts {
!numCallSignatures && !numConstructSignatures && !(apparentFuncType.flags & (TypeFlags.Union | TypeFlags.Never)) && isTypeAssignableTo(funcType, globalFunctionType);
}
function resolveNewExpression(node: NewExpression, candidatesOutArray: Signature[] | undefined, isForSignatureHelp: boolean): Signature {
function resolveNewExpression(node: NewExpression, candidatesOutArray: Signature[] | undefined, checkMode: CheckMode): Signature {
if (node.arguments && languageVersion < ScriptTarget.ES5) {
const spreadIndex = getSpreadArgumentIndex(node.arguments);
if (spreadIndex >= 0) {
@@ -20975,7 +20998,7 @@ namespace ts {
return resolveErrorCall(node);
}
return resolveCall(node, constructSignatures, candidatesOutArray, isForSignatureHelp);
return resolveCall(node, constructSignatures, candidatesOutArray, checkMode);
}
// If expressionType's apparent type is an object type with no construct signatures but
@@ -20984,7 +21007,7 @@ namespace ts {
// operation is Any. It is an error to have a Void this type.
const callSignatures = getSignaturesOfType(expressionType, SignatureKind.Call);
if (callSignatures.length) {
const signature = resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp);
const signature = resolveCall(node, callSignatures, candidatesOutArray, checkMode);
if (!noImplicitAny) {
if (signature.declaration && !isJSConstructor(signature.declaration) && getReturnTypeOfSignature(signature) !== voidType) {
error(node, Diagnostics.Only_a_void_function_can_be_called_with_the_new_keyword);
@@ -21094,7 +21117,7 @@ namespace ts {
}
}
function resolveTaggedTemplateExpression(node: TaggedTemplateExpression, candidatesOutArray: Signature[] | undefined, isForSignatureHelp: boolean): Signature {
function resolveTaggedTemplateExpression(node: TaggedTemplateExpression, candidatesOutArray: Signature[] | undefined, checkMode: CheckMode): Signature {
const tagType = checkExpression(node.tag);
const apparentType = getApparentType(tagType);
@@ -21115,7 +21138,7 @@ namespace ts {
return resolveErrorCall(node);
}
return resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp);
return resolveCall(node, callSignatures, candidatesOutArray, checkMode);
}
/**
@@ -21146,7 +21169,7 @@ namespace ts {
/**
* Resolves a decorator as if it were a call expression.
*/
function resolveDecorator(node: Decorator, candidatesOutArray: Signature[] | undefined, isForSignatureHelp: boolean): Signature {
function resolveDecorator(node: Decorator, candidatesOutArray: Signature[] | undefined, checkMode: CheckMode): Signature {
const funcType = checkExpression(node.expression);
const apparentType = getApparentType(funcType);
if (apparentType === errorType) {
@@ -21175,7 +21198,7 @@ namespace ts {
return resolveErrorCall(node);
}
return resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp, headMessage);
return resolveCall(node, callSignatures, candidatesOutArray, checkMode, headMessage);
}
function createSignatureForJSXIntrinsic(node: JsxOpeningLikeElement, result: Type): Signature {
@@ -21204,11 +21227,11 @@ namespace ts {
);
}
function resolveJsxOpeningLikeElement(node: JsxOpeningLikeElement, candidatesOutArray: Signature[] | undefined, isForSignatureHelp: boolean): Signature {
function resolveJsxOpeningLikeElement(node: JsxOpeningLikeElement, candidatesOutArray: Signature[] | undefined, checkMode: CheckMode): Signature {
if (isJsxIntrinsicIdentifier(node.tagName)) {
const result = getIntrinsicAttributesTypeFromJsxOpeningLikeElement(node);
const fakeSignature = createSignatureForJSXIntrinsic(node, result);
checkTypeAssignableToAndOptionallyElaborate(checkExpressionWithContextualType(node.attributes, getEffectiveFirstArgumentForJsxSignature(fakeSignature, node), /*mapper*/ undefined), result, node.tagName, node.attributes);
checkTypeAssignableToAndOptionallyElaborate(checkExpressionWithContextualType(node.attributes, getEffectiveFirstArgumentForJsxSignature(fakeSignature, node), /*mapper*/ undefined, CheckMode.Normal), result, node.tagName, node.attributes);
return fakeSignature;
}
const exprTypes = checkExpression(node.tagName);
@@ -21228,7 +21251,7 @@ namespace ts {
return resolveErrorCall(node);
}
return resolveCall(node, signatures, candidatesOutArray, isForSignatureHelp);
return resolveCall(node, signatures, candidatesOutArray, checkMode);
}
/**
@@ -21243,19 +21266,19 @@ namespace ts {
signature.parameters.length < getDecoratorArgumentCount(decorator, signature));
}
function resolveSignature(node: CallLikeExpression, candidatesOutArray: Signature[] | undefined, isForSignatureHelp: boolean): Signature {
function resolveSignature(node: CallLikeExpression, candidatesOutArray: Signature[] | undefined, checkMode: CheckMode): Signature {
switch (node.kind) {
case SyntaxKind.CallExpression:
return resolveCallExpression(node, candidatesOutArray, isForSignatureHelp);
return resolveCallExpression(node, candidatesOutArray, checkMode);
case SyntaxKind.NewExpression:
return resolveNewExpression(node, candidatesOutArray, isForSignatureHelp);
return resolveNewExpression(node, candidatesOutArray, checkMode);
case SyntaxKind.TaggedTemplateExpression:
return resolveTaggedTemplateExpression(node, candidatesOutArray, isForSignatureHelp);
return resolveTaggedTemplateExpression(node, candidatesOutArray, checkMode);
case SyntaxKind.Decorator:
return resolveDecorator(node, candidatesOutArray, isForSignatureHelp);
return resolveDecorator(node, candidatesOutArray, checkMode);
case SyntaxKind.JsxOpeningElement:
case SyntaxKind.JsxSelfClosingElement:
return resolveJsxOpeningLikeElement(node, candidatesOutArray, isForSignatureHelp);
return resolveJsxOpeningLikeElement(node, candidatesOutArray, checkMode);
}
throw Debug.assertNever(node, "Branch in 'resolveSignature' should be unreachable.");
}
@@ -21267,7 +21290,7 @@ namespace ts {
* the function will fill it up with appropriate candidate signatures
* @return a signature of the call-like expression or undefined if one can't be found
*/
function getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[] | undefined, isForSignatureHelp = false): Signature {
function getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[] | undefined, checkMode?: CheckMode): Signature {
const links = getNodeLinks(node);
// If getResolvedSignature has already been called, we will have cached the resolvedSignature.
// However, it is possible that either candidatesOutArray was not passed in the first time,
@@ -21278,11 +21301,15 @@ namespace ts {
return cached;
}
links.resolvedSignature = resolvingSignature;
const result = resolveSignature(node, candidatesOutArray, isForSignatureHelp);
// If signature resolution originated in control flow type analysis (for example to compute the
// assigned type in a flow assignment) we don't cache the result as it may be based on temporary
// types from the control flow analysis.
links.resolvedSignature = flowLoopStart === flowLoopCount ? result : cached;
const result = resolveSignature(node, candidatesOutArray, checkMode || CheckMode.Normal);
// When CheckMode.SkipGenericFunctions is set we use resolvingSignature to indicate that call
// resolution should be deferred.
if (result !== resolvingSignature) {
// If signature resolution originated in control flow type analysis (for example to compute the
// assigned type in a flow assignment) we don't cache the result as it may be based on temporary
// types from the control flow analysis.
links.resolvedSignature = flowLoopStart === flowLoopCount ? result : cached;
}
return result;
}
@@ -21366,10 +21393,15 @@ namespace ts {
* @param node The call/new expression to be checked.
* @returns On success, the expression's signature's return type. On failure, anyType.
*/
function checkCallExpression(node: CallExpression | NewExpression): Type {
function checkCallExpression(node: CallExpression | NewExpression, checkMode?: CheckMode): Type {
if (!checkGrammarTypeArguments(node, node.typeArguments)) checkGrammarArguments(node.arguments);
const signature = getResolvedSignature(node);
const signature = getResolvedSignature(node, /*candidatesOutArray*/ undefined, checkMode);
if (signature === resolvingSignature) {
// CheckMode.SkipGenericFunctions is enabled and this is a call to a generic function that
// returns a function type. We defer checking and return anyFunctionType.
return silentNeverType;
}
if (node.expression.kind === SyntaxKind.SuperKeyword) {
return voidType;
@@ -21870,7 +21902,7 @@ namespace ts {
const functionFlags = getFunctionFlags(func);
let type: Type;
if (func.body.kind !== SyntaxKind.Block) {
type = checkExpressionCached(func.body, checkMode);
type = checkExpressionCached(func.body, checkMode && checkMode & ~CheckMode.SkipGenericFunctions);
if (functionFlags & FunctionFlags.Async) {
// From within an async function you can return either a non-promise value or a promise. Any
// Promise/A+ compatible implementation will always assimilate any foreign promise, so the
@@ -22060,7 +22092,7 @@ namespace ts {
forEachReturnStatement(<Block>func.body, returnStatement => {
const expr = returnStatement.expression;
if (expr) {
let type = checkExpressionCached(expr, checkMode);
let type = checkExpressionCached(expr, checkMode && checkMode & ~CheckMode.SkipGenericFunctions);
if (functionFlags & FunctionFlags.Async) {
// From within an async function you can return either a non-promise value or a promise. Any
// Promise/A+ compatible implementation will always assimilate any foreign promise, so the
@@ -22160,7 +22192,7 @@ namespace ts {
checkNodeDeferred(node);
// The identityMapper object is used to indicate that function expressions are wildcards
if (checkMode === CheckMode.SkipContextSensitive && isContextSensitive(node)) {
if (checkMode && checkMode & CheckMode.SkipContextSensitive && isContextSensitive(node)) {
// Skip parameters, return signature with return type that retains noncontextual parts so inferences can still be drawn in an early stage
if (!getEffectiveReturnTypeNode(node) && hasContextSensitiveReturnExpression(node)) {
const links = getNodeLinks(node);
@@ -22200,7 +22232,7 @@ namespace ts {
const signature = getSignaturesOfType(type, SignatureKind.Call)[0];
if (isContextSensitive(node)) {
const contextualMapper = getContextualMapper(node);
if (checkMode === CheckMode.Inferential) {
if (checkMode && checkMode & CheckMode.Inferential) {
inferFromAnnotatedParameters(signature, contextualSignature, contextualMapper);
}
const instantiatedContextualSignature = contextualMapper === identityMapper ?
@@ -23211,15 +23243,13 @@ namespace ts {
return node;
}
function checkExpressionWithContextualType(node: Expression, contextualType: Type, contextualMapper: TypeMapper | undefined): Type {
function checkExpressionWithContextualType(node: Expression, contextualType: Type, contextualMapper: TypeMapper | undefined, checkMode: CheckMode): Type {
const context = getContextNode(node);
const saveContextualType = context.contextualType;
const saveContextualMapper = context.contextualMapper;
context.contextualType = contextualType;
context.contextualMapper = contextualMapper;
const checkMode = contextualMapper === identityMapper ? CheckMode.SkipContextSensitive :
contextualMapper ? CheckMode.Inferential : CheckMode.Contextual;
const type = checkExpression(node, checkMode);
const type = checkExpression(node, checkMode | CheckMode.Contextual | (contextualMapper ? CheckMode.Inferential : 0));
// We strip literal freshness when an appropriate contextual type is present such that contextually typed
// literals always preserve their literal types (otherwise they might widen during type inference). An alternative
// here would be to not mark contextually typed literals as fresh in the first place.
@@ -23233,7 +23263,7 @@ namespace ts {
function checkExpressionCached(node: Expression, checkMode?: CheckMode): Type {
const links = getNodeLinks(node);
if (!links.resolvedType) {
if (checkMode) {
if (checkMode && checkMode !== CheckMode.Normal) {
return checkExpression(node, checkMode);
}
// When computing a type that we're going to cache, we need to ignore any ongoing control flow
@@ -23341,22 +23371,127 @@ namespace ts {
}
function instantiateTypeWithSingleGenericCallSignature(node: Expression | MethodDeclaration | QualifiedName, type: Type, checkMode?: CheckMode) {
if (checkMode === CheckMode.Inferential) {
if (checkMode && checkMode & (CheckMode.Inferential | CheckMode.SkipGenericFunctions)) {
const signature = getSingleCallSignature(type);
if (signature && signature.typeParameters) {
if (checkMode & CheckMode.SkipGenericFunctions) {
skippedGenericFunction(node, checkMode);
return anyFunctionType;
}
const contextualType = getApparentTypeOfContextualType(<Expression>node);
if (contextualType) {
const contextualSignature = getSingleCallSignature(getNonNullableType(contextualType));
if (contextualSignature && !contextualSignature.typeParameters) {
return getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, getContextualMapper(node)));
const context = <InferenceContext>getContextualMapper(node);
// We have an expression that is an argument of a generic function for which we are performing
// type argument inference. The expression is of a function type with a single generic call
// signature and a contextual function type with a single non-generic call signature. Now check
// if the outer function returns a function type with a single non-generic call signature and
// if some of the outer function type parameters have no inferences so far. If so, we can
// potentially add inferred type parameters to the outer function return type.
const returnSignature = context.signature && getSingleCallSignature(getReturnTypeOfSignature(context.signature));
if (returnSignature && !returnSignature.typeParameters && !every(context.inferences, hasInferenceCandidates)) {
// Instantiate the expression type with its own type parameters as type arguments. This
// ensures that the type parameters are not erased to type any during type inference such
// that they can be inferred as actual types.
const uniqueTypeParameters = getUniqueTypeParameters(context, signature.typeParameters);
const strippedType = getOrCreateTypeFromSignature(getSignatureInstantiationWithoutFillingInTypeArguments(signature, uniqueTypeParameters));
// Infer from the stripped expression type to the contextual type starting with an empty
// set of inference candidates.
const inferences = map(context.typeParameters, createInferenceInfo);
inferTypes(inferences, strippedType, contextualType);
// If we produced some inference candidates and if the type parameters for which we produced
// candidates do not already have existing inferences, we adopt the new inference candidates and
// add the type parameters of the expression type to the set of inferred type parameters for
// the outer function return type.
if (some(inferences, hasInferenceCandidates) && !hasOverlappingInferences(context.inferences, inferences)) {
mergeInferences(context.inferences, inferences);
context.inferredTypeParameters = concatenate(context.inferredTypeParameters, uniqueTypeParameters);
return strippedType;
}
}
return getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, context));
}
}
}
}
return type;
}
function skippedGenericFunction(node: Node, checkMode: CheckMode) {
if (checkMode & CheckMode.Inferential) {
// We have skipped a generic function during inferential typing. Obtain the inference context and
// indicate this has occurred such that we know a second pass of inference is be needed.
const context = <InferenceContext>getContextualMapper(node);
context.flags |= InferenceFlags.SkippedGenericFunction;
}
}
function hasInferenceCandidates(info: InferenceInfo) {
return !!(info.candidates || info.contraCandidates);
}
function hasOverlappingInferences(a: InferenceInfo[], b: InferenceInfo[]) {
for (let i = 0; i < a.length; i++) {
if (hasInferenceCandidates(a[i]) && hasInferenceCandidates(b[i])) {
return true;
}
}
return false;
}
function mergeInferences(target: InferenceInfo[], source: InferenceInfo[]) {
for (let i = 0; i < target.length; i++) {
if (!hasInferenceCandidates(target[i]) && hasInferenceCandidates(source[i])) {
target[i] = source[i];
}
}
}
function getUniqueTypeParameters(context: InferenceContext, typeParameters: ReadonlyArray<TypeParameter>): ReadonlyArray<TypeParameter> {
const result: TypeParameter[] = [];
let oldTypeParameters: TypeParameter[] | undefined;
let newTypeParameters: TypeParameter[] | undefined;
for (const tp of typeParameters) {
const name = tp.symbol.escapedName;
if (hasTypeParameterByName(context.inferredTypeParameters, name) || hasTypeParameterByName(result, name)) {
const newName = getUniqueTypeParameterName(concatenate(context.inferredTypeParameters, result), name);
const symbol = createSymbol(SymbolFlags.TypeParameter, newName);
const newTypeParameter = createTypeParameter(symbol);
newTypeParameter.target = tp;
oldTypeParameters = append(oldTypeParameters, tp);
newTypeParameters = append(newTypeParameters, newTypeParameter);
result.push(newTypeParameter);
}
else {
result.push(tp);
}
}
if (newTypeParameters) {
const mapper = createTypeMapper(oldTypeParameters!, newTypeParameters);
for (const tp of newTypeParameters) {
tp.mapper = mapper;
}
}
return result;
}
function hasTypeParameterByName(typeParameters: ReadonlyArray<TypeParameter> | undefined, name: __String) {
return some(typeParameters, tp => tp.symbol.escapedName === name);
}
function getUniqueTypeParameterName(typeParameters: ReadonlyArray<TypeParameter>, baseName: __String) {
let len = (<string>baseName).length;
while (len > 1 && (<string>baseName).charCodeAt(len - 1) >= CharacterCodes._0 && (<string>baseName).charCodeAt(len - 1) <= CharacterCodes._9) len--;
const s = (<string>baseName).slice(0, len);
for (let index = 1; true; index++) {
const augmentedName = <__String>(s + index);
if (!hasTypeParameterByName(typeParameters, augmentedName)) {
return augmentedName;
}
}
}
/**
* Returns the type of an expression. Unlike checkExpression, this function is simply concerned
* with computing the type and may not fully check all contained sub-expressions for errors.
@@ -23496,7 +23631,7 @@ namespace ts {
}
/* falls through */
case SyntaxKind.NewExpression:
return checkCallExpression(<CallExpression>node);
return checkCallExpression(<CallExpression>node, checkMode);
case SyntaxKind.TaggedTemplateExpression:
return checkTaggedTemplateExpression(<TaggedTemplateExpression>node);
case SyntaxKind.ParenthesizedExpression:
+16 -1
View File
@@ -917,7 +917,7 @@ namespace ts {
/**
* Deduplicates an unsorted array.
* @param equalityComparer An optional `EqualityComparer` used to determine if two values are duplicates.
* @param equalityComparer An `EqualityComparer` used to determine if two values are duplicates.
* @param comparer An optional `Comparer` used to sort entries before comparison, though the
* result will remain in the original order in `array`.
*/
@@ -1173,6 +1173,21 @@ namespace ts {
}};
}
export function arrayReverseIterator<T>(array: ReadonlyArray<T>): Iterator<T> {
let i = array.length;
return {
next: () => {
if (i === 0) {
return { value: undefined as never, done: true };
}
else {
i--;
return { value: array[i], done: false };
}
}
};
}
/**
* Stable sort of an array. Elements equal to each other maintain their relative position in the array.
*/
+8
View File
@@ -2927,6 +2927,10 @@
"category": "Error",
"code": 4102
},
"Type parameter '{0}' of exported mapped object type is using private name '{1}'.": {
"category": "Error",
"code": 4103
},
"The current host does not support the '{0}' option.": {
"category": "Error",
@@ -4910,5 +4914,9 @@
"Enable the 'experimentalDecorators' option in your configuration file": {
"category": "Message",
"code": 95074
},
"Convert to named parameters": {
"category": "Message",
"code": 95075
}
}
+3 -3
View File
@@ -71,8 +71,8 @@ namespace ts {
nonRecursive?: boolean;
}
export function isPathInNodeModulesStartingWithDot(path: Path) {
return stringContains(path, "/node_modules/.");
export function isPathIgnored(path: Path) {
return some(ignoredPaths, searchPath => stringContains(path, searchPath));
}
export const maxNumberOfFilesToIterateForInvalidation = 256;
@@ -696,7 +696,7 @@ namespace ts {
}
else {
// If something to do with folder/file starting with "." in node_modules folder, skip it
if (isPathInNodeModulesStartingWithDot(fileOrDirectoryPath)) return false;
if (isPathIgnored(fileOrDirectoryPath)) return false;
// Some file or directory in the watching directory is created
// Return early if it does not have any of the watching extension or not the custom failed lookup path
+16 -1
View File
@@ -326,6 +326,9 @@ namespace ts {
: FileWatcherEventKind.Changed;
}
/*@internal*/
export const ignoredPaths = ["/node_modules/.", "/.git"];
/*@internal*/
export interface RecursiveDirectoryWatcherHost {
watchDirectory: HostWatchDirectory;
@@ -371,6 +374,8 @@ namespace ts {
else {
directoryWatcher = {
watcher: host.watchDirectory(dirName, fileName => {
if (isIgnoredPath(fileName)) return;
// Call the actual callback
callbackCache.forEach((callbacks, rootDirName) => {
if (rootDirName === dirPath || (startsWith(dirPath, rootDirName) && dirPath[rootDirName.length] === directorySeparator)) {
@@ -426,7 +431,7 @@ namespace ts {
const childFullName = getNormalizedAbsolutePath(child, parentDir);
// Filter our the symbolic link directories since those arent included in recursive watch
// which is same behaviour when recursive: true is passed to fs.watch
return filePathComparer(childFullName, normalizePath(host.realpath(childFullName))) === Comparison.EqualTo ? childFullName : undefined;
return !isIgnoredPath(childFullName) && filePathComparer(childFullName, normalizePath(host.realpath(childFullName))) === Comparison.EqualTo ? childFullName : undefined;
}) : emptyArray,
existingChildWatches,
(child, childWatcher) => filePathComparer(child, childWatcher.dirName),
@@ -452,6 +457,16 @@ namespace ts {
(newChildWatches || (newChildWatches = [])).push(childWatcher);
}
}
function isIgnoredPath(path: string) {
return some(ignoredPaths, searchPath => isInPath(path, searchPath));
}
function isInPath(path: string, searchPath: string) {
if (stringContains(path, searchPath)) return true;
if (host.useCaseSensitiveFileNames) return false;
return stringContains(toCanonicalFilePath(path), searchPath);
}
}
/*@internal*/
@@ -391,6 +391,10 @@ namespace ts {
diagnosticMessage = Diagnostics.Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1;
break;
case SyntaxKind.MappedType:
diagnosticMessage = Diagnostics.Type_parameter_0_of_exported_mapped_object_type_is_using_private_name_1;
break;
case SyntaxKind.ConstructorType:
case SyntaxKind.ConstructSignature:
diagnosticMessage = Diagnostics.Type_parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1;
+2
View File
@@ -4423,6 +4423,7 @@ namespace ts {
NoDefault = 1 << 0, // Infer unknownType for no inferences (otherwise anyType or emptyObjectType)
AnyDefault = 1 << 1, // Infer anyType for no inferences (otherwise emptyObjectType)
NoFixing = 1 << 2, // Disable type parameter fixing
SkippedGenericFunction = 1 << 3,
}
/**
@@ -4452,6 +4453,7 @@ namespace ts {
flags: InferenceFlags; // Inference flags
compareTypes: TypeComparer; // Type comparer function
returnMapper?: TypeMapper; // Type mapper for inferences from return types (if any)
inferredTypeParameters?: ReadonlyArray<TypeParameter>;
}
/* @internal */
+1 -1
View File
@@ -987,7 +987,7 @@ namespace ts {
}
nextSourceFileVersion(fileOrDirectoryPath);
if (isPathInNodeModulesStartingWithDot(fileOrDirectoryPath)) return;
if (isPathIgnored(fileOrDirectoryPath)) return;
// If the the added or created file or directory is not supported file name, ignore the file
// But when watched directory is added/removed, we need to reload the file list
+9 -372
View File
@@ -47,23 +47,6 @@ interface XMLHttpRequest {
/* tslint:enable:no-var-keyword prefer-const */
namespace Utils {
// Setup some globals based on the current environment
export const enum ExecutionEnvironment {
Node,
Browser,
}
export function getExecutionEnvironment() {
if (typeof window !== "undefined") {
return ExecutionEnvironment.Browser;
}
else {
return ExecutionEnvironment.Node;
}
}
export let currentExecutionEnvironment = getExecutionEnvironment();
export function encodeString(s: string): string {
return ts.sys.bufferFrom!(s).toString("utf8");
}
@@ -74,23 +57,12 @@ namespace Utils {
}
export function evalFile(fileContents: string, fileName: string, nodeContext?: any) {
const environment = getExecutionEnvironment();
switch (environment) {
case ExecutionEnvironment.Browser:
// tslint:disable-next-line:no-eval
eval(fileContents);
break;
case ExecutionEnvironment.Node:
const vm = require("vm");
if (nodeContext) {
vm.runInNewContext(fileContents, nodeContext, fileName);
}
else {
vm.runInThisContext(fileContents, fileName);
}
break;
default:
throw new Error("Unknown context");
const vm = require("vm");
if (nodeContext) {
vm.runInNewContext(fileContents, nodeContext, fileName);
}
else {
vm.runInThisContext(fileContents, fileName);
}
}
@@ -624,344 +596,11 @@ namespace Harness {
};
}
interface URL {
hash: string;
host: string;
hostname: string;
href: string;
password: string;
pathname: string;
port: string;
protocol: string;
search: string;
username: string;
toString(): string;
}
declare var URL: {
prototype: URL;
new(url: string, base?: string | URL): URL;
};
function createBrowserIO(): IO {
const serverRoot = new URL("http://localhost:8888/");
class HttpHeaders extends collections.SortedMap<string, string | string[]> {
constructor(template?: Record<string, string | string[]>) {
super(ts.compareStringsCaseInsensitive);
if (template) {
for (const key in template) {
if (ts.hasProperty(template, key)) {
this.set(key, template[key]);
}
}
}
}
public static combine(left: HttpHeaders | undefined, right: HttpHeaders | undefined): HttpHeaders | undefined {
if (!left && !right) return undefined;
const headers = new HttpHeaders();
if (left) left.forEach((value, key) => { headers.set(key, value); });
if (right) right.forEach((value, key) => { headers.set(key, value); });
return headers;
}
public has(key: string) {
return super.has(key.toLowerCase());
}
public get(key: string) {
return super.get(key.toLowerCase());
}
public set(key: string, value: string | string[]) {
return super.set(key.toLowerCase(), value);
}
public delete(key: string) {
return super.delete(key.toLowerCase());
}
public writeRequestHeaders(xhr: XMLHttpRequest) {
this.forEach((values, key) => {
if (key === "access-control-allow-origin" || key === "content-length") return;
const value = Array.isArray(values) ? values.join(",") : values;
if (key === "content-type") {
xhr.overrideMimeType(value);
return;
}
xhr.setRequestHeader(key, value);
});
}
public static readResponseHeaders(xhr: XMLHttpRequest): HttpHeaders {
const allHeaders = xhr.getAllResponseHeaders();
const headers = new HttpHeaders();
for (const header of allHeaders.split(/\r\n/g)) {
const colonIndex = header.indexOf(":");
if (colonIndex >= 0) {
const key = header.slice(0, colonIndex).trim();
const value = header.slice(colonIndex + 1).trim();
const values = value.split(",");
headers.set(key, values.length > 1 ? values : value);
}
}
return headers;
}
}
class HttpContent {
public headers: HttpHeaders;
public content: string;
constructor(headers: HttpHeaders | Record<string, string | string[]>, content: string) {
this.headers = headers instanceof HttpHeaders ? headers : new HttpHeaders(headers);
this.content = content;
}
public static fromMediaType(mediaType: string, content: string) {
return new HttpContent({ "Content-Type": mediaType }, content);
}
public static text(content: string) {
return HttpContent.fromMediaType("text/plain", content);
}
public static json(content: object) {
return HttpContent.fromMediaType("application/json", JSON.stringify(content));
}
public static readResponseContent(xhr: XMLHttpRequest) {
if (typeof xhr.responseText === "string") {
return new HttpContent({
"Content-Type": xhr.getResponseHeader("Content-Type") || undefined!, // TODO: GH#18217
"Content-Length": xhr.getResponseHeader("Content-Length") || undefined!, // TODO: GH#18217
}, xhr.responseText);
}
return undefined;
}
public writeRequestHeaders(xhr: XMLHttpRequest) {
this.headers.writeRequestHeaders(xhr);
}
}
class HttpRequestMessage {
public method: string;
public url: URL;
public headers: HttpHeaders;
public content?: HttpContent;
constructor(method: string, url: string | URL, headers?: HttpHeaders | Record<string, string | string[]>, content?: HttpContent) {
this.method = method;
this.url = typeof url === "string" ? new URL(url) : url;
this.headers = headers instanceof HttpHeaders ? headers : new HttpHeaders(headers);
this.content = content;
}
public static options(url: string | URL) {
return new HttpRequestMessage("OPTIONS", url);
}
public static head(url: string | URL) {
return new HttpRequestMessage("HEAD", url);
}
public static get(url: string | URL) {
return new HttpRequestMessage("GET", url);
}
public static delete(url: string | URL) {
return new HttpRequestMessage("DELETE", url);
}
public static put(url: string | URL, content: HttpContent) {
return new HttpRequestMessage("PUT", url, /*headers*/ undefined, content);
}
public static post(url: string | URL, content: HttpContent) {
return new HttpRequestMessage("POST", url, /*headers*/ undefined, content);
}
public writeRequestHeaders(xhr: XMLHttpRequest) {
this.headers.writeRequestHeaders(xhr);
if (this.content) {
this.content.writeRequestHeaders(xhr);
}
}
}
class HttpResponseMessage {
public statusCode: number;
public statusMessage: string;
public headers: HttpHeaders;
public content?: HttpContent;
constructor(statusCode: number, statusMessage: string, headers?: HttpHeaders | Record<string, string | string[]>, content?: HttpContent) {
this.statusCode = statusCode;
this.statusMessage = statusMessage;
this.headers = headers instanceof HttpHeaders ? headers : new HttpHeaders(headers);
this.content = content;
}
public static notFound(): HttpResponseMessage {
return new HttpResponseMessage(404, "Not Found");
}
public static hasSuccessStatusCode(response: HttpResponseMessage) {
return response.statusCode === 304 || (response.statusCode >= 200 && response.statusCode < 300);
}
public static readResponseMessage(xhr: XMLHttpRequest) {
return new HttpResponseMessage(
xhr.status,
xhr.statusText,
HttpHeaders.readResponseHeaders(xhr),
HttpContent.readResponseContent(xhr));
}
}
function send(request: HttpRequestMessage): HttpResponseMessage {
const xhr = new XMLHttpRequest();
try {
xhr.open(request.method, request.url.toString(), /*async*/ false);
request.writeRequestHeaders(xhr);
xhr.setRequestHeader("Access-Control-Allow-Origin", "*");
xhr.send(request.content && request.content.content);
while (xhr.readyState !== 4); // block until ready
return HttpResponseMessage.readResponseMessage(xhr);
}
catch (e) {
return HttpResponseMessage.notFound();
}
}
let caseSensitivity: "CI" | "CS" | undefined;
function useCaseSensitiveFileNames() {
if (!caseSensitivity) {
const response = send(HttpRequestMessage.options(new URL("*", serverRoot)));
const xCaseSensitivity = response.headers.get("X-Case-Sensitivity");
caseSensitivity = xCaseSensitivity === "CS" ? "CS" : "CI";
}
return caseSensitivity === "CS";
}
function resolvePath(path: string) {
const response = send(HttpRequestMessage.post(new URL("/api/resolve", serverRoot), HttpContent.text(path)));
return HttpResponseMessage.hasSuccessStatusCode(response) && response.content ? response.content.content : undefined;
}
function getFileSize(path: string): number {
const response = send(HttpRequestMessage.head(new URL(path, serverRoot)));
return HttpResponseMessage.hasSuccessStatusCode(response) ? +response.headers.get("Content-Length")!.toString() : 0;
}
function readFile(path: string): string | undefined {
const response = send(HttpRequestMessage.get(new URL(path, serverRoot)));
return HttpResponseMessage.hasSuccessStatusCode(response) && response.content ? response.content.content : undefined;
}
function writeFile(path: string, contents: string) {
send(HttpRequestMessage.put(new URL(path, serverRoot), HttpContent.text(contents)));
}
function fileExists(path: string): boolean {
const response = send(HttpRequestMessage.head(new URL(path, serverRoot)));
return HttpResponseMessage.hasSuccessStatusCode(response);
}
function directoryExists(path: string): boolean {
const response = send(HttpRequestMessage.post(new URL("/api/directoryExists", serverRoot), HttpContent.text(path)));
return hasJsonContent(response) && JSON.parse(response.content.content) as boolean;
}
function deleteFile(path: string) {
send(HttpRequestMessage.delete(new URL(path, serverRoot)));
}
function directoryName(path: string) {
const url = new URL(path, serverRoot);
return ts.getDirectoryPath(ts.normalizeSlashes(url.pathname || "/"));
}
function enumerateTestFiles(runner: RunnerBase): (string | FileBasedTest)[] {
const response = send(HttpRequestMessage.post(new URL("/api/enumerateTestFiles", serverRoot), HttpContent.text(runner.kind())));
return hasJsonContent(response) ? JSON.parse(response.content.content) : [];
}
function listFiles(dirname: string, spec?: RegExp, options?: { recursive?: boolean }): string[] {
if (spec || (options && !options.recursive)) {
let results = IO.listFiles(dirname);
if (spec) {
results = results.filter(file => spec.test(file));
}
if (options && !options.recursive) {
results = results.filter(file => ts.getDirectoryPath(ts.normalizeSlashes(file)) === dirname);
}
return results;
}
const response = send(HttpRequestMessage.post(new URL("/api/listFiles", serverRoot), HttpContent.text(dirname)));
return hasJsonContent(response) ? JSON.parse(response.content.content) : [];
}
function readDirectory(path: string, extension?: string[], exclude?: string[], include?: string[], depth?: number) {
return ts.matchFiles(path, extension, exclude, include, useCaseSensitiveFileNames(), "", depth, getAccessibleFileSystemEntries);
}
function getAccessibleFileSystemEntries(dirname: string): ts.FileSystemEntries {
const response = send(HttpRequestMessage.post(new URL("/api/getAccessibleFileSystemEntries", serverRoot), HttpContent.text(dirname)));
return hasJsonContent(response) ? JSON.parse(response.content.content) : { files: [], directories: [] };
}
function hasJsonContent(response: HttpResponseMessage): response is HttpResponseMessage & { content: HttpContent } {
return HttpResponseMessage.hasSuccessStatusCode(response)
&& !!response.content
&& /^application\/json(;.*)$/.test("" + response.content.headers.get("Content-Type"));
}
return {
newLine: () => harnessNewLine,
getCurrentDirectory: () => "",
useCaseSensitiveFileNames,
resolvePath,
getFileSize,
readFile,
writeFile,
directoryName: Utils.memoize(directoryName, path => path),
getDirectories: () => [],
createDirectory: () => {}, // tslint:disable-line no-empty
fileExists,
directoryExists,
deleteFile,
listFiles: Utils.memoize(listFiles, (path, spec, options) => `${path}|${spec}|${options ? options.recursive === true : true}`),
enumerateTestFiles: Utils.memoize(enumerateTestFiles, runner => runner.kind()),
log: s => console.log(s),
args: () => [],
getExecutingFilePath: () => "",
exit: () => {}, // tslint:disable-line no-empty
readDirectory,
getAccessibleFileSystemEntries,
getWorkspaceRoot: () => "/"
};
}
export function mockHash(s: string): string {
return `hash-${s}`;
}
const environment = Utils.getExecutionEnvironment();
switch (environment) {
case Utils.ExecutionEnvironment.Node:
IO = createNodeIO();
break;
case Utils.ExecutionEnvironment.Browser:
IO = createBrowserIO();
break;
default:
throw new Error(`Unknown value '${environment}' for ExecutionEnvironment.`);
}
IO = createNodeIO();
}
if (Harness.IO.tryEnableSourceMapsForHost && /^development$/i.test(Harness.IO.getEnvironmentVariable!("NODE_ENV"))) {
@@ -970,10 +609,8 @@ if (Harness.IO.tryEnableSourceMapsForHost && /^development$/i.test(Harness.IO.ge
namespace Harness {
export const libFolder = "built/local/";
const tcServicesFileName = ts.combinePaths(libFolder, Utils.getExecutionEnvironment() === Utils.ExecutionEnvironment.Browser ? "typescriptServicesInBrowserTest.js" : "typescriptServices.js");
export const tcServicesFile = IO.readFile(tcServicesFileName) + (Utils.getExecutionEnvironment() !== Utils.ExecutionEnvironment.Browser
? IO.newLine() + `//# sourceURL=${IO.resolvePath(tcServicesFileName)}`
: "");
const tcServicesFileName = ts.combinePaths(libFolder, "typescriptServices.js");
export const tcServicesFile = IO.readFile(tcServicesFileName) + IO.newLine() + `//# sourceURL=${IO.resolvePath(tcServicesFileName)}`;
export type SourceMapEmitterCallback = (
emittedFile: string,
+103 -35
View File
@@ -408,6 +408,21 @@ namespace ts.server {
}
}
/*@internal*/
export interface OpenFileArguments {
fileName: string;
content?: string;
scriptKind?: protocol.ScriptKindName | ScriptKind;
hasMixedContent?: boolean;
projectRootPath?: string;
}
/*@internal*/
export interface ChangeFileArguments {
fileName: string;
changes: Iterator<TextChange>;
}
export class ProjectService {
/*@internal*/
@@ -988,7 +1003,7 @@ namespace ts.server {
fileOrDirectory => {
const fileOrDirectoryPath = this.toPath(fileOrDirectory);
project.getCachedDirectoryStructureHost().addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath);
if (isPathInNodeModulesStartingWithDot(fileOrDirectoryPath)) return;
if (isPathIgnored(fileOrDirectoryPath)) return;
const configFilename = project.getConfigFilePath();
// If the the added or created file or directory is not supported file name, ignore the file
@@ -1129,11 +1144,22 @@ namespace ts.server {
return project;
}
private assignOrphanScriptInfosToInferredProject() {
// collect orphaned files and assign them to inferred project just like we treat open of a file
this.openFiles.forEach((projectRootPath, path) => {
const info = this.getScriptInfoForPath(path as Path)!;
// collect all orphaned script infos from open files
if (info.isOrphan()) {
this.assignOrphanScriptInfoToInferredProject(info, projectRootPath);
}
});
}
/**
* Remove this file from the set of open, non-configured files.
* @param info The file that has been closed or newly configured
*/
private closeOpenFile(info: ScriptInfo): void {
private closeOpenFile(info: ScriptInfo, skipAssignOrphanScriptInfosToInferredProject?: true) {
// Closing file should trigger re-reading the file content from disk. This is
// because the user may chose to discard the buffer content before saving
// to the disk, and the server's version of the file can be out of sync.
@@ -1177,15 +1203,8 @@ namespace ts.server {
this.openFiles.delete(info.path);
if (ensureProjectsForOpenFiles) {
// collect orphaned files and assign them to inferred project just like we treat open of a file
this.openFiles.forEach((projectRootPath, path) => {
const info = this.getScriptInfoForPath(path as Path)!;
// collect all orphaned script infos from open files
if (info.isOrphan()) {
this.assignOrphanScriptInfoToInferredProject(info, projectRootPath);
}
});
if (!skipAssignOrphanScriptInfosToInferredProject && ensureProjectsForOpenFiles) {
this.assignOrphanScriptInfosToInferredProject();
}
// Cleanup script infos that arent part of any project (eg. those could be closed script infos not referenced by any project)
@@ -1200,6 +1219,8 @@ namespace ts.server {
else {
this.handleDeletedFile(info);
}
return ensureProjectsForOpenFiles;
}
private deleteScriptInfo(info: ScriptInfo) {
@@ -2051,7 +2072,7 @@ namespace ts.server {
watchDir,
(fileOrDirectory) => {
const fileOrDirectoryPath = this.toPath(fileOrDirectory);
if (isPathInNodeModulesStartingWithDot(fileOrDirectoryPath)) return;
if (isPathIgnored(fileOrDirectoryPath)) return;
// Has extension
Debug.assert(result.refCount > 0);
@@ -2571,20 +2592,22 @@ namespace ts.server {
});
}
openClientFileWithNormalizedPath(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, projectRootPath?: NormalizedPath): OpenConfiguredProjectResult {
private getOrCreateOpenScriptInfo(fileName: NormalizedPath, fileContent: string | undefined, scriptKind: ScriptKind | undefined, hasMixedContent: boolean | undefined, projectRootPath: NormalizedPath | undefined) {
const info = this.getOrCreateScriptInfoOpenedByClientForNormalizedPath(fileName, projectRootPath ? this.getNormalizedAbsolutePath(projectRootPath) : this.currentDirectory, fileContent, scriptKind, hasMixedContent)!; // TODO: GH#18217
this.openFiles.set(info.path, projectRootPath);
return info;
}
private assignProjectToOpenedScriptInfo(info: ScriptInfo): OpenConfiguredProjectResult {
let configFileName: NormalizedPath | undefined;
let configFileErrors: ReadonlyArray<Diagnostic> | undefined;
const info = this.getOrCreateScriptInfoOpenedByClientForNormalizedPath(fileName, projectRootPath ? this.getNormalizedAbsolutePath(projectRootPath) : this.currentDirectory, fileContent, scriptKind, hasMixedContent)!; // TODO: GH#18217
this.openFiles.set(info.path, projectRootPath);
let project: ConfiguredProject | ExternalProject | undefined = this.findExternalProjectContainingOpenScriptInfo(info);
if (!project && !this.syntaxOnly) { // Checking syntaxOnly is an optimization
configFileName = this.getConfigFileNameForFile(info);
if (configFileName) {
project = this.findConfiguredProjectByProjectName(configFileName);
if (!project) {
project = this.createLoadAndUpdateConfiguredProject(configFileName, `Creating possible configured project for ${fileName} to open`);
project = this.createLoadAndUpdateConfiguredProject(configFileName, `Creating possible configured project for ${info.fileName} to open`);
// Send the event only if the project got created as part of this open request and info is part of the project
if (info.isOrphan()) {
// Since the file isnt part of configured project, do not send config file info
@@ -2592,7 +2615,7 @@ namespace ts.server {
}
else {
configFileErrors = project.getAllProjectErrors();
this.sendConfigFileDiagEvent(project, fileName);
this.sendConfigFileDiagEvent(project, info.fileName);
}
}
else {
@@ -2614,10 +2637,14 @@ namespace ts.server {
// At this point if file is part of any any configured or external project, then it would be present in the containing projects
// So if it still doesnt have any containing projects, it needs to be part of inferred project
if (info.isOrphan()) {
this.assignOrphanScriptInfoToInferredProject(info, projectRootPath);
Debug.assert(this.openFiles.has(info.path));
this.assignOrphanScriptInfoToInferredProject(info, this.openFiles.get(info.path));
}
Debug.assert(!info.isOrphan());
return { configFileName, configFileErrors };
}
private cleanupAfterOpeningFile() {
// This was postponed from closeOpenFile to after opening next file,
// so that we can reuse the project if we need to right away
this.removeOrphanConfiguredProjects();
@@ -2637,9 +2664,14 @@ namespace ts.server {
this.removeOrphanScriptInfos();
this.printProjects();
}
openClientFileWithNormalizedPath(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, projectRootPath?: NormalizedPath): OpenConfiguredProjectResult {
const info = this.getOrCreateOpenScriptInfo(fileName, fileContent, scriptKind, hasMixedContent, projectRootPath);
const result = this.assignProjectToOpenedScriptInfo(info);
this.cleanupAfterOpeningFile();
this.telemetryOnOpenFile(info);
return { configFileName, configFileErrors };
return result;
}
private removeOrphanConfiguredProjects() {
@@ -2746,12 +2778,16 @@ namespace ts.server {
* Close file whose contents is managed by the client
* @param filename is absolute pathname
*/
closeClientFile(uncheckedFileName: string) {
closeClientFile(uncheckedFileName: string): void;
/*@internal*/
closeClientFile(uncheckedFileName: string, skipAssignOrphanScriptInfosToInferredProject: true): boolean;
closeClientFile(uncheckedFileName: string, skipAssignOrphanScriptInfosToInferredProject?: true) {
const info = this.getScriptInfoForNormalizedPath(toNormalizedPath(uncheckedFileName));
if (info) {
this.closeOpenFile(info);
const result = info ? this.closeOpenFile(info, skipAssignOrphanScriptInfosToInferredProject) : false;
if (!skipAssignOrphanScriptInfosToInferredProject) {
this.printProjects();
}
this.printProjects();
return result;
}
private collectChanges(lastKnownProjectVersions: protocol.ProjectVersionInfo[], currentProjects: Project[], result: ProjectFilesWithTSDiagnostics[]): void {
@@ -2771,36 +2807,68 @@ namespace ts.server {
}
/* @internal */
applyChangesInOpenFiles(openFiles: protocol.ExternalFile[] | undefined, changedFiles: protocol.ChangedOpenFile[] | undefined, closedFiles: string[] | undefined): void {
applyChangesInOpenFiles(openFiles: Iterator<OpenFileArguments> | undefined, changedFiles?: Iterator<ChangeFileArguments>, closedFiles?: string[]): void {
let openScriptInfos: ScriptInfo[] | undefined;
let assignOrphanScriptInfosToInferredProject = false;
if (openFiles) {
for (const file of openFiles) {
while (true) {
const { value: file, done } = openFiles.next();
if (done) break;
const scriptInfo = this.getScriptInfo(file.fileName);
Debug.assert(!scriptInfo || !scriptInfo.isScriptOpen(), "Script should not exist and not be open already");
const normalizedPath = scriptInfo ? scriptInfo.fileName : toNormalizedPath(file.fileName);
this.openClientFileWithNormalizedPath(normalizedPath, file.content, tryConvertScriptKindName(file.scriptKind!), file.hasMixedContent); // TODO: GH#18217
// Create script infos so we have the new content for all the open files before we do any updates to projects
const info = this.getOrCreateOpenScriptInfo(
scriptInfo ? scriptInfo.fileName : toNormalizedPath(file.fileName),
file.content,
tryConvertScriptKindName(file.scriptKind!),
file.hasMixedContent,
file.projectRootPath ? toNormalizedPath(file.projectRootPath) : undefined
);
(openScriptInfos || (openScriptInfos = [])).push(info);
}
}
if (changedFiles) {
for (const file of changedFiles) {
while (true) {
const { value: file, done } = changedFiles.next();
if (done) break;
const scriptInfo = this.getScriptInfo(file.fileName)!;
Debug.assert(!!scriptInfo);
// Make edits to script infos and marks containing project as dirty
this.applyChangesToFile(scriptInfo, file.changes);
}
}
if (closedFiles) {
for (const file of closedFiles) {
this.closeClientFile(file);
// Close files, but dont assign projects to orphan open script infos, that part comes later
assignOrphanScriptInfosToInferredProject = this.closeClientFile(file, /*skipAssignOrphanScriptInfosToInferredProject*/ true) || assignOrphanScriptInfosToInferredProject;
}
}
// All the script infos now exist, so ok to go update projects for open files
if (openScriptInfos) {
openScriptInfos.forEach(info => this.assignProjectToOpenedScriptInfo(info));
}
// While closing files there could be open files that needed assigning new inferred projects, do it now
if (assignOrphanScriptInfosToInferredProject) {
this.assignOrphanScriptInfosToInferredProject();
}
// Cleanup projects
this.cleanupAfterOpeningFile();
// Telemetry
forEach(openScriptInfos, info => this.telemetryOnOpenFile(info));
this.printProjects();
}
/* @internal */
applyChangesToFile(scriptInfo: ScriptInfo, changes: TextChange[]) {
// apply changes in reverse order
for (let i = changes.length - 1; i >= 0; i--) {
const change = changes[i];
applyChangesToFile(scriptInfo: ScriptInfo, changes: Iterator<TextChange>) {
while (true) {
const { value: change, done } = changes.next();
if (done) break;
scriptInfo.editContent(change.span.start, change.span.start + change.span.length, change.newText);
}
}
+27
View File
@@ -92,6 +92,7 @@ namespace ts.server.protocol {
SynchronizeProjectList = "synchronizeProjectList",
/* @internal */
ApplyChangedToOpenFiles = "applyChangedToOpenFiles",
UpdateOpen = "updateOpen",
/* @internal */
EncodedSemanticClassificationsFull = "encodedSemanticClassifications-full",
/* @internal */
@@ -1543,6 +1544,32 @@ namespace ts.server.protocol {
closedFiles?: string[];
}
/**
* Request to synchronize list of open files with the client
*/
export interface UpdateOpenRequest extends Request {
command: CommandTypes.UpdateOpen;
arguments: UpdateOpenRequestArgs;
}
/**
* Arguments to UpdateOpenRequest
*/
export interface UpdateOpenRequestArgs {
/**
* List of newly open files
*/
openFiles?: OpenRequestArgs[];
/**
* List of open files files that were changes
*/
changedFiles?: FileCodeEdits[];
/**
* List of files that were closed
*/
closedFiles?: string[];
}
/**
* Request to set compiler options for inferred projects.
* External projects are opened / closed explicitly.
+33 -3
View File
@@ -1654,10 +1654,10 @@ namespace ts.server {
const end = scriptInfo.lineOffsetToPosition(args.endLine, args.endOffset);
if (start >= 0) {
this.changeSeq++;
this.projectService.applyChangesToFile(scriptInfo, [{
this.projectService.applyChangesToFile(scriptInfo, singleIterator({
span: { start, length: end - start },
newText: args.insertString! // TODO: GH#18217
}]);
}));
}
}
@@ -2096,9 +2096,39 @@ namespace ts.server {
});
return this.requiredResponse(converted);
},
[CommandNames.UpdateOpen]: (request: protocol.UpdateOpenRequest) => {
this.changeSeq++;
this.projectService.applyChangesInOpenFiles(
request.arguments.openFiles && mapIterator(arrayIterator(request.arguments.openFiles), file => ({
fileName: file.file,
content: file.fileContent,
scriptKind: file.scriptKindName,
projectRootPath: file.projectRootPath
})),
request.arguments.changedFiles && mapIterator(arrayIterator(request.arguments.changedFiles), file => ({
fileName: file.fileName,
changes: mapDefinedIterator(arrayReverseIterator(file.textChanges), change => {
const scriptInfo = Debug.assertDefined(this.projectService.getScriptInfo(file.fileName));
const start = scriptInfo.lineOffsetToPosition(change.start.line, change.start.offset);
const end = scriptInfo.lineOffsetToPosition(change.end.line, change.end.offset);
return start >= 0 ? { span: { start, length: end - start }, newText: change.newText } : undefined;
})
})),
request.arguments.closedFiles
);
return this.requiredResponse(/*response*/ true);
},
[CommandNames.ApplyChangedToOpenFiles]: (request: protocol.ApplyChangedToOpenFilesRequest) => {
this.changeSeq++;
this.projectService.applyChangesInOpenFiles(request.arguments.openFiles, request.arguments.changedFiles!, request.arguments.closedFiles!); // TODO: GH#18217
this.projectService.applyChangesInOpenFiles(
request.arguments.openFiles && arrayIterator(request.arguments.openFiles),
request.arguments.changedFiles && mapIterator(arrayIterator(request.arguments.changedFiles), file => ({
fileName: file.fileName,
// apply changes in reverse order
changes: arrayReverseIterator(file.changes)
})),
request.arguments.closedFiles
);
// TODO: report errors
return this.requiredResponse(/*response*/ true);
},
@@ -35,7 +35,7 @@ namespace ts.codefix {
precedingNode = ctorDeclaration.parent.parent;
newClassDeclaration = createClassFromVariableDeclaration(ctorDeclaration as VariableDeclaration);
if ((<VariableDeclarationList>ctorDeclaration.parent).declarations.length === 1) {
copyComments(precedingNode, newClassDeclaration!, sourceFile); // TODO: GH#18217
copyLeadingComments(precedingNode, newClassDeclaration!, sourceFile); // TODO: GH#18217
changes.delete(sourceFile, precedingNode);
}
else {
@@ -48,7 +48,7 @@ namespace ts.codefix {
return undefined;
}
copyComments(ctorDeclaration, newClassDeclaration, sourceFile);
copyLeadingComments(ctorDeclaration, newClassDeclaration, sourceFile);
// Because the preceding node could be touched, we need to insert nodes before delete nodes.
changes.insertNodeAfter(sourceFile, precedingNode!, newClassDeclaration);
@@ -112,7 +112,7 @@ namespace ts.codefix {
const fullModifiers = concatenate(modifiers, getModifierKindFromSource(functionExpression, SyntaxKind.AsyncKeyword));
const method = createMethod(/*decorators*/ undefined, fullModifiers, /*asteriskToken*/ undefined, memberDeclaration.name, /*questionToken*/ undefined,
/*typeParameters*/ undefined, functionExpression.parameters, /*type*/ undefined, functionExpression.body);
copyComments(assignmentBinaryExpression, method, sourceFile);
copyLeadingComments(assignmentBinaryExpression, method, sourceFile);
return method;
}
@@ -132,7 +132,7 @@ namespace ts.codefix {
const fullModifiers = concatenate(modifiers, getModifierKindFromSource(arrowFunction, SyntaxKind.AsyncKeyword));
const method = createMethod(/*decorators*/ undefined, fullModifiers, /*asteriskToken*/ undefined, memberDeclaration.name, /*questionToken*/ undefined,
/*typeParameters*/ undefined, arrowFunction.parameters, /*type*/ undefined, bodyBlock);
copyComments(assignmentBinaryExpression, method, sourceFile);
copyLeadingComments(assignmentBinaryExpression, method, sourceFile);
return method;
}
@@ -143,7 +143,7 @@ namespace ts.codefix {
}
const prop = createProperty(/*decorators*/ undefined, modifiers, memberDeclaration.name, /*questionToken*/ undefined,
/*type*/ undefined, assignmentBinaryExpression.right);
copyComments(assignmentBinaryExpression.parent, prop, sourceFile);
copyLeadingComments(assignmentBinaryExpression.parent, prop, sourceFile);
return prop;
}
}
-24
View File
@@ -304,30 +304,6 @@ namespace ts.codefix {
}
}
function getTypeNodeIfAccessible(type: Type, enclosingScope: Node, program: Program, host: LanguageServiceHost): TypeNode | undefined {
const checker = program.getTypeChecker();
let typeIsAccessible = true;
const notAccessible = () => { typeIsAccessible = false; };
const res = checker.typeToTypeNode(type, enclosingScope, /*flags*/ undefined, {
trackSymbol: (symbol, declaration, meaning) => {
// TODO: GH#18217
typeIsAccessible = typeIsAccessible && checker.isSymbolAccessible(symbol, declaration, meaning!, /*shouldComputeAliasToMarkVisible*/ false).accessibility === SymbolAccessibility.Accessible;
},
reportInaccessibleThisError: notAccessible,
reportPrivateInBaseOfClassExpression: notAccessible,
reportInaccessibleUniqueSymbolError: notAccessible,
moduleResolverHost: {
readFile: host.readFile,
fileExists: host.fileExists,
directoryExists: host.directoryExists,
getSourceFiles: program.getSourceFiles,
getCurrentDirectory: program.getCurrentDirectory,
getCommonSourceDirectory: program.getCommonSourceDirectory,
}
});
return typeIsAccessible ? res : undefined;
}
function getReferences(token: PropertyName | Token<SyntaxKind.ConstructorKeyword>, program: Program, cancellationToken: CancellationToken): ReadonlyArray<Identifier> {
// Position shouldn't matter since token is not a SourceFile.
return mapDefined(FindAllReferences.getReferenceEntriesForNode(-1, token, program, program.getSourceFiles(), cancellationToken), entry =>
+2 -2
View File
@@ -68,8 +68,8 @@ namespace ts.OrganizeImports {
else {
// Note: Delete the surrounding trivia because it will have been retained in newImportDecls.
changeTracker.replaceNodeWithNodes(sourceFile, oldImportDecls[0], newImportDecls, {
useNonAdjustedStartPosition: true, // Leave header comment in place
useNonAdjustedEndPosition: false,
leadingTriviaOption: textChanges.LeadingTriviaOption.Exclude, // Leave header comment in place
trailingTriviaOption: textChanges.TrailingTriviaOption.Include,
suffix: getNewLineOrDefaultFromHost(host, formatContext.options),
});
}
@@ -48,13 +48,13 @@ namespace ts.refactor.addOrRemoveBracesToArrowFunction {
const returnStatement = createReturn(expression);
body = createBlock([returnStatement], /* multiLine */ true);
suppressLeadingAndTrailingTrivia(body);
copyComments(expression!, returnStatement, file, SyntaxKind.MultiLineCommentTrivia, /* hasTrailingNewLine */ true);
copyLeadingComments(expression!, returnStatement, file, SyntaxKind.MultiLineCommentTrivia, /* hasTrailingNewLine */ true);
}
else if (actionName === removeBracesActionName && returnStatement) {
const actualExpression = expression || createVoidZero();
body = needsParentheses(actualExpression) ? createParen(actualExpression) : actualExpression;
suppressLeadingAndTrailingTrivia(body);
copyComments(returnStatement, body, file, SyntaxKind.MultiLineCommentTrivia, /* hasTrailingNewLine */ false);
copyLeadingComments(returnStatement, body, file, SyntaxKind.MultiLineCommentTrivia, /* hasTrailingNewLine */ false);
}
else {
Debug.fail("invalid action");
@@ -0,0 +1,520 @@
/* @internal */
namespace ts.refactor.convertToNamedParameters {
const refactorName = "Convert to named parameters";
const minimumParameterLength = 2;
registerRefactor(refactorName, { getEditsForAction, getAvailableActions });
function getAvailableActions(context: RefactorContext): ReadonlyArray<ApplicableRefactorInfo> {
const { file, startPosition } = context;
const isJSFile = isSourceFileJS(file);
if (isJSFile) return emptyArray; // TODO: GH#30113
const functionDeclaration = getFunctionDeclarationAtPosition(file, startPosition, context.program.getTypeChecker());
if (!functionDeclaration) return emptyArray;
const description = getLocaleSpecificMessage(Diagnostics.Convert_to_named_parameters);
return [{
name: refactorName,
description,
actions: [{
name: refactorName,
description
}]
}];
}
function getEditsForAction(context: RefactorContext, actionName: string): RefactorEditInfo | undefined {
Debug.assert(actionName === refactorName);
const { file, startPosition, program, cancellationToken, host } = context;
const functionDeclaration = getFunctionDeclarationAtPosition(file, startPosition, program.getTypeChecker());
if (!functionDeclaration || !cancellationToken) return undefined;
const groupedReferences = getGroupedReferences(functionDeclaration, program, cancellationToken);
if (groupedReferences.valid) {
const edits = textChanges.ChangeTracker.with(context, t => doChange(file, program, host, t, functionDeclaration, groupedReferences));
return { renameFilename: undefined, renameLocation: undefined, edits };
}
return { edits: [] }; // TODO: GH#30113
}
function doChange(
sourceFile: SourceFile,
program: Program,
host: LanguageServiceHost,
changes: textChanges.ChangeTracker,
functionDeclaration: ValidFunctionDeclaration,
groupedReferences: GroupedReferences): void {
const newParamDeclaration = map(createNewParameters(functionDeclaration, program, host), param => getSynthesizedDeepClone(param));
changes.replaceNodeRangeWithNodes(
sourceFile,
first(functionDeclaration.parameters),
last(functionDeclaration.parameters),
newParamDeclaration,
{ joiner: ", ",
// indentation is set to 0 because otherwise the object parameter will be indented if there is a `this` parameter
indentation: 0,
leadingTriviaOption: textChanges.LeadingTriviaOption.IncludeAll,
trailingTriviaOption: textChanges.TrailingTriviaOption.Include
});
const functionCalls = sortAndDeduplicate(groupedReferences.functionCalls, /*comparer*/ (a, b) => compareValues(a.pos, b.pos));
for (const call of functionCalls) {
if (call.arguments && call.arguments.length) {
const newArgument = getSynthesizedDeepClone(createNewArgument(functionDeclaration, call.arguments), /*includeTrivia*/ true);
changes.replaceNodeRange(
getSourceFileOfNode(call),
first(call.arguments),
last(call.arguments),
newArgument,
{ leadingTriviaOption: textChanges.LeadingTriviaOption.IncludeAll, trailingTriviaOption: textChanges.TrailingTriviaOption.Include });
}
}
}
function getGroupedReferences(functionDeclaration: ValidFunctionDeclaration, program: Program, cancellationToken: CancellationToken): GroupedReferences {
const functionNames = getFunctionNames(functionDeclaration);
const classNames = isConstructorDeclaration(functionDeclaration) ? getClassNames(functionDeclaration) : [];
const names = deduplicate([...functionNames, ...classNames], equateValues);
const checker = program.getTypeChecker();
const references = flatMap(names, /*mapfn*/ name => FindAllReferences.getReferenceEntriesForNode(-1, name, program, program.getSourceFiles(), cancellationToken));
const groupedReferences = groupReferences(references);
if (!every(groupedReferences.declarations, decl => contains(names, decl))) {
groupedReferences.valid = false;
}
return groupedReferences;
function groupReferences(referenceEntries: ReadonlyArray<FindAllReferences.Entry>): GroupedReferences {
const classReferences: ClassReferences = { accessExpressions: [], typeUsages: [] };
const groupedReferences: GroupedReferences = { functionCalls: [], declarations: [], classReferences, valid: true };
const functionSymbols = map(functionNames, checker.getSymbolAtLocation);
const classSymbols = map(classNames, checker.getSymbolAtLocation);
const isConstructor = isConstructorDeclaration(functionDeclaration);
for (const entry of referenceEntries) {
if (entry.kind !== FindAllReferences.EntryKind.Node) {
groupedReferences.valid = false;
continue;
}
if (contains(functionSymbols, checker.getSymbolAtLocation(entry.node), symbolComparer)) {
const decl = entryToDeclaration(entry);
if (decl) {
groupedReferences.declarations.push(decl);
continue;
}
const call = entryToFunctionCall(entry);
if (call) {
groupedReferences.functionCalls.push(call);
continue;
}
}
// if the refactored function is a constructor, we must also check if the references to its class are valid
if (isConstructor && contains(classSymbols, checker.getSymbolAtLocation(entry.node), symbolComparer)) {
const decl = entryToDeclaration(entry);
if (decl) {
groupedReferences.declarations.push(decl);
continue;
}
const accessExpression = entryToAccessExpression(entry);
if (accessExpression) {
classReferences.accessExpressions.push(accessExpression);
continue;
}
// Only class declarations are allowed to be used as a type (in a heritage clause),
// otherwise `findAllReferences` might not be able to track constructor calls.
if (isClassDeclaration(functionDeclaration.parent)) {
const type = entryToType(entry);
if (type) {
classReferences.typeUsages.push(type);
continue;
}
}
}
groupedReferences.valid = false;
}
return groupedReferences;
}
}
function symbolComparer(a: Symbol, b: Symbol): boolean {
return getSymbolTarget(a) === getSymbolTarget(b);
}
function entryToDeclaration(entry: FindAllReferences.NodeEntry): Node | undefined {
if (isDeclaration(entry.node.parent)) {
return entry.node;
}
return undefined;
}
function entryToFunctionCall(entry: FindAllReferences.NodeEntry): CallExpression | NewExpression | undefined {
if (entry.node.parent) {
const functionReference = entry.node;
const parent = functionReference.parent;
switch (parent.kind) {
// Function call (foo(...) or super(...))
case SyntaxKind.CallExpression:
const callExpression = tryCast(parent, isCallExpression);
if (callExpression && callExpression.expression === functionReference) {
return callExpression;
}
break;
// Constructor call (new Foo(...))
case SyntaxKind.NewExpression:
const newExpression = tryCast(parent, isNewExpression);
if (newExpression && newExpression.expression === functionReference) {
return newExpression;
}
break;
// Method call (x.foo(...))
case SyntaxKind.PropertyAccessExpression:
const propertyAccessExpression = tryCast(parent, isPropertyAccessExpression);
if (propertyAccessExpression && propertyAccessExpression.parent && propertyAccessExpression.name === functionReference) {
const callExpression = tryCast(propertyAccessExpression.parent, isCallExpression);
if (callExpression && callExpression.expression === propertyAccessExpression) {
return callExpression;
}
}
break;
// Method call (x["foo"](...))
case SyntaxKind.ElementAccessExpression:
const elementAccessExpression = tryCast(parent, isElementAccessExpression);
if (elementAccessExpression && elementAccessExpression.parent && elementAccessExpression.argumentExpression === functionReference) {
const callExpression = tryCast(elementAccessExpression.parent, isCallExpression);
if (callExpression && callExpression.expression === elementAccessExpression) {
return callExpression;
}
}
break;
}
}
return undefined;
}
function entryToAccessExpression(entry: FindAllReferences.NodeEntry): ElementAccessExpression | PropertyAccessExpression | undefined {
if (entry.node.parent) {
const reference = entry.node;
const parent = reference.parent;
switch (parent.kind) {
// `C.foo`
case SyntaxKind.PropertyAccessExpression:
const propertyAccessExpression = tryCast(parent, isPropertyAccessExpression);
if (propertyAccessExpression && propertyAccessExpression.expression === reference) {
return propertyAccessExpression;
}
break;
// `C["foo"]`
case SyntaxKind.ElementAccessExpression:
const elementAccessExpression = tryCast(parent, isElementAccessExpression);
if (elementAccessExpression && elementAccessExpression.expression === reference) {
return elementAccessExpression;
}
break;
}
}
return undefined;
}
function entryToType(entry: FindAllReferences.NodeEntry): Node | undefined {
const reference = entry.node;
if (getMeaningFromLocation(reference) === SemanticMeaning.Type || isExpressionWithTypeArgumentsInClassExtendsClause(reference.parent)) {
return reference;
}
return undefined;
}
function getFunctionDeclarationAtPosition(file: SourceFile, startPosition: number, checker: TypeChecker): ValidFunctionDeclaration | undefined {
const node = getTouchingToken(file, startPosition);
const functionDeclaration = getContainingFunction(node);
if (functionDeclaration
&& isValidFunctionDeclaration(functionDeclaration, checker)
&& rangeContainsRange(functionDeclaration, node)
&& !(functionDeclaration.body && rangeContainsRange(functionDeclaration.body, node))) return functionDeclaration;
return undefined;
}
function isValidFunctionDeclaration(functionDeclaration: SignatureDeclaration, checker: TypeChecker): functionDeclaration is ValidFunctionDeclaration {
if (!isValidParameterNodeArray(functionDeclaration.parameters)) return false;
switch (functionDeclaration.kind) {
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.MethodDeclaration:
return !!functionDeclaration.name && !!functionDeclaration.body && !checker.isImplementationOfOverload(functionDeclaration);
case SyntaxKind.Constructor:
if (isClassDeclaration(functionDeclaration.parent)) {
return !!functionDeclaration.body && !!functionDeclaration.parent.name && !checker.isImplementationOfOverload(functionDeclaration);
}
else {
return isValidVariableDeclaration(functionDeclaration.parent.parent) && !!functionDeclaration.body && !checker.isImplementationOfOverload(functionDeclaration);
}
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
return isValidVariableDeclaration(functionDeclaration.parent);
}
return false;
}
function isValidParameterNodeArray(parameters: NodeArray<ParameterDeclaration>): parameters is ValidParameterNodeArray {
return getRefactorableParametersLength(parameters) >= minimumParameterLength && every(parameters, isValidParameterDeclaration);
}
function isValidParameterDeclaration(paramDeclaration: ParameterDeclaration): paramDeclaration is ValidParameterDeclaration {
return !paramDeclaration.modifiers && !paramDeclaration.decorators && isIdentifier(paramDeclaration.name);
}
function isValidVariableDeclaration(node: Node): node is ValidVariableDeclaration {
return isVariableDeclaration(node) && isVarConst(node) && isIdentifier(node.name) && !node.type; // TODO: GH#30113
}
function hasThisParameter(parameters: NodeArray<ParameterDeclaration>): boolean {
return parameters.length > 0 && isThis(parameters[0].name);
}
function getRefactorableParametersLength(parameters: NodeArray<ParameterDeclaration>): number {
if (hasThisParameter(parameters)) {
return parameters.length - 1;
}
return parameters.length;
}
function getRefactorableParameters(parameters: NodeArray<ValidParameterDeclaration>): NodeArray<ValidParameterDeclaration> {
if (hasThisParameter(parameters)) {
parameters = createNodeArray(parameters.slice(1), parameters.hasTrailingComma);
}
return parameters;
}
function createNewArgument(functionDeclaration: ValidFunctionDeclaration, functionArguments: NodeArray<Expression>): ObjectLiteralExpression {
const parameters = getRefactorableParameters(functionDeclaration.parameters);
const hasRestParameter = isRestParameter(last(parameters));
const nonRestArguments = hasRestParameter ? functionArguments.slice(0, parameters.length - 1) : functionArguments;
const properties = map(nonRestArguments, (arg, i) => {
const property = createPropertyAssignment(getParameterName(parameters[i]), arg);
suppressLeadingAndTrailingTrivia(property.initializer);
copyComments(arg, property);
return property;
});
if (hasRestParameter && functionArguments.length >= parameters.length) {
const restArguments = functionArguments.slice(parameters.length - 1);
const restProperty = createPropertyAssignment(getParameterName(last(parameters)), createArrayLiteral(restArguments));
properties.push(restProperty);
}
const objectLiteral = createObjectLiteral(properties, /*multiLine*/ false);
return objectLiteral;
}
function createNewParameters(functionDeclaration: ValidFunctionDeclaration, program: Program, host: LanguageServiceHost): NodeArray<ParameterDeclaration> {
const refactorableParameters = getRefactorableParameters(functionDeclaration.parameters);
const bindingElements = map(refactorableParameters, createBindingElementFromParameterDeclaration);
const objectParameterName = createObjectBindingPattern(bindingElements);
const objectParameterType = createParameterTypeNode(refactorableParameters);
const checker = program.getTypeChecker();
let objectInitializer: Expression | undefined;
// If every parameter in the original function was optional, add an empty object initializer to the new object parameter
if (every(refactorableParameters, checker.isOptionalParameter)) {
objectInitializer = createObjectLiteral();
}
const objectParameter = createParameter(
/*decorators*/ undefined,
/*modifiers*/ undefined,
/*dotDotDotToken*/ undefined,
objectParameterName,
/*questionToken*/ undefined,
objectParameterType,
objectInitializer);
if (hasThisParameter(functionDeclaration.parameters)) {
const thisParameter = functionDeclaration.parameters[0];
const newThisParameter = createParameter(
/*decorators*/ undefined,
/*modifiers*/ undefined,
/*dotDotDotToken*/ undefined,
thisParameter.name,
/*questionToken*/ undefined,
thisParameter.type);
suppressLeadingAndTrailingTrivia(newThisParameter.name);
copyComments(thisParameter.name, newThisParameter.name);
if (thisParameter.type) {
suppressLeadingAndTrailingTrivia(newThisParameter.type!);
copyComments(thisParameter.type, newThisParameter.type!);
}
return createNodeArray([newThisParameter, objectParameter]);
}
return createNodeArray([objectParameter]);
function createParameterTypeNode(parameters: NodeArray<ValidParameterDeclaration>): TypeLiteralNode {
const members = map(parameters, createPropertySignatureFromParameterDeclaration);
const typeNode = addEmitFlags(createTypeLiteralNode(members), EmitFlags.SingleLine);
return typeNode;
}
function createPropertySignatureFromParameterDeclaration(parameterDeclaration: ValidParameterDeclaration): PropertySignature {
let parameterType = parameterDeclaration.type;
if (!parameterType && (parameterDeclaration.initializer || isRestParameter(parameterDeclaration))) {
parameterType = getTypeNode(parameterDeclaration);
}
const propertySignature = createPropertySignature(
/*modifiers*/ undefined,
getParameterName(parameterDeclaration),
parameterDeclaration.initializer || isRestParameter(parameterDeclaration) ? createToken(SyntaxKind.QuestionToken) : parameterDeclaration.questionToken,
parameterType,
/*initializer*/ undefined);
suppressLeadingAndTrailingTrivia(propertySignature);
copyComments(parameterDeclaration.name, propertySignature.name);
if (parameterDeclaration.type && propertySignature.type) {
copyComments(parameterDeclaration.type, propertySignature.type);
}
return propertySignature;
}
function getTypeNode(node: Node): TypeNode | undefined {
const checker = program.getTypeChecker();
const type = checker.getTypeAtLocation(node);
return getTypeNodeIfAccessible(type, node, program, host);
}
}
function createBindingElementFromParameterDeclaration(parameterDeclaration: ValidParameterDeclaration): BindingElement {
const element = createBindingElement(
/*dotDotDotToken*/ undefined,
/*propertyName*/ undefined,
getParameterName(parameterDeclaration),
isRestParameter(parameterDeclaration) ? createArrayLiteral() : parameterDeclaration.initializer);
suppressLeadingAndTrailingTrivia(element);
if (parameterDeclaration.initializer && element.initializer) {
copyComments(parameterDeclaration.initializer, element.initializer);
}
return element;
}
function copyComments(sourceNode: Node, targetNode: Node) {
const sourceFile = sourceNode.getSourceFile();
const text = sourceFile.text;
if (hasLeadingLineBreak(sourceNode, text)) {
copyLeadingComments(sourceNode, targetNode, sourceFile);
}
else {
copyTrailingAsLeadingComments(sourceNode, targetNode, sourceFile);
}
copyTrailingComments(sourceNode, targetNode, sourceFile);
}
function hasLeadingLineBreak(node: Node, text: string) {
const start = node.getFullStart();
const end = node.getStart();
for (let i = start; i < end; i++) {
if (text.charCodeAt(i) === CharacterCodes.lineFeed) return true;
}
return false;
}
function getParameterName(paramDeclaration: ValidParameterDeclaration) {
return getTextOfIdentifierOrLiteral(paramDeclaration.name);
}
function getClassNames(constructorDeclaration: ValidConstructor): Identifier[] {
switch (constructorDeclaration.parent.kind) {
case SyntaxKind.ClassDeclaration:
const classDeclaration = constructorDeclaration.parent;
return [classDeclaration.name];
case SyntaxKind.ClassExpression:
const classExpression = constructorDeclaration.parent;
const variableDeclaration = constructorDeclaration.parent.parent;
const className = classExpression.name;
if (className) return [className, variableDeclaration.name];
return [variableDeclaration.name];
}
}
function getFunctionNames(functionDeclaration: ValidFunctionDeclaration): Node[] {
switch (functionDeclaration.kind) {
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.MethodDeclaration:
return [functionDeclaration.name];
case SyntaxKind.Constructor:
const ctrKeyword = findChildOfKind(functionDeclaration, SyntaxKind.ConstructorKeyword, functionDeclaration.getSourceFile())!;
if (functionDeclaration.parent.kind === SyntaxKind.ClassExpression) {
const variableDeclaration = functionDeclaration.parent.parent;
return [variableDeclaration.name, ctrKeyword];
}
return [ctrKeyword];
case SyntaxKind.ArrowFunction:
return [functionDeclaration.parent.name];
case SyntaxKind.FunctionExpression:
if (functionDeclaration.name) return [functionDeclaration.name, functionDeclaration.parent.name];
return [functionDeclaration.parent.name];
default:
return Debug.assertNever(functionDeclaration);
}
}
type ValidParameterNodeArray = NodeArray<ValidParameterDeclaration>;
interface ValidVariableDeclaration extends VariableDeclaration {
name: Identifier;
type: undefined;
}
interface ValidConstructor extends ConstructorDeclaration {
parent: (ClassDeclaration & { name: Identifier }) | (ClassExpression & { parent: ValidVariableDeclaration });
parameters: NodeArray<ValidParameterDeclaration>;
body: FunctionBody;
}
interface ValidFunction extends FunctionDeclaration {
name: Identifier;
parameters: NodeArray<ValidParameterDeclaration>;
body: FunctionBody;
}
interface ValidMethod extends MethodDeclaration {
parameters: NodeArray<ValidParameterDeclaration>;
body: FunctionBody;
}
interface ValidFunctionExpression extends FunctionExpression {
parent: ValidVariableDeclaration;
parameters: NodeArray<ValidParameterDeclaration>;
}
interface ValidArrowFunction extends ArrowFunction {
parent: ValidVariableDeclaration;
parameters: NodeArray<ValidParameterDeclaration>;
}
type ValidFunctionDeclaration = ValidConstructor | ValidFunction | ValidMethod | ValidArrowFunction | ValidFunctionExpression;
interface ValidParameterDeclaration extends ParameterDeclaration {
name: Identifier;
modifiers: undefined;
decorators: undefined;
}
interface GroupedReferences {
functionCalls: (CallExpression | NewExpression)[];
declarations: Node[];
classReferences?: ClassReferences;
valid: boolean;
}
interface ClassReferences {
accessExpressions: Node[];
typeUsages: Node[];
}
}
+1 -1
View File
@@ -1798,7 +1798,7 @@ namespace ts {
const span = createTextSpanFromBounds(start, end);
const formatContext = formatting.getFormatContext(formatOptions);
return flatMap(deduplicate(errorCodes, equateValues, compareValues), errorCode => {
return flatMap(deduplicate<number>(errorCodes, equateValues, compareValues), errorCode => {
cancellationToken.throwIfCancellationRequested();
return codefix.getFixes({ errorCode, sourceFile, span, program, host, cancellationToken, formatContext, preferences });
});
+42 -29
View File
@@ -28,17 +28,27 @@ namespace ts.textChanges {
}
export interface ConfigurableStart {
/** True to use getStart() (NB, not getFullStart()) without adjustment. */
useNonAdjustedStartPosition?: boolean;
leadingTriviaOption?: LeadingTriviaOption;
}
export interface ConfigurableEnd {
/** True to use getEnd() without adjustment. */
useNonAdjustedEndPosition?: boolean;
trailingTriviaOption?: TrailingTriviaOption;
}
export enum Position {
FullStart,
Start
export enum LeadingTriviaOption {
/** Exclude all leading trivia (use getStart()) */
Exclude,
/** Include leading trivia and,
* if there are no line breaks between the node and the previous token,
* include all trivia between the node and the previous token
*/
IncludeAll,
}
export enum TrailingTriviaOption {
/** Exclude all trailing trivia (use getEnd()) */
Exclude,
/** Include trailing trivia */
Include,
}
function skipWhitespacesAndLineBreaks(text: string, start: number) {
@@ -68,13 +78,14 @@ namespace ts.textChanges {
* Usually leading trivia of the variable declaration 'y' should not include trailing trivia (whitespace, comment 'this is x' and newline) from the preceding
* variable declaration and trailing trivia for 'y' should include (whitespace, comment 'this is y', newline).
* By default when removing nodes we adjust start and end positions to respect specification of the trivia above.
* If pos\end should be interpreted literally 'useNonAdjustedStartPosition' or 'useNonAdjustedEndPosition' should be set to true
* If pos\end should be interpreted literally (that is, withouth including leading and trailing trivia), `leadingTriviaOption` should be set to `LeadingTriviaOption.Exclude`
* and `trailingTriviaOption` to `TrailingTriviaOption.Exclude`.
*/
export interface ConfigurableStartEnd extends ConfigurableStart, ConfigurableEnd {}
export const useNonAdjustedPositions: ConfigurableStartEnd = {
useNonAdjustedStartPosition: true,
useNonAdjustedEndPosition: true,
const useNonAdjustedPositions: ConfigurableStartEnd = {
leadingTriviaOption: LeadingTriviaOption.Exclude,
trailingTriviaOption: TrailingTriviaOption.Exclude,
};
export interface InsertNodeOptions {
@@ -143,11 +154,12 @@ namespace ts.textChanges {
}
function getAdjustedRange(sourceFile: SourceFile, startNode: Node, endNode: Node, options: ConfigurableStartEnd): TextRange {
return { pos: getAdjustedStartPosition(sourceFile, startNode, options, Position.Start), end: getAdjustedEndPosition(sourceFile, endNode, options) };
return { pos: getAdjustedStartPosition(sourceFile, startNode, options), end: getAdjustedEndPosition(sourceFile, endNode, options) };
}
function getAdjustedStartPosition(sourceFile: SourceFile, node: Node, options: ConfigurableStart, position: Position) {
if (options.useNonAdjustedStartPosition) {
function getAdjustedStartPosition(sourceFile: SourceFile, node: Node, options: ConfigurableStart) {
const { leadingTriviaOption } = options;
if (leadingTriviaOption === LeadingTriviaOption.Exclude) {
return node.getStart(sourceFile);
}
const fullStart = node.getFullStart();
@@ -165,7 +177,7 @@ namespace ts.textChanges {
// fullstart
// when b is replaced - we usually want to keep the leading trvia
// when b is deleted - we delete it
return position === Position.Start ? start : fullStart;
return leadingTriviaOption === LeadingTriviaOption.IncludeAll ? fullStart : start;
}
// get start position of the line following the line that contains fullstart position
// (but only if the fullstart isn't the very beginning of the file)
@@ -178,11 +190,12 @@ namespace ts.textChanges {
function getAdjustedEndPosition(sourceFile: SourceFile, node: Node, options: ConfigurableEnd) {
const { end } = node;
if (options.useNonAdjustedEndPosition || isExpression(node)) {
const { trailingTriviaOption } = options;
if (trailingTriviaOption === TrailingTriviaOption.Exclude || (isExpression(node) && trailingTriviaOption !== TrailingTriviaOption.Include)) {
return end;
}
const newEnd = skipTrivia(sourceFile.text, end, /*stopAfterLineBreak*/ true);
return newEnd !== end && isLineBreak(sourceFile.text.charCodeAt(newEnd - 1))
return newEnd !== end && (trailingTriviaOption === TrailingTriviaOption.Include || isLineBreak(sourceFile.text.charCodeAt(newEnd - 1)))
? newEnd
: end;
}
@@ -240,15 +253,15 @@ namespace ts.textChanges {
this.deleteRange(sourceFile, { pos: modifier.getStart(sourceFile), end: skipTrivia(sourceFile.text, modifier.end, /*stopAfterLineBreak*/ true) });
}
public deleteNodeRange(sourceFile: SourceFile, startNode: Node, endNode: Node, options: ConfigurableStartEnd = {}): void {
const startPosition = getAdjustedStartPosition(sourceFile, startNode, options, Position.FullStart);
public deleteNodeRange(sourceFile: SourceFile, startNode: Node, endNode: Node, options: ConfigurableStartEnd = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }): void {
const startPosition = getAdjustedStartPosition(sourceFile, startNode, options);
const endPosition = getAdjustedEndPosition(sourceFile, endNode, options);
this.deleteRange(sourceFile, { pos: startPosition, end: endPosition });
}
public deleteNodeRangeExcludingEnd(sourceFile: SourceFile, startNode: Node, afterEndNode: Node | undefined, options: ConfigurableStartEnd = {}): void {
const startPosition = getAdjustedStartPosition(sourceFile, startNode, options, Position.FullStart);
const endPosition = afterEndNode === undefined ? sourceFile.text.length : getAdjustedStartPosition(sourceFile, afterEndNode, options, Position.FullStart);
public deleteNodeRangeExcludingEnd(sourceFile: SourceFile, startNode: Node, afterEndNode: Node | undefined, options: ConfigurableStartEnd = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }): void {
const startPosition = getAdjustedStartPosition(sourceFile, startNode, options);
const endPosition = afterEndNode === undefined ? sourceFile.text.length : getAdjustedStartPosition(sourceFile, afterEndNode, options);
this.deleteRange(sourceFile, { pos: startPosition, end: endPosition });
}
@@ -307,7 +320,7 @@ namespace ts.textChanges {
}
public insertNodeBefore(sourceFile: SourceFile, before: Node, newNode: Node, blankLineBetween = false): void {
this.insertNodeAt(sourceFile, getAdjustedStartPosition(sourceFile, before, {}, Position.Start), newNode, this.getOptionsForInsertNodeBefore(before, blankLineBetween));
this.insertNodeAt(sourceFile, getAdjustedStartPosition(sourceFile, before, {}), newNode, this.getOptionsForInsertNodeBefore(before, blankLineBetween));
}
public insertModifierBefore(sourceFile: SourceFile, modifier: SyntaxKind, before: Node): void {
@@ -427,7 +440,7 @@ namespace ts.textChanges {
}
public insertNodeAtEndOfScope(sourceFile: SourceFile, scope: Node, newNode: Node): void {
const pos = getAdjustedStartPosition(sourceFile, scope.getLastToken()!, {}, Position.Start);
const pos = getAdjustedStartPosition(sourceFile, scope.getLastToken()!, {});
this.insertNodeAt(sourceFile, pos, newNode, {
prefix: isLineBreak(sourceFile.text.charCodeAt(scope.getLastToken()!.pos)) ? this.newLineCharacter : this.newLineCharacter + this.newLineCharacter,
suffix: this.newLineCharacter
@@ -736,7 +749,7 @@ namespace ts.textChanges {
// find first non-whitespace position in the leading trivia of the node
function startPositionToDeleteNodeInList(sourceFile: SourceFile, node: Node): number {
return skipTrivia(sourceFile.text, getAdjustedStartPosition(sourceFile, node, {}, Position.FullStart), /*stopAfterLineBreak*/ false, /*stopAtComments*/ true);
return skipTrivia(sourceFile.text, getAdjustedStartPosition(sourceFile, node, { leadingTriviaOption: LeadingTriviaOption.IncludeAll }), /*stopAfterLineBreak*/ false, /*stopAtComments*/ true);
}
function getClassOrObjectBraceEnds(cls: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression, sourceFile: SourceFile): [number, number] {
@@ -1090,7 +1103,7 @@ namespace ts.textChanges {
case SyntaxKind.ImportDeclaration:
deleteNode(changes, sourceFile, node,
// For first import, leave header comment in place
node === sourceFile.imports[0].parent ? { useNonAdjustedStartPosition: true, useNonAdjustedEndPosition: false } : undefined);
node === sourceFile.imports[0].parent ? { leadingTriviaOption: LeadingTriviaOption.Exclude } : undefined);
break;
case SyntaxKind.BindingElement:
@@ -1134,7 +1147,7 @@ namespace ts.textChanges {
deleteNodeInList(changes, deletedNodesInLists, sourceFile, node);
}
else {
deleteNode(changes, sourceFile, node, node.kind === SyntaxKind.SemicolonToken ? { useNonAdjustedEndPosition: true } : undefined);
deleteNode(changes, sourceFile, node, node.kind === SyntaxKind.SemicolonToken ? { trailingTriviaOption: TrailingTriviaOption.Exclude } : undefined);
}
}
}
@@ -1213,8 +1226,8 @@ namespace ts.textChanges {
/** Warning: This deletes comments too. See `copyComments` in `convertFunctionToEs6Class`. */
// Exported for tests only! (TODO: improve tests to not need this)
export function deleteNode(changes: ChangeTracker, sourceFile: SourceFile, node: Node, options: ConfigurableStartEnd = {}): void {
const startPosition = getAdjustedStartPosition(sourceFile, node, options, Position.FullStart);
export function deleteNode(changes: ChangeTracker, sourceFile: SourceFile, node: Node, options: ConfigurableStartEnd = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }): void {
const startPosition = getAdjustedStartPosition(sourceFile, node, options);
const endPosition = getAdjustedEndPosition(sourceFile, node, options);
changes.deleteRange(sourceFile, { pos: startPosition, end: endPosition });
}
+1
View File
@@ -84,6 +84,7 @@
"refactors/generateGetAccessorAndSetAccessor.ts",
"refactors/moveToNewFile.ts",
"refactors/addOrRemoveBracesToArrowFunction.ts",
"refactors/convertToNamedParameters.ts",
"services.ts",
"breakpoints.ts",
"transform.ts",
+60 -4
View File
@@ -1664,6 +1664,18 @@ namespace ts {
return ensureScriptKind(fileName, host && host.getScriptKind && host.getScriptKind(fileName));
}
export function getSymbolTarget(symbol: Symbol): Symbol {
let next: Symbol = symbol;
while (isTransientSymbol(next) && next.target) {
next = next.target;
}
return next;
}
function isTransientSymbol(symbol: Symbol): symbol is TransientSymbol {
return (symbol.flags & SymbolFlags.Transient) !== 0;
}
export function getUniqueSymbolId(symbol: Symbol, checker: TypeChecker) {
return getSymbolId(skipAlias(symbol, checker));
}
@@ -1821,8 +1833,28 @@ namespace ts {
return lastPos;
}
export function copyComments(sourceNode: Node, targetNode: Node, sourceFile: SourceFile, commentKind?: CommentKind, hasTrailingNewLine?: boolean) {
forEachLeadingCommentRange(sourceFile.text, sourceNode.pos, (pos, end, kind, htnl) => {
export function copyLeadingComments(sourceNode: Node, targetNode: Node, sourceFile: SourceFile, commentKind?: CommentKind, hasTrailingNewLine?: boolean) {
forEachLeadingCommentRange(sourceFile.text, sourceNode.pos, getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, addSyntheticLeadingComment));
}
export function copyTrailingComments(sourceNode: Node, targetNode: Node, sourceFile: SourceFile, commentKind?: CommentKind, hasTrailingNewLine?: boolean) {
forEachTrailingCommentRange(sourceFile.text, sourceNode.end, getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, addSyntheticTrailingComment));
}
/**
* This function copies the trailing comments for the token that comes before `sourceNode`, as leading comments of `targetNode`.
* This is useful because sometimes a comment that refers to `sourceNode` will be a leading comment for `sourceNode`, according to the
* notion of trivia ownership, and instead will be a trailing comment for the token before `sourceNode`, e.g.:
* `function foo(\* not leading comment for a *\ a: string) {}`
* The comment refers to `a` but belongs to the `(` token, but we might want to copy it.
*/
export function copyTrailingAsLeadingComments(sourceNode: Node, targetNode: Node, sourceFile: SourceFile, commentKind?: CommentKind, hasTrailingNewLine?: boolean) {
forEachTrailingCommentRange(sourceFile.text, sourceNode.pos, getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, addSyntheticLeadingComment));
}
function getAddCommentsFunction(targetNode: Node, sourceFile: SourceFile, commentKind: CommentKind | undefined, hasTrailingNewLine: boolean | undefined, cb: (node: Node, kind: CommentKind, text: string, hasTrailingNewLine?: boolean) => void) {
return (pos: number, end: number, kind: CommentKind, htnl: boolean) => {
if (kind === SyntaxKind.MultiLineCommentTrivia) {
// Remove leading /*
pos += 2;
@@ -1833,8 +1865,8 @@ namespace ts {
// Remove leading //
pos += 2;
}
addSyntheticLeadingComment(targetNode, commentKind || kind, sourceFile.text.slice(pos, end), hasTrailingNewLine !== undefined ? hasTrailingNewLine : htnl);
});
cb(targetNode, commentKind || kind, sourceFile.text.slice(pos, end), hasTrailingNewLine !== undefined ? hasTrailingNewLine : htnl);
};
}
function indexInTextChange(change: string, name: string): number {
@@ -1914,4 +1946,28 @@ namespace ts {
export function getSwitchedType(caseClause: CaseClause, checker: TypeChecker): Type | undefined {
return checker.getTypeAtLocation(caseClause.parent.parent.expression);
}
export function getTypeNodeIfAccessible(type: Type, enclosingScope: Node, program: Program, host: LanguageServiceHost): TypeNode | undefined {
const checker = program.getTypeChecker();
let typeIsAccessible = true;
const notAccessible = () => { typeIsAccessible = false; };
const res = checker.typeToTypeNode(type, enclosingScope, /*flags*/ undefined, {
trackSymbol: (symbol, declaration, meaning) => {
// TODO: GH#18217
typeIsAccessible = typeIsAccessible && checker.isSymbolAccessible(symbol, declaration, meaning!, /*shouldComputeAliasToMarkVisible*/ false).accessibility === SymbolAccessibility.Accessible;
},
reportInaccessibleThisError: notAccessible,
reportPrivateInBaseOfClassExpression: notAccessible,
reportInaccessibleUniqueSymbolError: notAccessible,
moduleResolverHost: {
readFile: host.readFile,
fileExists: host.fileExists,
directoryExists: host.directoryExists,
getSourceFiles: program.getSourceFiles,
getCurrentDirectory: program.getCurrentDirectory,
getCommonSourceDirectory: program.getCommonSourceDirectory,
}
});
return typeIsAccessible ? res : undefined;
}
}
+17 -19
View File
@@ -538,25 +538,23 @@ namespace Harness.Parallel.Host {
let xunitReporter: import("mocha").reporters.XUnit | undefined;
let failedTestReporter: import("../../../scripts/failed-tests") | undefined;
if (Utils.getExecutionEnvironment() !== Utils.ExecutionEnvironment.Browser) {
if (process.env.CI === "true") {
xunitReporter = new Mocha.reporters.XUnit(replayRunner, {
reporterOptions: {
suiteName: "Tests",
output: "./TEST-results.xml"
}
});
patchStats(xunitReporter.stats);
xunitReporter.write(`<?xml version="1.0" encoding="UTF-8"?>\n`);
}
else {
failedTestReporter = new FailedTestReporter(replayRunner, {
reporterOptions: {
file: path.resolve(".failed-tests"),
keepFailed
}
});
}
if (process.env.CI === "true") {
xunitReporter = new Mocha.reporters.XUnit(replayRunner, {
reporterOptions: {
suiteName: "Tests",
output: "./TEST-results.xml"
}
});
patchStats(xunitReporter.stats);
xunitReporter.write(`<?xml version="1.0" encoding="UTF-8"?>\n`);
}
else {
failedTestReporter = new FailedTestReporter(replayRunner, {
reporterOptions: {
file: path.resolve(".failed-tests"),
keepFailed
}
});
}
const savedUseColors = Base.useColors;
+7 -12
View File
@@ -182,10 +182,7 @@ function handleTestConfig() {
runners.push(new CompilerBaselineRunner(CompilerTestType.Conformance));
runners.push(new CompilerBaselineRunner(CompilerTestType.Regressions));
// TODO: project tests don"t work in the browser yet
if (Utils.getExecutionEnvironment() !== Utils.ExecutionEnvironment.Browser) {
runners.push(new project.ProjectRunner());
}
runners.push(new project.ProjectRunner());
// language services
runners.push(new FourSlashRunner(FourSlash.FourSlashTestType.Native));
@@ -195,7 +192,7 @@ function handleTestConfig() {
// runners.push(new GeneratedFourslashRunner());
// CRON-only tests
if (Utils.getExecutionEnvironment() !== Utils.ExecutionEnvironment.Browser && process.env.TRAVIS_EVENT_TYPE === "cron") {
if (process.env.TRAVIS_EVENT_TYPE === "cron") {
runners.push(new UserCodeRunner());
}
}
@@ -229,13 +226,11 @@ function beginTests() {
let isWorker: boolean;
function startTestEnvironment() {
isWorker = handleTestConfig();
if (Utils.getExecutionEnvironment() !== Utils.ExecutionEnvironment.Browser) {
if (isWorker) {
return Harness.Parallel.Worker.start();
}
else if (taskConfigsFolder && workerCount && workerCount > 1) {
return Harness.Parallel.Host.start();
}
if (isWorker) {
return Harness.Parallel.Worker.start();
}
else if (taskConfigsFolder && workerCount && workerCount > 1) {
return Harness.Parallel.Host.start();
}
beginTests();
}
+1
View File
@@ -105,6 +105,7 @@
"unittests/tscWatch/resolutionCache.ts",
"unittests/tscWatch/watchEnvironment.ts",
"unittests/tscWatch/watchApi.ts",
"unittests/tsserver/applyChangesToOpenFiles.ts",
"unittests/tsserver/cachingFileSystemInformation.ts",
"unittests/tsserver/cancellationToken.ts",
"unittests/tsserver/compileOnSave.ts",
@@ -140,13 +140,13 @@ var z = 3; // comment 4
deleteNode(changeTracker, sourceFile, findVariableStatementContaining("y", sourceFile));
});
runSingleFileTest("deleteNode2", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
deleteNode(changeTracker, sourceFile, findVariableStatementContaining("y", sourceFile), { useNonAdjustedStartPosition: true });
deleteNode(changeTracker, sourceFile, findVariableStatementContaining("y", sourceFile), { leadingTriviaOption: textChanges.LeadingTriviaOption.Exclude });
});
runSingleFileTest("deleteNode3", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
deleteNode(changeTracker, sourceFile, findVariableStatementContaining("y", sourceFile), { useNonAdjustedEndPosition: true });
deleteNode(changeTracker, sourceFile, findVariableStatementContaining("y", sourceFile), { trailingTriviaOption: textChanges.TrailingTriviaOption.Exclude });
});
runSingleFileTest("deleteNode4", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
deleteNode(changeTracker, sourceFile, findVariableStatementContaining("y", sourceFile), { useNonAdjustedStartPosition: true, useNonAdjustedEndPosition: true });
deleteNode(changeTracker, sourceFile, findVariableStatementContaining("y", sourceFile), { leadingTriviaOption: textChanges.LeadingTriviaOption.Exclude, trailingTriviaOption: textChanges.TrailingTriviaOption.Exclude });
});
runSingleFileTest("deleteNode5", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
deleteNode(changeTracker, sourceFile, findVariableStatementContaining("x", sourceFile));
@@ -167,15 +167,15 @@ var a = 4; // comment 7
});
runSingleFileTest("deleteNodeRange2", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile),
{ useNonAdjustedStartPosition: true });
{ leadingTriviaOption: textChanges.LeadingTriviaOption.Exclude });
});
runSingleFileTest("deleteNodeRange3", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile),
{ useNonAdjustedEndPosition: true });
{ trailingTriviaOption: textChanges.TrailingTriviaOption.Exclude });
});
runSingleFileTest("deleteNodeRange4", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile),
{ useNonAdjustedStartPosition: true, useNonAdjustedEndPosition: true });
{ leadingTriviaOption: textChanges.LeadingTriviaOption.Exclude, trailingTriviaOption: textChanges.TrailingTriviaOption.Exclude });
});
}
function createTestVariableDeclaration(name: string) {
@@ -254,16 +254,16 @@ var a = 4; // comment 7`;
changeTracker.replaceNode(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { suffix: newLineCharacter });
});
runSingleFileTest("replaceNode2", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
changeTracker.replaceNode(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { useNonAdjustedStartPosition: true, suffix: newLineCharacter, prefix: newLineCharacter });
changeTracker.replaceNode(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { leadingTriviaOption: textChanges.LeadingTriviaOption.Exclude, suffix: newLineCharacter, prefix: newLineCharacter });
});
runSingleFileTest("replaceNode3", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
changeTracker.replaceNode(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { useNonAdjustedEndPosition: true, suffix: newLineCharacter });
changeTracker.replaceNode(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { trailingTriviaOption: textChanges.TrailingTriviaOption.Exclude, suffix: newLineCharacter });
});
runSingleFileTest("replaceNode4", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
changeTracker.replaceNode(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { useNonAdjustedStartPosition: true, useNonAdjustedEndPosition: true });
changeTracker.replaceNode(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { leadingTriviaOption: textChanges.LeadingTriviaOption.Exclude, trailingTriviaOption: textChanges.TrailingTriviaOption.Exclude });
});
runSingleFileTest("replaceNode5", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
changeTracker.replaceNode(sourceFile, findVariableStatementContaining("x", sourceFile), createTestClass(), { useNonAdjustedStartPosition: true, useNonAdjustedEndPosition: true });
changeTracker.replaceNode(sourceFile, findVariableStatementContaining("x", sourceFile), createTestClass(), { leadingTriviaOption: textChanges.LeadingTriviaOption.Exclude, trailingTriviaOption: textChanges.TrailingTriviaOption.Exclude });
});
}
{
@@ -279,13 +279,13 @@ var a = 4; // comment 7`;
changeTracker.replaceNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), createTestClass(), { suffix: newLineCharacter });
});
runSingleFileTest("replaceNodeRange2", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
changeTracker.replaceNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), createTestClass(), { useNonAdjustedStartPosition: true, suffix: newLineCharacter, prefix: newLineCharacter });
changeTracker.replaceNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), createTestClass(), { leadingTriviaOption: textChanges.LeadingTriviaOption.Exclude, suffix: newLineCharacter, prefix: newLineCharacter });
});
runSingleFileTest("replaceNodeRange3", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
changeTracker.replaceNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), createTestClass(), { useNonAdjustedEndPosition: true, suffix: newLineCharacter });
changeTracker.replaceNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), createTestClass(), { trailingTriviaOption: textChanges.TrailingTriviaOption.Exclude, suffix: newLineCharacter });
});
runSingleFileTest("replaceNodeRange4", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
changeTracker.replaceNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), createTestClass(), { useNonAdjustedStartPosition: true, useNonAdjustedEndPosition: true });
changeTracker.replaceNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), createTestClass(), { leadingTriviaOption: textChanges.LeadingTriviaOption.Exclude, trailingTriviaOption: textChanges.TrailingTriviaOption.Exclude });
});
}
{
@@ -0,0 +1,148 @@
namespace ts.projectSystem {
describe("unittests:: tsserver:: applyChangesToOpenFiles", () => {
const configFile: File = {
path: "/a/b/tsconfig.json",
content: "{}"
};
const file3: File = {
path: "/a/b/file3.ts",
content: "let xyz = 1;"
};
const app: File = {
path: "/a/b/app.ts",
content: "let z = 1;"
};
function fileContentWithComment(file: File) {
return `// some copy right notice
${file.content}`;
}
function verifyText(service: server.ProjectService, file: string, expected: string) {
const info = service.getScriptInfo(file)!;
const snap = info.getSnapshot();
// Verified applied in reverse order
assert.equal(snap.getText(0, snap.getLength()), expected, `Text of changed file: ${file}`);
}
function verifyProjectVersion(project: server.Project, expected: number) {
assert.equal(Number(project.getProjectVersion()), expected);
}
function verify(applyChangesToOpen: (session: TestSession) => void) {
const host = createServerHost([app, file3, commonFile1, commonFile2, libFile, configFile]);
const session = createSession(host);
session.executeCommandSeq<protocol.OpenRequest>({
command: protocol.CommandTypes.Open,
arguments: { file: app.path }
});
const service = session.getProjectService();
const project = service.configuredProjects.get(configFile.path)!;
assert.isDefined(project);
verifyProjectVersion(project, 1);
session.executeCommandSeq<protocol.OpenRequest>({
command: protocol.CommandTypes.Open,
arguments: {
file: file3.path,
fileContent: fileContentWithComment(file3)
}
});
verifyProjectVersion(project, 2);
// Verify Texts
verifyText(service, commonFile1.path, commonFile1.content);
verifyText(service, commonFile2.path, commonFile2.content);
verifyText(service, app.path, app.content);
verifyText(service, file3.path, fileContentWithComment(file3));
// Apply changes
applyChangesToOpen(session);
// Verify again
verifyProjectVersion(project, 3);
// Open file contents
verifyText(service, commonFile1.path, fileContentWithComment(commonFile1));
verifyText(service, commonFile2.path, fileContentWithComment(commonFile2));
verifyText(service, app.path, "let zzz = 10;let zz = 10;let z = 1;");
verifyText(service, file3.path, file3.content);
}
it("with applyChangedToOpenFiles request", () => {
verify(session =>
session.executeCommandSeq<protocol.ApplyChangedToOpenFilesRequest>({
command: protocol.CommandTypes.ApplyChangedToOpenFiles,
arguments: {
openFiles: [
{
fileName: commonFile1.path,
content: fileContentWithComment(commonFile1)
},
{
fileName: commonFile2.path,
content: fileContentWithComment(commonFile2)
}
],
changedFiles: [
{
fileName: app.path,
changes: [
{
span: { start: 0, length: 0 },
newText: "let zzz = 10;"
},
{
span: { start: 0, length: 0 },
newText: "let zz = 10;"
}
]
}
],
closedFiles: [
file3.path
]
}
})
);
});
it("with updateOpen request", () => {
verify(session =>
session.executeCommandSeq<protocol.UpdateOpenRequest>({
command: protocol.CommandTypes.UpdateOpen,
arguments: {
openFiles: [
{
file: commonFile1.path,
fileContent: fileContentWithComment(commonFile1)
},
{
file: commonFile2.path,
fileContent: fileContentWithComment(commonFile2)
}
],
changedFiles: [
{
fileName: app.path,
textChanges: [
{
start: { line: 1, offset: 1 },
end: { line: 1, offset: 1 },
newText: "let zzz = 10;",
},
{
start: { line: 1, offset: 1 },
end: { line: 1, offset: 1 },
newText: "let zz = 10;",
}
]
}
],
closedFiles: [
file3.path
]
}
})
);
});
});
}
@@ -41,13 +41,13 @@ namespace ts.projectSystem {
function changeFileToNotImportModule(service: TestProjectService) {
const info = service.getScriptInfo(file.path)!;
service.applyChangesToFile(info, [{ span: { start: 0, length: importModuleContent.length }, newText: "" }]);
service.applyChangesToFile(info, singleIterator({ span: { start: 0, length: importModuleContent.length }, newText: "" }));
checkProject(service, /*moduleIsOrphan*/ true);
}
function changeFileToImportModule(service: TestProjectService) {
const info = service.getScriptInfo(file.path)!;
service.applyChangesToFile(info, [{ span: { start: 0, length: 0 }, newText: importModuleContent }]);
service.applyChangesToFile(info, singleIterator({ span: { start: 0, length: 0 }, newText: importModuleContent }));
checkProject(service, /*moduleIsOrphan*/ false);
}
@@ -161,7 +161,7 @@ namespace ts.projectSystem {
checkNumberOfInferredProjects(projectService, 0);
externalFiles[0].content = "let x =1;";
projectService.applyChangesInOpenFiles(externalFiles, [], []);
projectService.applyChangesInOpenFiles(arrayIterator(externalFiles));
});
it("external project that included config files", () => {
@@ -790,9 +790,7 @@ namespace ts.projectSystem {
rootFiles: [{ fileName: tsconfig.path }, { fileName: jsFilePath }],
options: { allowJs: false }
}]);
service.applyChangesInOpenFiles([
{ fileName: jsFilePath, scriptKind: ScriptKind.JS, content: "" }
], /*changedFiles*/ undefined, /*closedFiles*/ undefined);
service.applyChangesInOpenFiles(singleIterator({ fileName: jsFilePath, scriptKind: ScriptKind.JS, content: "" }));
checkNumberOfProjects(service, { configuredProjects: 1, inferredProjects: 1 });
checkProjectActualFiles(configProject, [tsconfig.path]);
const inferredProject = service.inferredProjects[0];
+10 -9
View File
@@ -202,7 +202,7 @@ namespace ts.projectSystem {
const host = createServerHost([file1, config1]);
const projectService = createProjectService(host, { useSingleInferredProject: true }, { syntaxOnly: true });
projectService.applyChangesInOpenFiles([{ fileName: file1.path, content: file1.content }], [], []);
projectService.applyChangesInOpenFiles(singleIterator({ fileName: file1.path, content: file1.content }));
checkNumberOfProjects(projectService, { inferredProjects: 1 });
const proj = projectService.inferredProjects[0];
@@ -588,11 +588,11 @@ namespace ts.projectSystem {
const host = createServerHost([]);
const projectService = createProjectService(host);
projectService.applyChangesInOpenFiles([tsFile], [], []);
projectService.applyChangesInOpenFiles(singleIterator(tsFile));
const projs = projectService.synchronizeProjectList([]);
projectService.findProject(projs[0].info!.projectName)!.getLanguageService().getNavigationBarItems(tsFile.fileName);
projectService.synchronizeProjectList([projs[0].info!]);
projectService.applyChangesInOpenFiles([jsFile], [], []);
projectService.applyChangesInOpenFiles(singleIterator(jsFile));
});
it("config file is deleted", () => {
@@ -696,11 +696,12 @@ namespace ts.projectSystem {
checkProjectActualFiles(configuredProjectAt(projectService, 0), [file1.path, file2.path, config.path]);
// Open HTML file
projectService.applyChangesInOpenFiles(
/*openFiles*/[{ fileName: file2.path, hasMixedContent: true, scriptKind: ScriptKind.JS, content: `var hello = "hello";` }],
/*changedFiles*/ undefined,
/*closedFiles*/ undefined);
projectService.applyChangesInOpenFiles(singleIterator({
fileName: file2.path,
hasMixedContent: true,
scriptKind: ScriptKind.JS,
content: `var hello = "hello";`
}));
// Now HTML file is included in the project
checkNumberOfProjects(projectService, { configuredProjects: 1 });
checkProjectActualFiles(configuredProjectAt(projectService, 0), [file1.path, file2.path, config.path]);
@@ -853,7 +854,7 @@ namespace ts.projectSystem {
checkNumberOfProjects(projectService, { inferredProjects: 1 });
projectService.applyChangesInOpenFiles(
/*openFiles*/ undefined,
/*changedFiles*/[{ fileName: file1.path, changes: [{ span: createTextSpan(0, file1.path.length), newText: "let y = 1" }] }],
/*changedFiles*/singleIterator({ fileName: file1.path, changes: singleIterator({ span: createTextSpan(0, file1.path.length), newText: "let y = 1" }) }),
/*closedFiles*/ undefined);
checkNumberOfProjects(projectService, { inferredProjects: 1 });
@@ -132,4 +132,79 @@ namespace ts.projectSystem {
verifyRootedDirectoryWatch("c:/users/username/");
});
});
it(`unittests:: tsserver:: watchEnvironment:: tsserverProjectSystem recursive watch directory implementation does not watch files/directories in node_modules starting with "."`, () => {
const projectFolder = "/a/username/project";
const projectSrcFolder = `${projectFolder}/src`;
const configFile: File = {
path: `${projectFolder}/tsconfig.json`,
content: "{}"
};
const index: File = {
path: `${projectSrcFolder}/index.ts`,
content: `import {} from "file"`
};
const file1: File = {
path: `${projectSrcFolder}/file1.ts`,
content: ""
};
const nodeModulesExistingUnusedFile: File = {
path: `${projectFolder}/node_modules/someFile.d.ts`,
content: ""
};
const fileNames = [index, file1, configFile, libFile].map(file => file.path);
// All closed files(files other than index), project folder, project/src folder and project/node_modules/@types folder
const expectedWatchedFiles = arrayToMap(fileNames.slice(1), identity, () => 1);
const expectedWatchedDirectories = arrayToMap([projectFolder, projectSrcFolder, `${projectFolder}/${nodeModules}`, `${projectFolder}/${nodeModulesAtTypes}`], identity, () => 1);
const environmentVariables = createMap<string>();
environmentVariables.set("TSC_WATCHDIRECTORY", Tsc_WatchDirectory.NonRecursiveWatchDirectory);
const host = createServerHost([index, file1, configFile, libFile, nodeModulesExistingUnusedFile], { environmentVariables });
const projectService = createProjectService(host);
projectService.openClientFile(index.path);
const project = Debug.assertDefined(projectService.configuredProjects.get(configFile.path));
verifyProject();
const nodeModulesIgnoredFileFromIgnoreDirectory: File = {
path: `${projectFolder}/node_modules/.cache/someFile.d.ts`,
content: ""
};
host.ensureFileOrFolder(nodeModulesIgnoredFileFromIgnoreDirectory);
host.checkTimeoutQueueLength(0);
verifyProject();
const nodeModulesIgnoredFile: File = {
path: `${projectFolder}/node_modules/.cacheFile.ts`,
content: ""
};
host.ensureFileOrFolder(nodeModulesIgnoredFile);
host.checkTimeoutQueueLength(0);
verifyProject();
const gitIgnoredFileFromIgnoreDirectory: File = {
path: `${projectFolder}/.git/someFile.d.ts`,
content: ""
};
host.ensureFileOrFolder(gitIgnoredFileFromIgnoreDirectory);
host.checkTimeoutQueueLength(0);
verifyProject();
const gitIgnoredFile: File = {
path: `${projectFolder}/.gitCache.d.ts`,
content: ""
};
host.ensureFileOrFolder(gitIgnoredFile);
host.checkTimeoutQueueLength(0);
verifyProject();
function verifyProject() {
checkWatchedDirectories(host, emptyArray, /*recursive*/ true);
checkWatchedFilesDetailed(host, expectedWatchedFiles);
checkWatchedDirectoriesDetailed(host, expectedWatchedDirectories, /*recursive*/ false);
checkProjectActualFiles(project, fileNames);
}
});
}
+29
View File
@@ -5769,6 +5769,7 @@ declare namespace ts.server.protocol {
OpenExternalProject = "openExternalProject",
OpenExternalProjects = "openExternalProjects",
CloseExternalProject = "closeExternalProject",
UpdateOpen = "updateOpen",
GetOutliningSpans = "getOutliningSpans",
TodoComments = "todoComments",
Indentation = "indentation",
@@ -6837,6 +6838,30 @@ declare namespace ts.server.protocol {
*/
interface CloseExternalProjectResponse extends Response {
}
/**
* Request to synchronize list of open files with the client
*/
interface UpdateOpenRequest extends Request {
command: CommandTypes.UpdateOpen;
arguments: UpdateOpenRequestArgs;
}
/**
* Arguments to UpdateOpenRequest
*/
interface UpdateOpenRequestArgs {
/**
* List of newly open files
*/
openFiles?: OpenRequestArgs[];
/**
* List of open files files that were changes
*/
changedFiles?: FileCodeEdits[];
/**
* List of files that were closed
*/
closedFiles?: string[];
}
/**
* Request to set compiler options for inferred projects.
* External projects are opened / closed explicitly.
@@ -8676,6 +8701,7 @@ declare namespace ts.server {
*/
private onConfigFileChangeForOpenScriptInfo;
private removeProject;
private assignOrphanScriptInfosToInferredProject;
/**
* Remove this file from the set of open, non-configured files.
* @param info The file that has been closed or newly configured
@@ -8794,6 +8820,9 @@ declare namespace ts.server {
*/
openClientFile(fileName: string, fileContent?: string, scriptKind?: ScriptKind, projectRootPath?: string): OpenConfiguredProjectResult;
private findExternalProjectContainingOpenScriptInfo;
private getOrCreateOpenScriptInfo;
private assignProjectToOpenedScriptInfo;
private cleanupAfterOpeningFile;
openClientFileWithNormalizedPath(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, projectRootPath?: NormalizedPath): OpenConfiguredProjectResult;
private removeOrphanConfiguredProjects;
private removeOrphanScriptInfos;
@@ -15,8 +15,8 @@ var e = <K>(x: string, y?: K) => x.length;
>length : number
var r99 = map(e); // should be {}[] for S since a generic lambda is not inferentially typed
>r99 : (a: {}[]) => number[]
>map(e) : (a: {}[]) => number[]
>r99 : <K>(a: string[]) => number[]
>map(e) : <K>(a: string[]) => number[]
>map : <S, T>(f: (x: S) => T) => (a: S[]) => T[]
>e : <K>(x: string, y?: K) => number
@@ -37,8 +37,8 @@ var e2 = <K>(x: string, y?: K) => x.length;
>length : number
var r100 = map2(e2); // type arg inference should fail for S since a generic lambda is not inferentially typed. Falls back to { length: number }
>r100 : (a: { length: number; }[]) => number[]
>map2(e2) : (a: { length: number; }[]) => number[]
>r100 : <K>(a: string[]) => number[]
>map2(e2) : <K>(a: string[]) => number[]
>map2 : <S extends { length: number; }, T>(f: (x: S) => T) => (a: S[]) => T[]
>e2 : <K>(x: string, y?: K) => number
@@ -31,8 +31,8 @@ var id: <T>(x:T) => T;
>x : T
var r23 = dot(id)(id);
>r23 : (_: {}) => {}
>dot(id)(id) : (_: {}) => {}
>r23 : <T>(_: T) => {}
>dot(id)(id) : <T>(_: T) => {}
>dot(id) : <U>(g: (_: U) => {}) => (_: U) => {}
>dot : <T, S>(f: (_: T) => S) => <U>(g: (_: U) => T) => (_: U) => S
>id : <T>(x: T) => T
@@ -0,0 +1,15 @@
/FromFactor.ts(2,15): error TS2304: Cannot find name 'StringKeyOf'.
/FromFactor.ts(2,15): error TS4103: Type parameter 'TName' of exported mapped object type is using private name 'StringKeyOf'.
==== /Helpers.ts (0 errors) ====
export type StringKeyOf<TObj> = Extract<string, keyof TObj>;
==== /FromFactor.ts (2 errors) ====
export type RowToColumns<TColumns> = {
[TName in StringKeyOf<TColumns>]: any;
~~~~~~~~~~~
!!! error TS2304: Cannot find name 'StringKeyOf'.
~~~~~~~~~~~
!!! error TS4103: Type parameter 'TName' of exported mapped object type is using private name 'StringKeyOf'.
}
@@ -0,0 +1,20 @@
//// [tests/cases/compiler/declarationEmitMappedPrivateTypeTypeParameter.ts] ////
//// [Helpers.ts]
export type StringKeyOf<TObj> = Extract<string, keyof TObj>;
//// [FromFactor.ts]
export type RowToColumns<TColumns> = {
[TName in StringKeyOf<TColumns>]: any;
}
//// [Helpers.js]
"use strict";
exports.__esModule = true;
//// [FromFactor.js]
"use strict";
exports.__esModule = true;
//// [Helpers.d.ts]
export declare type StringKeyOf<TObj> = Extract<string, keyof TObj>;
@@ -0,0 +1,16 @@
=== /Helpers.ts ===
export type StringKeyOf<TObj> = Extract<string, keyof TObj>;
>StringKeyOf : Symbol(StringKeyOf, Decl(Helpers.ts, 0, 0))
>TObj : Symbol(TObj, Decl(Helpers.ts, 0, 24))
>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --))
>TObj : Symbol(TObj, Decl(Helpers.ts, 0, 24))
=== /FromFactor.ts ===
export type RowToColumns<TColumns> = {
>RowToColumns : Symbol(RowToColumns, Decl(FromFactor.ts, 0, 0))
>TColumns : Symbol(TColumns, Decl(FromFactor.ts, 0, 25))
[TName in StringKeyOf<TColumns>]: any;
>TName : Symbol(TName, Decl(FromFactor.ts, 1, 5))
>TColumns : Symbol(TColumns, Decl(FromFactor.ts, 0, 25))
}
@@ -0,0 +1,10 @@
=== /Helpers.ts ===
export type StringKeyOf<TObj> = Extract<string, keyof TObj>;
>StringKeyOf : Extract<string, keyof TObj>
=== /FromFactor.ts ===
export type RowToColumns<TColumns> = {
>RowToColumns : RowToColumns<TColumns>
[TName in StringKeyOf<TColumns>]: any;
}
@@ -0,0 +1,193 @@
tests/cases/compiler/genericFunctionInference1.ts(83,14): error TS2345: Argument of type '<a>(value: { key: a; }) => a' is not assignable to parameter of type '(value: Data) => string'.
Type 'number' is not assignable to type 'string'.
==== tests/cases/compiler/genericFunctionInference1.ts (1 errors) ====
declare function pipe<A extends any[], B>(ab: (...args: A) => B): (...args: A) => B;
declare function pipe<A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C;
declare function pipe<A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D;
declare function list<T>(a: T): T[];
declare function box<V>(x: V): { value: V };
declare function foo<T extends { value: T }>(x: T): T;
const f00 = pipe(list);
const f01 = pipe(list, box);
const f02 = pipe(box, list);
const f03 = pipe(x => list(x), box);
const f04 = pipe(list, x => box(x));
const f05 = pipe(x => list(x), x => box(x))
const f06 = pipe(list, pipe(box));
const f07 = pipe(x => list(x), pipe(box));
const f08 = pipe(x => list(x), pipe(x => box(x)));
const f09 = pipe(list, x => x.length);
const f10 = pipe(foo);
const f11 = pipe(foo, foo);
const g00: <T>(x: T) => T[] = pipe(list);
const g01: <T>(x: T) => { value: T[] } = pipe(list, box);
const g02: <T>(x: T) => { value: T }[] = pipe(box, list);
const g03: <T>(x: T) => { value: T[] } = pipe(x => list(x), box);
const g04: <T>(x: T) => { value: T[] } = pipe(list, x => box(x));
const g05: <T>(x: T) => { value: T[] } = pipe(x => list(x), x => box(x))
const g06: <T>(x: T) => { value: T[] } = pipe(list, pipe(box));
const g07: <T>(x: T) => { value: T[] } = pipe(x => list(x), pipe(box));
const g08: <T>(x: T) => { value: T[] } = pipe(x => list(x), pipe(x => box(x)));
const g09: <T>(x: T) => number = pipe(list, x => x.length);
const g10: <T extends { value: T }>(x: T) => T = pipe(foo);
const g12: <T extends { value: T }>(x: T) => T = pipe(foo, foo);
declare function pipe2<A, B, C, D>(ab: (a: A) => B, cd: (c: C) => D): (a: [A, C]) => [B, D];
const f20 = pipe2(list, box);
const f21 = pipe2(box, list);
const f22 = pipe2(list, list);
const f23 = pipe2(box, box);
const f24 = pipe2(f20, f20);
const f25 = pipe2(foo, foo);
const f26 = pipe2(f25, f25);
declare function pipe3<A, B, C>(ab: (a: A) => B, ac: (a: A) => C): (a: A) => [B, C];
const f30 = pipe3(list, box);
const f31 = pipe3(box, list);
const f32 = pipe3(list, list);
declare function pipe4<A, B, C>(funcs: [(a: A) => B, (b: B) => C]): (a: A) => C;
const f40 = pipe4([list, box]);
const f41 = pipe4([box, list]);
declare function pipe5<A, B>(f: (a: A) => B): { f: (a: A) => B };
const f50 = pipe5(list); // No higher order inference
// #417
function mirror<A, B>(f: (a: A) => B): (a: A) => B { return f; }
var identityM = mirror(identity);
var x = 1;
var y = identity(x);
var z = identityM(x);
// #3038
export function keyOf<a>(value: { key: a; }): a {
return value.key;
}
export interface Data {
key: number;
value: Date;
}
var data: Data[] = [];
declare function toKeys<a>(values: a[], toKey: (value: a) => string): string[];
toKeys(data, keyOf); // Error
~~~~~
!!! error TS2345: Argument of type '<a>(value: { key: a; }) => a' is not assignable to parameter of type '(value: Data) => string'.
!!! error TS2345: Type 'number' is not assignable to type 'string'.
// #9366
function flip<a, b, c>(f: (a: a, b: b) => c): (b: b, a: a) => c {
return (b: b, a: a) => f(a, b);
}
function zip<T, U>(x: T, y: U): [T, U] {
return [x, y];
}
var expected: <T, U>(y: U, x: T) => [T, U] = flip(zip);
var actual = flip(zip);
// #9366
const map = <T, U>(transform: (t: T) => U) =>
(arr: T[]) => arr.map(transform)
const identityStr = (t: string) => t;
const arr: string[] = map(identityStr)(['a']);
const arr1: string[] = map(identity)(['a']);
// #9949
function of2<a, b>(one: a, two: b): [a, b] {
return [one, two];
}
const flipped = flip(of2);
// #29904.1
type Component<P> = (props: P) => {};
declare const myHoc1: <P>(C: Component<P>) => Component<P>;
declare const myHoc2: <P>(C: Component<P>) => Component<P>;
declare const MyComponent1: Component<{ foo: 1 }>;
const enhance = pipe(
myHoc1,
myHoc2,
);
const MyComponent2 = enhance(MyComponent1);
// #29904.2
const fn20 = pipe((_a?: {}) => 1);
// #29904.3
type Fn = (n: number) => number;
const fn30: Fn = pipe(
x => x + 1,
x => x * 2,
);
const promise = Promise.resolve(1);
promise.then(
pipe(
x => x + 1,
x => x * 2,
),
);
// #29904.4
declare const getString: () => string;
declare const orUndefined: (name: string) => string | undefined;
declare const identity: <T>(value: T) => T;
const fn40 = pipe(
getString,
string => orUndefined(string),
identity,
);
// #29904.6
declare const getArray: () => string[];
declare const first: <T>(ts: T[]) => T;
const fn60 = pipe(
getArray,
x => x,
first,
);
const fn61 = pipe(
getArray,
identity,
first,
);
const fn62 = pipe(
getArray,
x => x,
x => first(x),
);
@@ -0,0 +1,267 @@
//// [genericFunctionInference1.ts]
declare function pipe<A extends any[], B>(ab: (...args: A) => B): (...args: A) => B;
declare function pipe<A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C;
declare function pipe<A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D;
declare function list<T>(a: T): T[];
declare function box<V>(x: V): { value: V };
declare function foo<T extends { value: T }>(x: T): T;
const f00 = pipe(list);
const f01 = pipe(list, box);
const f02 = pipe(box, list);
const f03 = pipe(x => list(x), box);
const f04 = pipe(list, x => box(x));
const f05 = pipe(x => list(x), x => box(x))
const f06 = pipe(list, pipe(box));
const f07 = pipe(x => list(x), pipe(box));
const f08 = pipe(x => list(x), pipe(x => box(x)));
const f09 = pipe(list, x => x.length);
const f10 = pipe(foo);
const f11 = pipe(foo, foo);
const g00: <T>(x: T) => T[] = pipe(list);
const g01: <T>(x: T) => { value: T[] } = pipe(list, box);
const g02: <T>(x: T) => { value: T }[] = pipe(box, list);
const g03: <T>(x: T) => { value: T[] } = pipe(x => list(x), box);
const g04: <T>(x: T) => { value: T[] } = pipe(list, x => box(x));
const g05: <T>(x: T) => { value: T[] } = pipe(x => list(x), x => box(x))
const g06: <T>(x: T) => { value: T[] } = pipe(list, pipe(box));
const g07: <T>(x: T) => { value: T[] } = pipe(x => list(x), pipe(box));
const g08: <T>(x: T) => { value: T[] } = pipe(x => list(x), pipe(x => box(x)));
const g09: <T>(x: T) => number = pipe(list, x => x.length);
const g10: <T extends { value: T }>(x: T) => T = pipe(foo);
const g12: <T extends { value: T }>(x: T) => T = pipe(foo, foo);
declare function pipe2<A, B, C, D>(ab: (a: A) => B, cd: (c: C) => D): (a: [A, C]) => [B, D];
const f20 = pipe2(list, box);
const f21 = pipe2(box, list);
const f22 = pipe2(list, list);
const f23 = pipe2(box, box);
const f24 = pipe2(f20, f20);
const f25 = pipe2(foo, foo);
const f26 = pipe2(f25, f25);
declare function pipe3<A, B, C>(ab: (a: A) => B, ac: (a: A) => C): (a: A) => [B, C];
const f30 = pipe3(list, box);
const f31 = pipe3(box, list);
const f32 = pipe3(list, list);
declare function pipe4<A, B, C>(funcs: [(a: A) => B, (b: B) => C]): (a: A) => C;
const f40 = pipe4([list, box]);
const f41 = pipe4([box, list]);
declare function pipe5<A, B>(f: (a: A) => B): { f: (a: A) => B };
const f50 = pipe5(list); // No higher order inference
// #417
function mirror<A, B>(f: (a: A) => B): (a: A) => B { return f; }
var identityM = mirror(identity);
var x = 1;
var y = identity(x);
var z = identityM(x);
// #3038
export function keyOf<a>(value: { key: a; }): a {
return value.key;
}
export interface Data {
key: number;
value: Date;
}
var data: Data[] = [];
declare function toKeys<a>(values: a[], toKey: (value: a) => string): string[];
toKeys(data, keyOf); // Error
// #9366
function flip<a, b, c>(f: (a: a, b: b) => c): (b: b, a: a) => c {
return (b: b, a: a) => f(a, b);
}
function zip<T, U>(x: T, y: U): [T, U] {
return [x, y];
}
var expected: <T, U>(y: U, x: T) => [T, U] = flip(zip);
var actual = flip(zip);
// #9366
const map = <T, U>(transform: (t: T) => U) =>
(arr: T[]) => arr.map(transform)
const identityStr = (t: string) => t;
const arr: string[] = map(identityStr)(['a']);
const arr1: string[] = map(identity)(['a']);
// #9949
function of2<a, b>(one: a, two: b): [a, b] {
return [one, two];
}
const flipped = flip(of2);
// #29904.1
type Component<P> = (props: P) => {};
declare const myHoc1: <P>(C: Component<P>) => Component<P>;
declare const myHoc2: <P>(C: Component<P>) => Component<P>;
declare const MyComponent1: Component<{ foo: 1 }>;
const enhance = pipe(
myHoc1,
myHoc2,
);
const MyComponent2 = enhance(MyComponent1);
// #29904.2
const fn20 = pipe((_a?: {}) => 1);
// #29904.3
type Fn = (n: number) => number;
const fn30: Fn = pipe(
x => x + 1,
x => x * 2,
);
const promise = Promise.resolve(1);
promise.then(
pipe(
x => x + 1,
x => x * 2,
),
);
// #29904.4
declare const getString: () => string;
declare const orUndefined: (name: string) => string | undefined;
declare const identity: <T>(value: T) => T;
const fn40 = pipe(
getString,
string => orUndefined(string),
identity,
);
// #29904.6
declare const getArray: () => string[];
declare const first: <T>(ts: T[]) => T;
const fn60 = pipe(
getArray,
x => x,
first,
);
const fn61 = pipe(
getArray,
identity,
first,
);
const fn62 = pipe(
getArray,
x => x,
x => first(x),
);
//// [genericFunctionInference1.js]
const f00 = pipe(list);
const f01 = pipe(list, box);
const f02 = pipe(box, list);
const f03 = pipe(x => list(x), box);
const f04 = pipe(list, x => box(x));
const f05 = pipe(x => list(x), x => box(x));
const f06 = pipe(list, pipe(box));
const f07 = pipe(x => list(x), pipe(box));
const f08 = pipe(x => list(x), pipe(x => box(x)));
const f09 = pipe(list, x => x.length);
const f10 = pipe(foo);
const f11 = pipe(foo, foo);
const g00 = pipe(list);
const g01 = pipe(list, box);
const g02 = pipe(box, list);
const g03 = pipe(x => list(x), box);
const g04 = pipe(list, x => box(x));
const g05 = pipe(x => list(x), x => box(x));
const g06 = pipe(list, pipe(box));
const g07 = pipe(x => list(x), pipe(box));
const g08 = pipe(x => list(x), pipe(x => box(x)));
const g09 = pipe(list, x => x.length);
const g10 = pipe(foo);
const g12 = pipe(foo, foo);
const f20 = pipe2(list, box);
const f21 = pipe2(box, list);
const f22 = pipe2(list, list);
const f23 = pipe2(box, box);
const f24 = pipe2(f20, f20);
const f25 = pipe2(foo, foo);
const f26 = pipe2(f25, f25);
const f30 = pipe3(list, box);
const f31 = pipe3(box, list);
const f32 = pipe3(list, list);
const f40 = pipe4([list, box]);
const f41 = pipe4([box, list]);
const f50 = pipe5(list); // No higher order inference
// #417
function mirror(f) { return f; }
var identityM = mirror(identity);
var x = 1;
var y = identity(x);
var z = identityM(x);
// #3038
export function keyOf(value) {
return value.key;
}
var data = [];
toKeys(data, keyOf); // Error
// #9366
function flip(f) {
return (b, a) => f(a, b);
}
function zip(x, y) {
return [x, y];
}
var expected = flip(zip);
var actual = flip(zip);
// #9366
const map = (transform) => (arr) => arr.map(transform);
const identityStr = (t) => t;
const arr = map(identityStr)(['a']);
const arr1 = map(identity)(['a']);
// #9949
function of2(one, two) {
return [one, two];
}
const flipped = flip(of2);
const enhance = pipe(myHoc1, myHoc2);
const MyComponent2 = enhance(MyComponent1);
// #29904.2
const fn20 = pipe((_a) => 1);
const fn30 = pipe(x => x + 1, x => x * 2);
const promise = Promise.resolve(1);
promise.then(pipe(x => x + 1, x => x * 2));
const fn40 = pipe(getString, string => orUndefined(string), identity);
const fn60 = pipe(getArray, x => x, first);
const fn61 = pipe(getArray, identity, first);
const fn62 = pipe(getArray, x => x, x => first(x));
@@ -0,0 +1,850 @@
=== tests/cases/compiler/genericFunctionInference1.ts ===
declare function pipe<A extends any[], B>(ab: (...args: A) => B): (...args: A) => B;
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
>A : Symbol(A, Decl(genericFunctionInference1.ts, 0, 22))
>B : Symbol(B, Decl(genericFunctionInference1.ts, 0, 38))
>ab : Symbol(ab, Decl(genericFunctionInference1.ts, 0, 42))
>args : Symbol(args, Decl(genericFunctionInference1.ts, 0, 47))
>A : Symbol(A, Decl(genericFunctionInference1.ts, 0, 22))
>B : Symbol(B, Decl(genericFunctionInference1.ts, 0, 38))
>args : Symbol(args, Decl(genericFunctionInference1.ts, 0, 67))
>A : Symbol(A, Decl(genericFunctionInference1.ts, 0, 22))
>B : Symbol(B, Decl(genericFunctionInference1.ts, 0, 38))
declare function pipe<A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C;
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
>A : Symbol(A, Decl(genericFunctionInference1.ts, 1, 22))
>B : Symbol(B, Decl(genericFunctionInference1.ts, 1, 38))
>C : Symbol(C, Decl(genericFunctionInference1.ts, 1, 41))
>ab : Symbol(ab, Decl(genericFunctionInference1.ts, 1, 45))
>args : Symbol(args, Decl(genericFunctionInference1.ts, 1, 50))
>A : Symbol(A, Decl(genericFunctionInference1.ts, 1, 22))
>B : Symbol(B, Decl(genericFunctionInference1.ts, 1, 38))
>bc : Symbol(bc, Decl(genericFunctionInference1.ts, 1, 67))
>b : Symbol(b, Decl(genericFunctionInference1.ts, 1, 73))
>B : Symbol(B, Decl(genericFunctionInference1.ts, 1, 38))
>C : Symbol(C, Decl(genericFunctionInference1.ts, 1, 41))
>args : Symbol(args, Decl(genericFunctionInference1.ts, 1, 87))
>A : Symbol(A, Decl(genericFunctionInference1.ts, 1, 22))
>C : Symbol(C, Decl(genericFunctionInference1.ts, 1, 41))
declare function pipe<A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D;
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
>A : Symbol(A, Decl(genericFunctionInference1.ts, 2, 22))
>B : Symbol(B, Decl(genericFunctionInference1.ts, 2, 38))
>C : Symbol(C, Decl(genericFunctionInference1.ts, 2, 41))
>D : Symbol(D, Decl(genericFunctionInference1.ts, 2, 44))
>ab : Symbol(ab, Decl(genericFunctionInference1.ts, 2, 48))
>args : Symbol(args, Decl(genericFunctionInference1.ts, 2, 53))
>A : Symbol(A, Decl(genericFunctionInference1.ts, 2, 22))
>B : Symbol(B, Decl(genericFunctionInference1.ts, 2, 38))
>bc : Symbol(bc, Decl(genericFunctionInference1.ts, 2, 70))
>b : Symbol(b, Decl(genericFunctionInference1.ts, 2, 76))
>B : Symbol(B, Decl(genericFunctionInference1.ts, 2, 38))
>C : Symbol(C, Decl(genericFunctionInference1.ts, 2, 41))
>cd : Symbol(cd, Decl(genericFunctionInference1.ts, 2, 87))
>c : Symbol(c, Decl(genericFunctionInference1.ts, 2, 93))
>C : Symbol(C, Decl(genericFunctionInference1.ts, 2, 41))
>D : Symbol(D, Decl(genericFunctionInference1.ts, 2, 44))
>args : Symbol(args, Decl(genericFunctionInference1.ts, 2, 107))
>A : Symbol(A, Decl(genericFunctionInference1.ts, 2, 22))
>D : Symbol(D, Decl(genericFunctionInference1.ts, 2, 44))
declare function list<T>(a: T): T[];
>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 4, 22))
>a : Symbol(a, Decl(genericFunctionInference1.ts, 4, 25))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 4, 22))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 4, 22))
declare function box<V>(x: V): { value: V };
>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36))
>V : Symbol(V, Decl(genericFunctionInference1.ts, 5, 21))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 5, 24))
>V : Symbol(V, Decl(genericFunctionInference1.ts, 5, 21))
>value : Symbol(value, Decl(genericFunctionInference1.ts, 5, 32))
>V : Symbol(V, Decl(genericFunctionInference1.ts, 5, 21))
declare function foo<T extends { value: T }>(x: T): T;
>foo : Symbol(foo, Decl(genericFunctionInference1.ts, 5, 44))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 6, 21))
>value : Symbol(value, Decl(genericFunctionInference1.ts, 6, 32))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 6, 21))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 6, 45))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 6, 21))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 6, 21))
const f00 = pipe(list);
>f00 : Symbol(f00, Decl(genericFunctionInference1.ts, 8, 5))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124))
const f01 = pipe(list, box);
>f01 : Symbol(f01, Decl(genericFunctionInference1.ts, 9, 5))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124))
>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36))
const f02 = pipe(box, list);
>f02 : Symbol(f02, Decl(genericFunctionInference1.ts, 10, 5))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36))
>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124))
const f03 = pipe(x => list(x), box);
>f03 : Symbol(f03, Decl(genericFunctionInference1.ts, 11, 5))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 11, 17))
>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 11, 17))
>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36))
const f04 = pipe(list, x => box(x));
>f04 : Symbol(f04, Decl(genericFunctionInference1.ts, 12, 5))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 12, 22))
>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 12, 22))
const f05 = pipe(x => list(x), x => box(x))
>f05 : Symbol(f05, Decl(genericFunctionInference1.ts, 13, 5))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 13, 17))
>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 13, 17))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 13, 30))
>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 13, 30))
const f06 = pipe(list, pipe(box));
>f06 : Symbol(f06, Decl(genericFunctionInference1.ts, 14, 5))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36))
const f07 = pipe(x => list(x), pipe(box));
>f07 : Symbol(f07, Decl(genericFunctionInference1.ts, 15, 5))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 15, 17))
>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 15, 17))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36))
const f08 = pipe(x => list(x), pipe(x => box(x)));
>f08 : Symbol(f08, Decl(genericFunctionInference1.ts, 16, 5))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 16, 17))
>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 16, 17))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 16, 36))
>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 16, 36))
const f09 = pipe(list, x => x.length);
>f09 : Symbol(f09, Decl(genericFunctionInference1.ts, 17, 5))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 17, 22))
>x.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 17, 22))
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
const f10 = pipe(foo);
>f10 : Symbol(f10, Decl(genericFunctionInference1.ts, 18, 5))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
>foo : Symbol(foo, Decl(genericFunctionInference1.ts, 5, 44))
const f11 = pipe(foo, foo);
>f11 : Symbol(f11, Decl(genericFunctionInference1.ts, 19, 5))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
>foo : Symbol(foo, Decl(genericFunctionInference1.ts, 5, 44))
>foo : Symbol(foo, Decl(genericFunctionInference1.ts, 5, 44))
const g00: <T>(x: T) => T[] = pipe(list);
>g00 : Symbol(g00, Decl(genericFunctionInference1.ts, 21, 5))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 21, 12))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 21, 15))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 21, 12))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 21, 12))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124))
const g01: <T>(x: T) => { value: T[] } = pipe(list, box);
>g01 : Symbol(g01, Decl(genericFunctionInference1.ts, 22, 5))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 22, 12))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 22, 15))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 22, 12))
>value : Symbol(value, Decl(genericFunctionInference1.ts, 22, 25))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 22, 12))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124))
>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36))
const g02: <T>(x: T) => { value: T }[] = pipe(box, list);
>g02 : Symbol(g02, Decl(genericFunctionInference1.ts, 23, 5))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 23, 12))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 23, 15))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 23, 12))
>value : Symbol(value, Decl(genericFunctionInference1.ts, 23, 25))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 23, 12))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36))
>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124))
const g03: <T>(x: T) => { value: T[] } = pipe(x => list(x), box);
>g03 : Symbol(g03, Decl(genericFunctionInference1.ts, 24, 5))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 24, 12))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 24, 15))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 24, 12))
>value : Symbol(value, Decl(genericFunctionInference1.ts, 24, 25))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 24, 12))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 24, 46))
>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 24, 46))
>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36))
const g04: <T>(x: T) => { value: T[] } = pipe(list, x => box(x));
>g04 : Symbol(g04, Decl(genericFunctionInference1.ts, 25, 5))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 25, 12))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 25, 15))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 25, 12))
>value : Symbol(value, Decl(genericFunctionInference1.ts, 25, 25))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 25, 12))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 25, 51))
>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 25, 51))
const g05: <T>(x: T) => { value: T[] } = pipe(x => list(x), x => box(x))
>g05 : Symbol(g05, Decl(genericFunctionInference1.ts, 26, 5))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 26, 12))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 26, 15))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 26, 12))
>value : Symbol(value, Decl(genericFunctionInference1.ts, 26, 25))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 26, 12))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 26, 46))
>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 26, 46))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 26, 59))
>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 26, 59))
const g06: <T>(x: T) => { value: T[] } = pipe(list, pipe(box));
>g06 : Symbol(g06, Decl(genericFunctionInference1.ts, 27, 5))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 27, 12))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 27, 15))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 27, 12))
>value : Symbol(value, Decl(genericFunctionInference1.ts, 27, 25))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 27, 12))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36))
const g07: <T>(x: T) => { value: T[] } = pipe(x => list(x), pipe(box));
>g07 : Symbol(g07, Decl(genericFunctionInference1.ts, 28, 5))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 28, 12))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 28, 15))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 28, 12))
>value : Symbol(value, Decl(genericFunctionInference1.ts, 28, 25))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 28, 12))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 28, 46))
>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 28, 46))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36))
const g08: <T>(x: T) => { value: T[] } = pipe(x => list(x), pipe(x => box(x)));
>g08 : Symbol(g08, Decl(genericFunctionInference1.ts, 29, 5))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 29, 12))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 29, 15))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 29, 12))
>value : Symbol(value, Decl(genericFunctionInference1.ts, 29, 25))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 29, 12))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 29, 46))
>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 29, 46))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 29, 65))
>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 29, 65))
const g09: <T>(x: T) => number = pipe(list, x => x.length);
>g09 : Symbol(g09, Decl(genericFunctionInference1.ts, 30, 5))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 30, 12))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 30, 15))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 30, 12))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 30, 43))
>x.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 30, 43))
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
const g10: <T extends { value: T }>(x: T) => T = pipe(foo);
>g10 : Symbol(g10, Decl(genericFunctionInference1.ts, 31, 5))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 31, 12))
>value : Symbol(value, Decl(genericFunctionInference1.ts, 31, 23))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 31, 12))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 31, 36))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 31, 12))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 31, 12))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
>foo : Symbol(foo, Decl(genericFunctionInference1.ts, 5, 44))
const g12: <T extends { value: T }>(x: T) => T = pipe(foo, foo);
>g12 : Symbol(g12, Decl(genericFunctionInference1.ts, 32, 5))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 32, 12))
>value : Symbol(value, Decl(genericFunctionInference1.ts, 32, 23))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 32, 12))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 32, 36))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 32, 12))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 32, 12))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
>foo : Symbol(foo, Decl(genericFunctionInference1.ts, 5, 44))
>foo : Symbol(foo, Decl(genericFunctionInference1.ts, 5, 44))
declare function pipe2<A, B, C, D>(ab: (a: A) => B, cd: (c: C) => D): (a: [A, C]) => [B, D];
>pipe2 : Symbol(pipe2, Decl(genericFunctionInference1.ts, 32, 64))
>A : Symbol(A, Decl(genericFunctionInference1.ts, 34, 23))
>B : Symbol(B, Decl(genericFunctionInference1.ts, 34, 25))
>C : Symbol(C, Decl(genericFunctionInference1.ts, 34, 28))
>D : Symbol(D, Decl(genericFunctionInference1.ts, 34, 31))
>ab : Symbol(ab, Decl(genericFunctionInference1.ts, 34, 35))
>a : Symbol(a, Decl(genericFunctionInference1.ts, 34, 40))
>A : Symbol(A, Decl(genericFunctionInference1.ts, 34, 23))
>B : Symbol(B, Decl(genericFunctionInference1.ts, 34, 25))
>cd : Symbol(cd, Decl(genericFunctionInference1.ts, 34, 51))
>c : Symbol(c, Decl(genericFunctionInference1.ts, 34, 57))
>C : Symbol(C, Decl(genericFunctionInference1.ts, 34, 28))
>D : Symbol(D, Decl(genericFunctionInference1.ts, 34, 31))
>a : Symbol(a, Decl(genericFunctionInference1.ts, 34, 71))
>A : Symbol(A, Decl(genericFunctionInference1.ts, 34, 23))
>C : Symbol(C, Decl(genericFunctionInference1.ts, 34, 28))
>B : Symbol(B, Decl(genericFunctionInference1.ts, 34, 25))
>D : Symbol(D, Decl(genericFunctionInference1.ts, 34, 31))
const f20 = pipe2(list, box);
>f20 : Symbol(f20, Decl(genericFunctionInference1.ts, 36, 5))
>pipe2 : Symbol(pipe2, Decl(genericFunctionInference1.ts, 32, 64))
>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124))
>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36))
const f21 = pipe2(box, list);
>f21 : Symbol(f21, Decl(genericFunctionInference1.ts, 37, 5))
>pipe2 : Symbol(pipe2, Decl(genericFunctionInference1.ts, 32, 64))
>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36))
>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124))
const f22 = pipe2(list, list);
>f22 : Symbol(f22, Decl(genericFunctionInference1.ts, 38, 5))
>pipe2 : Symbol(pipe2, Decl(genericFunctionInference1.ts, 32, 64))
>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124))
>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124))
const f23 = pipe2(box, box);
>f23 : Symbol(f23, Decl(genericFunctionInference1.ts, 39, 5))
>pipe2 : Symbol(pipe2, Decl(genericFunctionInference1.ts, 32, 64))
>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36))
>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36))
const f24 = pipe2(f20, f20);
>f24 : Symbol(f24, Decl(genericFunctionInference1.ts, 40, 5))
>pipe2 : Symbol(pipe2, Decl(genericFunctionInference1.ts, 32, 64))
>f20 : Symbol(f20, Decl(genericFunctionInference1.ts, 36, 5))
>f20 : Symbol(f20, Decl(genericFunctionInference1.ts, 36, 5))
const f25 = pipe2(foo, foo);
>f25 : Symbol(f25, Decl(genericFunctionInference1.ts, 41, 5))
>pipe2 : Symbol(pipe2, Decl(genericFunctionInference1.ts, 32, 64))
>foo : Symbol(foo, Decl(genericFunctionInference1.ts, 5, 44))
>foo : Symbol(foo, Decl(genericFunctionInference1.ts, 5, 44))
const f26 = pipe2(f25, f25);
>f26 : Symbol(f26, Decl(genericFunctionInference1.ts, 42, 5))
>pipe2 : Symbol(pipe2, Decl(genericFunctionInference1.ts, 32, 64))
>f25 : Symbol(f25, Decl(genericFunctionInference1.ts, 41, 5))
>f25 : Symbol(f25, Decl(genericFunctionInference1.ts, 41, 5))
declare function pipe3<A, B, C>(ab: (a: A) => B, ac: (a: A) => C): (a: A) => [B, C];
>pipe3 : Symbol(pipe3, Decl(genericFunctionInference1.ts, 42, 28))
>A : Symbol(A, Decl(genericFunctionInference1.ts, 44, 23))
>B : Symbol(B, Decl(genericFunctionInference1.ts, 44, 25))
>C : Symbol(C, Decl(genericFunctionInference1.ts, 44, 28))
>ab : Symbol(ab, Decl(genericFunctionInference1.ts, 44, 32))
>a : Symbol(a, Decl(genericFunctionInference1.ts, 44, 37))
>A : Symbol(A, Decl(genericFunctionInference1.ts, 44, 23))
>B : Symbol(B, Decl(genericFunctionInference1.ts, 44, 25))
>ac : Symbol(ac, Decl(genericFunctionInference1.ts, 44, 48))
>a : Symbol(a, Decl(genericFunctionInference1.ts, 44, 54))
>A : Symbol(A, Decl(genericFunctionInference1.ts, 44, 23))
>C : Symbol(C, Decl(genericFunctionInference1.ts, 44, 28))
>a : Symbol(a, Decl(genericFunctionInference1.ts, 44, 68))
>A : Symbol(A, Decl(genericFunctionInference1.ts, 44, 23))
>B : Symbol(B, Decl(genericFunctionInference1.ts, 44, 25))
>C : Symbol(C, Decl(genericFunctionInference1.ts, 44, 28))
const f30 = pipe3(list, box);
>f30 : Symbol(f30, Decl(genericFunctionInference1.ts, 46, 5))
>pipe3 : Symbol(pipe3, Decl(genericFunctionInference1.ts, 42, 28))
>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124))
>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36))
const f31 = pipe3(box, list);
>f31 : Symbol(f31, Decl(genericFunctionInference1.ts, 47, 5))
>pipe3 : Symbol(pipe3, Decl(genericFunctionInference1.ts, 42, 28))
>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36))
>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124))
const f32 = pipe3(list, list);
>f32 : Symbol(f32, Decl(genericFunctionInference1.ts, 48, 5))
>pipe3 : Symbol(pipe3, Decl(genericFunctionInference1.ts, 42, 28))
>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124))
>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124))
declare function pipe4<A, B, C>(funcs: [(a: A) => B, (b: B) => C]): (a: A) => C;
>pipe4 : Symbol(pipe4, Decl(genericFunctionInference1.ts, 48, 30))
>A : Symbol(A, Decl(genericFunctionInference1.ts, 50, 23))
>B : Symbol(B, Decl(genericFunctionInference1.ts, 50, 25))
>C : Symbol(C, Decl(genericFunctionInference1.ts, 50, 28))
>funcs : Symbol(funcs, Decl(genericFunctionInference1.ts, 50, 32))
>a : Symbol(a, Decl(genericFunctionInference1.ts, 50, 41))
>A : Symbol(A, Decl(genericFunctionInference1.ts, 50, 23))
>B : Symbol(B, Decl(genericFunctionInference1.ts, 50, 25))
>b : Symbol(b, Decl(genericFunctionInference1.ts, 50, 54))
>B : Symbol(B, Decl(genericFunctionInference1.ts, 50, 25))
>C : Symbol(C, Decl(genericFunctionInference1.ts, 50, 28))
>a : Symbol(a, Decl(genericFunctionInference1.ts, 50, 69))
>A : Symbol(A, Decl(genericFunctionInference1.ts, 50, 23))
>C : Symbol(C, Decl(genericFunctionInference1.ts, 50, 28))
const f40 = pipe4([list, box]);
>f40 : Symbol(f40, Decl(genericFunctionInference1.ts, 52, 5))
>pipe4 : Symbol(pipe4, Decl(genericFunctionInference1.ts, 48, 30))
>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124))
>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36))
const f41 = pipe4([box, list]);
>f41 : Symbol(f41, Decl(genericFunctionInference1.ts, 53, 5))
>pipe4 : Symbol(pipe4, Decl(genericFunctionInference1.ts, 48, 30))
>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36))
>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124))
declare function pipe5<A, B>(f: (a: A) => B): { f: (a: A) => B };
>pipe5 : Symbol(pipe5, Decl(genericFunctionInference1.ts, 53, 31))
>A : Symbol(A, Decl(genericFunctionInference1.ts, 55, 23))
>B : Symbol(B, Decl(genericFunctionInference1.ts, 55, 25))
>f : Symbol(f, Decl(genericFunctionInference1.ts, 55, 29))
>a : Symbol(a, Decl(genericFunctionInference1.ts, 55, 33))
>A : Symbol(A, Decl(genericFunctionInference1.ts, 55, 23))
>B : Symbol(B, Decl(genericFunctionInference1.ts, 55, 25))
>f : Symbol(f, Decl(genericFunctionInference1.ts, 55, 47))
>a : Symbol(a, Decl(genericFunctionInference1.ts, 55, 52))
>A : Symbol(A, Decl(genericFunctionInference1.ts, 55, 23))
>B : Symbol(B, Decl(genericFunctionInference1.ts, 55, 25))
const f50 = pipe5(list); // No higher order inference
>f50 : Symbol(f50, Decl(genericFunctionInference1.ts, 57, 5))
>pipe5 : Symbol(pipe5, Decl(genericFunctionInference1.ts, 53, 31))
>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124))
// #417
function mirror<A, B>(f: (a: A) => B): (a: A) => B { return f; }
>mirror : Symbol(mirror, Decl(genericFunctionInference1.ts, 57, 24))
>A : Symbol(A, Decl(genericFunctionInference1.ts, 61, 16))
>B : Symbol(B, Decl(genericFunctionInference1.ts, 61, 18))
>f : Symbol(f, Decl(genericFunctionInference1.ts, 61, 22))
>a : Symbol(a, Decl(genericFunctionInference1.ts, 61, 26))
>A : Symbol(A, Decl(genericFunctionInference1.ts, 61, 16))
>B : Symbol(B, Decl(genericFunctionInference1.ts, 61, 18))
>a : Symbol(a, Decl(genericFunctionInference1.ts, 61, 40))
>A : Symbol(A, Decl(genericFunctionInference1.ts, 61, 16))
>B : Symbol(B, Decl(genericFunctionInference1.ts, 61, 18))
>f : Symbol(f, Decl(genericFunctionInference1.ts, 61, 22))
var identityM = mirror(identity);
>identityM : Symbol(identityM, Decl(genericFunctionInference1.ts, 62, 3))
>mirror : Symbol(mirror, Decl(genericFunctionInference1.ts, 57, 24))
>identity : Symbol(identity, Decl(genericFunctionInference1.ts, 154, 13))
var x = 1;
>x : Symbol(x, Decl(genericFunctionInference1.ts, 64, 3))
var y = identity(x);
>y : Symbol(y, Decl(genericFunctionInference1.ts, 65, 3))
>identity : Symbol(identity, Decl(genericFunctionInference1.ts, 154, 13))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 64, 3))
var z = identityM(x);
>z : Symbol(z, Decl(genericFunctionInference1.ts, 66, 3))
>identityM : Symbol(identityM, Decl(genericFunctionInference1.ts, 62, 3))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 64, 3))
// #3038
export function keyOf<a>(value: { key: a; }): a {
>keyOf : Symbol(keyOf, Decl(genericFunctionInference1.ts, 66, 21))
>a : Symbol(a, Decl(genericFunctionInference1.ts, 70, 22))
>value : Symbol(value, Decl(genericFunctionInference1.ts, 70, 25))
>key : Symbol(key, Decl(genericFunctionInference1.ts, 70, 33))
>a : Symbol(a, Decl(genericFunctionInference1.ts, 70, 22))
>a : Symbol(a, Decl(genericFunctionInference1.ts, 70, 22))
return value.key;
>value.key : Symbol(key, Decl(genericFunctionInference1.ts, 70, 33))
>value : Symbol(value, Decl(genericFunctionInference1.ts, 70, 25))
>key : Symbol(key, Decl(genericFunctionInference1.ts, 70, 33))
}
export interface Data {
>Data : Symbol(Data, Decl(genericFunctionInference1.ts, 72, 1))
key: number;
>key : Symbol(Data.key, Decl(genericFunctionInference1.ts, 73, 23))
value: Date;
>value : Symbol(Data.value, Decl(genericFunctionInference1.ts, 74, 16))
>Date : Symbol(Date, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.scripthost.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
}
var data: Data[] = [];
>data : Symbol(data, Decl(genericFunctionInference1.ts, 78, 3))
>Data : Symbol(Data, Decl(genericFunctionInference1.ts, 72, 1))
declare function toKeys<a>(values: a[], toKey: (value: a) => string): string[];
>toKeys : Symbol(toKeys, Decl(genericFunctionInference1.ts, 78, 22))
>a : Symbol(a, Decl(genericFunctionInference1.ts, 80, 24))
>values : Symbol(values, Decl(genericFunctionInference1.ts, 80, 27))
>a : Symbol(a, Decl(genericFunctionInference1.ts, 80, 24))
>toKey : Symbol(toKey, Decl(genericFunctionInference1.ts, 80, 39))
>value : Symbol(value, Decl(genericFunctionInference1.ts, 80, 48))
>a : Symbol(a, Decl(genericFunctionInference1.ts, 80, 24))
toKeys(data, keyOf); // Error
>toKeys : Symbol(toKeys, Decl(genericFunctionInference1.ts, 78, 22))
>data : Symbol(data, Decl(genericFunctionInference1.ts, 78, 3))
>keyOf : Symbol(keyOf, Decl(genericFunctionInference1.ts, 66, 21))
// #9366
function flip<a, b, c>(f: (a: a, b: b) => c): (b: b, a: a) => c {
>flip : Symbol(flip, Decl(genericFunctionInference1.ts, 82, 20))
>a : Symbol(a, Decl(genericFunctionInference1.ts, 86, 14))
>b : Symbol(b, Decl(genericFunctionInference1.ts, 86, 16))
>c : Symbol(c, Decl(genericFunctionInference1.ts, 86, 19))
>f : Symbol(f, Decl(genericFunctionInference1.ts, 86, 23))
>a : Symbol(a, Decl(genericFunctionInference1.ts, 86, 27))
>a : Symbol(a, Decl(genericFunctionInference1.ts, 86, 14))
>b : Symbol(b, Decl(genericFunctionInference1.ts, 86, 32))
>b : Symbol(b, Decl(genericFunctionInference1.ts, 86, 16))
>c : Symbol(c, Decl(genericFunctionInference1.ts, 86, 19))
>b : Symbol(b, Decl(genericFunctionInference1.ts, 86, 47))
>b : Symbol(b, Decl(genericFunctionInference1.ts, 86, 16))
>a : Symbol(a, Decl(genericFunctionInference1.ts, 86, 52))
>a : Symbol(a, Decl(genericFunctionInference1.ts, 86, 14))
>c : Symbol(c, Decl(genericFunctionInference1.ts, 86, 19))
return (b: b, a: a) => f(a, b);
>b : Symbol(b, Decl(genericFunctionInference1.ts, 87, 10))
>b : Symbol(b, Decl(genericFunctionInference1.ts, 86, 16))
>a : Symbol(a, Decl(genericFunctionInference1.ts, 87, 15))
>a : Symbol(a, Decl(genericFunctionInference1.ts, 86, 14))
>f : Symbol(f, Decl(genericFunctionInference1.ts, 86, 23))
>a : Symbol(a, Decl(genericFunctionInference1.ts, 87, 15))
>b : Symbol(b, Decl(genericFunctionInference1.ts, 87, 10))
}
function zip<T, U>(x: T, y: U): [T, U] {
>zip : Symbol(zip, Decl(genericFunctionInference1.ts, 88, 1))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 89, 13))
>U : Symbol(U, Decl(genericFunctionInference1.ts, 89, 15))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 89, 19))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 89, 13))
>y : Symbol(y, Decl(genericFunctionInference1.ts, 89, 24))
>U : Symbol(U, Decl(genericFunctionInference1.ts, 89, 15))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 89, 13))
>U : Symbol(U, Decl(genericFunctionInference1.ts, 89, 15))
return [x, y];
>x : Symbol(x, Decl(genericFunctionInference1.ts, 89, 19))
>y : Symbol(y, Decl(genericFunctionInference1.ts, 89, 24))
}
var expected: <T, U>(y: U, x: T) => [T, U] = flip(zip);
>expected : Symbol(expected, Decl(genericFunctionInference1.ts, 93, 3))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 93, 15))
>U : Symbol(U, Decl(genericFunctionInference1.ts, 93, 17))
>y : Symbol(y, Decl(genericFunctionInference1.ts, 93, 21))
>U : Symbol(U, Decl(genericFunctionInference1.ts, 93, 17))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 93, 26))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 93, 15))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 93, 15))
>U : Symbol(U, Decl(genericFunctionInference1.ts, 93, 17))
>flip : Symbol(flip, Decl(genericFunctionInference1.ts, 82, 20))
>zip : Symbol(zip, Decl(genericFunctionInference1.ts, 88, 1))
var actual = flip(zip);
>actual : Symbol(actual, Decl(genericFunctionInference1.ts, 94, 3))
>flip : Symbol(flip, Decl(genericFunctionInference1.ts, 82, 20))
>zip : Symbol(zip, Decl(genericFunctionInference1.ts, 88, 1))
// #9366
const map = <T, U>(transform: (t: T) => U) =>
>map : Symbol(map, Decl(genericFunctionInference1.ts, 98, 5))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 98, 13))
>U : Symbol(U, Decl(genericFunctionInference1.ts, 98, 15))
>transform : Symbol(transform, Decl(genericFunctionInference1.ts, 98, 19))
>t : Symbol(t, Decl(genericFunctionInference1.ts, 98, 31))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 98, 13))
>U : Symbol(U, Decl(genericFunctionInference1.ts, 98, 15))
(arr: T[]) => arr.map(transform)
>arr : Symbol(arr, Decl(genericFunctionInference1.ts, 99, 5))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 98, 13))
>arr.map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --))
>arr : Symbol(arr, Decl(genericFunctionInference1.ts, 99, 5))
>map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --))
>transform : Symbol(transform, Decl(genericFunctionInference1.ts, 98, 19))
const identityStr = (t: string) => t;
>identityStr : Symbol(identityStr, Decl(genericFunctionInference1.ts, 101, 5))
>t : Symbol(t, Decl(genericFunctionInference1.ts, 101, 21))
>t : Symbol(t, Decl(genericFunctionInference1.ts, 101, 21))
const arr: string[] = map(identityStr)(['a']);
>arr : Symbol(arr, Decl(genericFunctionInference1.ts, 103, 5))
>map : Symbol(map, Decl(genericFunctionInference1.ts, 98, 5))
>identityStr : Symbol(identityStr, Decl(genericFunctionInference1.ts, 101, 5))
const arr1: string[] = map(identity)(['a']);
>arr1 : Symbol(arr1, Decl(genericFunctionInference1.ts, 104, 5))
>map : Symbol(map, Decl(genericFunctionInference1.ts, 98, 5))
>identity : Symbol(identity, Decl(genericFunctionInference1.ts, 154, 13))
// #9949
function of2<a, b>(one: a, two: b): [a, b] {
>of2 : Symbol(of2, Decl(genericFunctionInference1.ts, 104, 44))
>a : Symbol(a, Decl(genericFunctionInference1.ts, 108, 13))
>b : Symbol(b, Decl(genericFunctionInference1.ts, 108, 15))
>one : Symbol(one, Decl(genericFunctionInference1.ts, 108, 19))
>a : Symbol(a, Decl(genericFunctionInference1.ts, 108, 13))
>two : Symbol(two, Decl(genericFunctionInference1.ts, 108, 26))
>b : Symbol(b, Decl(genericFunctionInference1.ts, 108, 15))
>a : Symbol(a, Decl(genericFunctionInference1.ts, 108, 13))
>b : Symbol(b, Decl(genericFunctionInference1.ts, 108, 15))
return [one, two];
>one : Symbol(one, Decl(genericFunctionInference1.ts, 108, 19))
>two : Symbol(two, Decl(genericFunctionInference1.ts, 108, 26))
}
const flipped = flip(of2);
>flipped : Symbol(flipped, Decl(genericFunctionInference1.ts, 112, 5))
>flip : Symbol(flip, Decl(genericFunctionInference1.ts, 82, 20))
>of2 : Symbol(of2, Decl(genericFunctionInference1.ts, 104, 44))
// #29904.1
type Component<P> = (props: P) => {};
>Component : Symbol(Component, Decl(genericFunctionInference1.ts, 112, 26))
>P : Symbol(P, Decl(genericFunctionInference1.ts, 116, 15))
>props : Symbol(props, Decl(genericFunctionInference1.ts, 116, 21))
>P : Symbol(P, Decl(genericFunctionInference1.ts, 116, 15))
declare const myHoc1: <P>(C: Component<P>) => Component<P>;
>myHoc1 : Symbol(myHoc1, Decl(genericFunctionInference1.ts, 118, 13))
>P : Symbol(P, Decl(genericFunctionInference1.ts, 118, 23))
>C : Symbol(C, Decl(genericFunctionInference1.ts, 118, 26))
>Component : Symbol(Component, Decl(genericFunctionInference1.ts, 112, 26))
>P : Symbol(P, Decl(genericFunctionInference1.ts, 118, 23))
>Component : Symbol(Component, Decl(genericFunctionInference1.ts, 112, 26))
>P : Symbol(P, Decl(genericFunctionInference1.ts, 118, 23))
declare const myHoc2: <P>(C: Component<P>) => Component<P>;
>myHoc2 : Symbol(myHoc2, Decl(genericFunctionInference1.ts, 119, 13))
>P : Symbol(P, Decl(genericFunctionInference1.ts, 119, 23))
>C : Symbol(C, Decl(genericFunctionInference1.ts, 119, 26))
>Component : Symbol(Component, Decl(genericFunctionInference1.ts, 112, 26))
>P : Symbol(P, Decl(genericFunctionInference1.ts, 119, 23))
>Component : Symbol(Component, Decl(genericFunctionInference1.ts, 112, 26))
>P : Symbol(P, Decl(genericFunctionInference1.ts, 119, 23))
declare const MyComponent1: Component<{ foo: 1 }>;
>MyComponent1 : Symbol(MyComponent1, Decl(genericFunctionInference1.ts, 121, 13))
>Component : Symbol(Component, Decl(genericFunctionInference1.ts, 112, 26))
>foo : Symbol(foo, Decl(genericFunctionInference1.ts, 121, 39))
const enhance = pipe(
>enhance : Symbol(enhance, Decl(genericFunctionInference1.ts, 123, 5))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
myHoc1,
>myHoc1 : Symbol(myHoc1, Decl(genericFunctionInference1.ts, 118, 13))
myHoc2,
>myHoc2 : Symbol(myHoc2, Decl(genericFunctionInference1.ts, 119, 13))
);
const MyComponent2 = enhance(MyComponent1);
>MyComponent2 : Symbol(MyComponent2, Decl(genericFunctionInference1.ts, 128, 5))
>enhance : Symbol(enhance, Decl(genericFunctionInference1.ts, 123, 5))
>MyComponent1 : Symbol(MyComponent1, Decl(genericFunctionInference1.ts, 121, 13))
// #29904.2
const fn20 = pipe((_a?: {}) => 1);
>fn20 : Symbol(fn20, Decl(genericFunctionInference1.ts, 132, 5))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
>_a : Symbol(_a, Decl(genericFunctionInference1.ts, 132, 19))
// #29904.3
type Fn = (n: number) => number;
>Fn : Symbol(Fn, Decl(genericFunctionInference1.ts, 132, 34))
>n : Symbol(n, Decl(genericFunctionInference1.ts, 136, 11))
const fn30: Fn = pipe(
>fn30 : Symbol(fn30, Decl(genericFunctionInference1.ts, 137, 5))
>Fn : Symbol(Fn, Decl(genericFunctionInference1.ts, 132, 34))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
x => x + 1,
>x : Symbol(x, Decl(genericFunctionInference1.ts, 137, 22))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 137, 22))
x => x * 2,
>x : Symbol(x, Decl(genericFunctionInference1.ts, 138, 15))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 138, 15))
);
const promise = Promise.resolve(1);
>promise : Symbol(promise, Decl(genericFunctionInference1.ts, 142, 5))
>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
promise.then(
>promise.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --))
>promise : Symbol(promise, Decl(genericFunctionInference1.ts, 142, 5))
>then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --))
pipe(
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
x => x + 1,
>x : Symbol(x, Decl(genericFunctionInference1.ts, 144, 9))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 144, 9))
x => x * 2,
>x : Symbol(x, Decl(genericFunctionInference1.ts, 145, 19))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 145, 19))
),
);
// #29904.4
declare const getString: () => string;
>getString : Symbol(getString, Decl(genericFunctionInference1.ts, 152, 13))
declare const orUndefined: (name: string) => string | undefined;
>orUndefined : Symbol(orUndefined, Decl(genericFunctionInference1.ts, 153, 13))
>name : Symbol(name, Decl(genericFunctionInference1.ts, 153, 28))
declare const identity: <T>(value: T) => T;
>identity : Symbol(identity, Decl(genericFunctionInference1.ts, 154, 13))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 154, 25))
>value : Symbol(value, Decl(genericFunctionInference1.ts, 154, 28))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 154, 25))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 154, 25))
const fn40 = pipe(
>fn40 : Symbol(fn40, Decl(genericFunctionInference1.ts, 156, 5))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
getString,
>getString : Symbol(getString, Decl(genericFunctionInference1.ts, 152, 13))
string => orUndefined(string),
>string : Symbol(string, Decl(genericFunctionInference1.ts, 157, 14))
>orUndefined : Symbol(orUndefined, Decl(genericFunctionInference1.ts, 153, 13))
>string : Symbol(string, Decl(genericFunctionInference1.ts, 157, 14))
identity,
>identity : Symbol(identity, Decl(genericFunctionInference1.ts, 154, 13))
);
// #29904.6
declare const getArray: () => string[];
>getArray : Symbol(getArray, Decl(genericFunctionInference1.ts, 164, 13))
declare const first: <T>(ts: T[]) => T;
>first : Symbol(first, Decl(genericFunctionInference1.ts, 165, 13))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 165, 22))
>ts : Symbol(ts, Decl(genericFunctionInference1.ts, 165, 25))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 165, 22))
>T : Symbol(T, Decl(genericFunctionInference1.ts, 165, 22))
const fn60 = pipe(
>fn60 : Symbol(fn60, Decl(genericFunctionInference1.ts, 167, 5))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
getArray,
>getArray : Symbol(getArray, Decl(genericFunctionInference1.ts, 164, 13))
x => x,
>x : Symbol(x, Decl(genericFunctionInference1.ts, 168, 13))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 168, 13))
first,
>first : Symbol(first, Decl(genericFunctionInference1.ts, 165, 13))
);
const fn61 = pipe(
>fn61 : Symbol(fn61, Decl(genericFunctionInference1.ts, 173, 5))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
getArray,
>getArray : Symbol(getArray, Decl(genericFunctionInference1.ts, 164, 13))
identity,
>identity : Symbol(identity, Decl(genericFunctionInference1.ts, 154, 13))
first,
>first : Symbol(first, Decl(genericFunctionInference1.ts, 165, 13))
);
const fn62 = pipe(
>fn62 : Symbol(fn62, Decl(genericFunctionInference1.ts, 179, 5))
>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104))
getArray,
>getArray : Symbol(getArray, Decl(genericFunctionInference1.ts, 164, 13))
x => x,
>x : Symbol(x, Decl(genericFunctionInference1.ts, 180, 13))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 180, 13))
x => first(x),
>x : Symbol(x, Decl(genericFunctionInference1.ts, 181, 11))
>first : Symbol(first, Decl(genericFunctionInference1.ts, 165, 13))
>x : Symbol(x, Decl(genericFunctionInference1.ts, 181, 11))
);
@@ -0,0 +1,801 @@
=== tests/cases/compiler/genericFunctionInference1.ts ===
declare function pipe<A extends any[], B>(ab: (...args: A) => B): (...args: A) => B;
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
>ab : (...args: A) => B
>args : A
>args : A
declare function pipe<A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C;
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
>ab : (...args: A) => B
>args : A
>bc : (b: B) => C
>b : B
>args : A
declare function pipe<A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D;
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
>ab : (...args: A) => B
>args : A
>bc : (b: B) => C
>b : B
>cd : (c: C) => D
>c : C
>args : A
declare function list<T>(a: T): T[];
>list : <T>(a: T) => T[]
>a : T
declare function box<V>(x: V): { value: V };
>box : <V>(x: V) => { value: V; }
>x : V
>value : V
declare function foo<T extends { value: T }>(x: T): T;
>foo : <T extends { value: T; }>(x: T) => T
>value : T
>x : T
const f00 = pipe(list);
>f00 : <T>(a: T) => T[]
>pipe(list) : <T>(a: T) => T[]
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
>list : <T>(a: T) => T[]
const f01 = pipe(list, box);
>f01 : <T>(a: T) => { value: T[]; }
>pipe(list, box) : <T>(a: T) => { value: T[]; }
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
>list : <T>(a: T) => T[]
>box : <V>(x: V) => { value: V; }
const f02 = pipe(box, list);
>f02 : <V>(x: V) => { value: V; }[]
>pipe(box, list) : <V>(x: V) => { value: V; }[]
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
>box : <V>(x: V) => { value: V; }
>list : <T>(a: T) => T[]
const f03 = pipe(x => list(x), box);
>f03 : (x: any) => { value: any[]; }
>pipe(x => list(x), box) : (x: any) => { value: any[]; }
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
>x => list(x) : (x: any) => any[]
>x : any
>list(x) : any[]
>list : <T>(a: T) => T[]
>x : any
>box : <V>(x: V) => { value: V; }
const f04 = pipe(list, x => box(x));
>f04 : <T>(a: T) => { value: T[]; }
>pipe(list, x => box(x)) : <T>(a: T) => { value: T[]; }
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
>list : <T>(a: T) => T[]
>x => box(x) : (x: T[]) => { value: T[]; }
>x : T[]
>box(x) : { value: T[]; }
>box : <V>(x: V) => { value: V; }
>x : T[]
const f05 = pipe(x => list(x), x => box(x))
>f05 : (x: any) => { value: any[]; }
>pipe(x => list(x), x => box(x)) : (x: any) => { value: any[]; }
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
>x => list(x) : (x: any) => any[]
>x : any
>list(x) : any[]
>list : <T>(a: T) => T[]
>x : any
>x => box(x) : (x: any[]) => { value: any[]; }
>x : any[]
>box(x) : { value: any[]; }
>box : <V>(x: V) => { value: V; }
>x : any[]
const f06 = pipe(list, pipe(box));
>f06 : <T>(a: T) => { value: T[]; }
>pipe(list, pipe(box)) : <T>(a: T) => { value: T[]; }
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
>list : <T>(a: T) => T[]
>pipe(box) : (x: T[]) => { value: T[]; }
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
>box : <V>(x: V) => { value: V; }
const f07 = pipe(x => list(x), pipe(box));
>f07 : (x: any) => { value: any[]; }
>pipe(x => list(x), pipe(box)) : (x: any) => { value: any[]; }
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
>x => list(x) : (x: any) => any[]
>x : any
>list(x) : any[]
>list : <T>(a: T) => T[]
>x : any
>pipe(box) : (x: any[]) => { value: any[]; }
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
>box : <V>(x: V) => { value: V; }
const f08 = pipe(x => list(x), pipe(x => box(x)));
>f08 : (x: any) => { value: any[]; }
>pipe(x => list(x), pipe(x => box(x))) : (x: any) => { value: any[]; }
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
>x => list(x) : (x: any) => any[]
>x : any
>list(x) : any[]
>list : <T>(a: T) => T[]
>x : any
>pipe(x => box(x)) : (x: any[]) => { value: any[]; }
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
>x => box(x) : (x: any[]) => { value: any[]; }
>x : any[]
>box(x) : { value: any[]; }
>box : <V>(x: V) => { value: V; }
>x : any[]
const f09 = pipe(list, x => x.length);
>f09 : <T>(a: T) => number
>pipe(list, x => x.length) : <T>(a: T) => number
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
>list : <T>(a: T) => T[]
>x => x.length : (x: T[]) => number
>x : T[]
>x.length : number
>x : T[]
>length : number
const f10 = pipe(foo);
>f10 : <T extends { value: T; }>(x: T) => T
>pipe(foo) : <T extends { value: T; }>(x: T) => T
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
>foo : <T extends { value: T; }>(x: T) => T
const f11 = pipe(foo, foo);
>f11 : <T extends { value: T; }>(x: T) => T
>pipe(foo, foo) : <T extends { value: T; }>(x: T) => T
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
>foo : <T extends { value: T; }>(x: T) => T
>foo : <T extends { value: T; }>(x: T) => T
const g00: <T>(x: T) => T[] = pipe(list);
>g00 : <T>(x: T) => T[]
>x : T
>pipe(list) : (a: T) => T[]
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
>list : <T>(a: T) => T[]
const g01: <T>(x: T) => { value: T[] } = pipe(list, box);
>g01 : <T>(x: T) => { value: T[]; }
>x : T
>value : T[]
>pipe(list, box) : (a: T) => { value: T[]; }
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
>list : <T>(a: T) => T[]
>box : <V>(x: V) => { value: V; }
const g02: <T>(x: T) => { value: T }[] = pipe(box, list);
>g02 : <T>(x: T) => { value: T; }[]
>x : T
>value : T
>pipe(box, list) : (x: T) => { value: T; }[]
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
>box : <V>(x: V) => { value: V; }
>list : <T>(a: T) => T[]
const g03: <T>(x: T) => { value: T[] } = pipe(x => list(x), box);
>g03 : <T>(x: T) => { value: T[]; }
>x : T
>value : T[]
>pipe(x => list(x), box) : (x: T) => { value: T[]; }
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
>x => list(x) : (x: T) => T[]
>x : T
>list(x) : T[]
>list : <T>(a: T) => T[]
>x : T
>box : <V>(x: V) => { value: V; }
const g04: <T>(x: T) => { value: T[] } = pipe(list, x => box(x));
>g04 : <T>(x: T) => { value: T[]; }
>x : T
>value : T[]
>pipe(list, x => box(x)) : (a: T) => { value: T[]; }
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
>list : <T>(a: T) => T[]
>x => box(x) : (x: T[]) => { value: T[]; }
>x : T[]
>box(x) : { value: T[]; }
>box : <V>(x: V) => { value: V; }
>x : T[]
const g05: <T>(x: T) => { value: T[] } = pipe(x => list(x), x => box(x))
>g05 : <T>(x: T) => { value: T[]; }
>x : T
>value : T[]
>pipe(x => list(x), x => box(x)) : (x: T) => { value: T[]; }
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
>x => list(x) : (x: T) => T[]
>x : T
>list(x) : T[]
>list : <T>(a: T) => T[]
>x : T
>x => box(x) : (x: T[]) => { value: T[]; }
>x : T[]
>box(x) : { value: T[]; }
>box : <V>(x: V) => { value: V; }
>x : T[]
const g06: <T>(x: T) => { value: T[] } = pipe(list, pipe(box));
>g06 : <T>(x: T) => { value: T[]; }
>x : T
>value : T[]
>pipe(list, pipe(box)) : (a: T) => { value: T[]; }
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
>list : <T>(a: T) => T[]
>pipe(box) : (x: T[]) => { value: T[]; }
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
>box : <V>(x: V) => { value: V; }
const g07: <T>(x: T) => { value: T[] } = pipe(x => list(x), pipe(box));
>g07 : <T>(x: T) => { value: T[]; }
>x : T
>value : T[]
>pipe(x => list(x), pipe(box)) : (x: T) => { value: T[]; }
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
>x => list(x) : (x: T) => T[]
>x : T
>list(x) : T[]
>list : <T>(a: T) => T[]
>x : T
>pipe(box) : (x: T[]) => { value: T[]; }
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
>box : <V>(x: V) => { value: V; }
const g08: <T>(x: T) => { value: T[] } = pipe(x => list(x), pipe(x => box(x)));
>g08 : <T>(x: T) => { value: T[]; }
>x : T
>value : T[]
>pipe(x => list(x), pipe(x => box(x))) : (x: T) => { value: T[]; }
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
>x => list(x) : (x: T) => T[]
>x : T
>list(x) : T[]
>list : <T>(a: T) => T[]
>x : T
>pipe(x => box(x)) : (x: T[]) => { value: T[]; }
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
>x => box(x) : (x: T[]) => { value: T[]; }
>x : T[]
>box(x) : { value: T[]; }
>box : <V>(x: V) => { value: V; }
>x : T[]
const g09: <T>(x: T) => number = pipe(list, x => x.length);
>g09 : <T>(x: T) => number
>x : T
>pipe(list, x => x.length) : (a: T) => number
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
>list : <T>(a: T) => T[]
>x => x.length : (x: T[]) => number
>x : T[]
>x.length : number
>x : T[]
>length : number
const g10: <T extends { value: T }>(x: T) => T = pipe(foo);
>g10 : <T extends { value: T; }>(x: T) => T
>value : T
>x : T
>pipe(foo) : (x: T) => T
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
>foo : <T extends { value: T; }>(x: T) => T
const g12: <T extends { value: T }>(x: T) => T = pipe(foo, foo);
>g12 : <T extends { value: T; }>(x: T) => T
>value : T
>x : T
>pipe(foo, foo) : (x: T) => T
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
>foo : <T extends { value: T; }>(x: T) => T
>foo : <T extends { value: T; }>(x: T) => T
declare function pipe2<A, B, C, D>(ab: (a: A) => B, cd: (c: C) => D): (a: [A, C]) => [B, D];
>pipe2 : <A, B, C, D>(ab: (a: A) => B, cd: (c: C) => D) => (a: [A, C]) => [B, D]
>ab : (a: A) => B
>a : A
>cd : (c: C) => D
>c : C
>a : [A, C]
const f20 = pipe2(list, box);
>f20 : <T, V>(a: [T, V]) => [T[], { value: V; }]
>pipe2(list, box) : <T, V>(a: [T, V]) => [T[], { value: V; }]
>pipe2 : <A, B, C, D>(ab: (a: A) => B, cd: (c: C) => D) => (a: [A, C]) => [B, D]
>list : <T>(a: T) => T[]
>box : <V>(x: V) => { value: V; }
const f21 = pipe2(box, list);
>f21 : <V, T>(a: [V, T]) => [{ value: V; }, T[]]
>pipe2(box, list) : <V, T>(a: [V, T]) => [{ value: V; }, T[]]
>pipe2 : <A, B, C, D>(ab: (a: A) => B, cd: (c: C) => D) => (a: [A, C]) => [B, D]
>box : <V>(x: V) => { value: V; }
>list : <T>(a: T) => T[]
const f22 = pipe2(list, list);
>f22 : <T, T1>(a: [T, T1]) => [T[], T1[]]
>pipe2(list, list) : <T, T1>(a: [T, T1]) => [T[], T1[]]
>pipe2 : <A, B, C, D>(ab: (a: A) => B, cd: (c: C) => D) => (a: [A, C]) => [B, D]
>list : <T>(a: T) => T[]
>list : <T>(a: T) => T[]
const f23 = pipe2(box, box);
>f23 : <V, V1>(a: [V, V1]) => [{ value: V; }, { value: V1; }]
>pipe2(box, box) : <V, V1>(a: [V, V1]) => [{ value: V; }, { value: V1; }]
>pipe2 : <A, B, C, D>(ab: (a: A) => B, cd: (c: C) => D) => (a: [A, C]) => [B, D]
>box : <V>(x: V) => { value: V; }
>box : <V>(x: V) => { value: V; }
const f24 = pipe2(f20, f20);
>f24 : <T, V, T1, V1>(a: [[T, V], [T1, V1]]) => [[T[], { value: V; }], [T1[], { value: V1; }]]
>pipe2(f20, f20) : <T, V, T1, V1>(a: [[T, V], [T1, V1]]) => [[T[], { value: V; }], [T1[], { value: V1; }]]
>pipe2 : <A, B, C, D>(ab: (a: A) => B, cd: (c: C) => D) => (a: [A, C]) => [B, D]
>f20 : <T, V>(a: [T, V]) => [T[], { value: V; }]
>f20 : <T, V>(a: [T, V]) => [T[], { value: V; }]
const f25 = pipe2(foo, foo);
>f25 : <T extends { value: T; }, T1 extends { value: T1; }>(a: [T, T1]) => [T, T1]
>pipe2(foo, foo) : <T extends { value: T; }, T1 extends { value: T1; }>(a: [T, T1]) => [T, T1]
>pipe2 : <A, B, C, D>(ab: (a: A) => B, cd: (c: C) => D) => (a: [A, C]) => [B, D]
>foo : <T extends { value: T; }>(x: T) => T
>foo : <T extends { value: T; }>(x: T) => T
const f26 = pipe2(f25, f25);
>f26 : <T extends { value: T; }, T1 extends { value: T1; }, T2 extends { value: T2; }, T3 extends { value: T3; }>(a: [[T, T1], [T2, T3]]) => [[T, T1], [T2, T3]]
>pipe2(f25, f25) : <T extends { value: T; }, T1 extends { value: T1; }, T2 extends { value: T2; }, T3 extends { value: T3; }>(a: [[T, T1], [T2, T3]]) => [[T, T1], [T2, T3]]
>pipe2 : <A, B, C, D>(ab: (a: A) => B, cd: (c: C) => D) => (a: [A, C]) => [B, D]
>f25 : <T extends { value: T; }, T1 extends { value: T1; }>(a: [T, T1]) => [T, T1]
>f25 : <T extends { value: T; }, T1 extends { value: T1; }>(a: [T, T1]) => [T, T1]
declare function pipe3<A, B, C>(ab: (a: A) => B, ac: (a: A) => C): (a: A) => [B, C];
>pipe3 : <A, B, C>(ab: (a: A) => B, ac: (a: A) => C) => (a: A) => [B, C]
>ab : (a: A) => B
>a : A
>ac : (a: A) => C
>a : A
>a : A
const f30 = pipe3(list, box);
>f30 : <T>(a: T) => [T[], { value: T; }]
>pipe3(list, box) : <T>(a: T) => [T[], { value: T; }]
>pipe3 : <A, B, C>(ab: (a: A) => B, ac: (a: A) => C) => (a: A) => [B, C]
>list : <T>(a: T) => T[]
>box : <V>(x: V) => { value: V; }
const f31 = pipe3(box, list);
>f31 : <V>(a: V) => [{ value: V; }, V[]]
>pipe3(box, list) : <V>(a: V) => [{ value: V; }, V[]]
>pipe3 : <A, B, C>(ab: (a: A) => B, ac: (a: A) => C) => (a: A) => [B, C]
>box : <V>(x: V) => { value: V; }
>list : <T>(a: T) => T[]
const f32 = pipe3(list, list);
>f32 : <T>(a: T) => [T[], T[]]
>pipe3(list, list) : <T>(a: T) => [T[], T[]]
>pipe3 : <A, B, C>(ab: (a: A) => B, ac: (a: A) => C) => (a: A) => [B, C]
>list : <T>(a: T) => T[]
>list : <T>(a: T) => T[]
declare function pipe4<A, B, C>(funcs: [(a: A) => B, (b: B) => C]): (a: A) => C;
>pipe4 : <A, B, C>(funcs: [(a: A) => B, (b: B) => C]) => (a: A) => C
>funcs : [(a: A) => B, (b: B) => C]
>a : A
>b : B
>a : A
const f40 = pipe4([list, box]);
>f40 : <T>(a: T) => { value: T[]; }
>pipe4([list, box]) : <T>(a: T) => { value: T[]; }
>pipe4 : <A, B, C>(funcs: [(a: A) => B, (b: B) => C]) => (a: A) => C
>[list, box] : [<T>(a: T) => T[], <V>(x: V) => { value: V; }]
>list : <T>(a: T) => T[]
>box : <V>(x: V) => { value: V; }
const f41 = pipe4([box, list]);
>f41 : <V>(a: V) => { value: V; }[]
>pipe4([box, list]) : <V>(a: V) => { value: V; }[]
>pipe4 : <A, B, C>(funcs: [(a: A) => B, (b: B) => C]) => (a: A) => C
>[box, list] : [<V>(x: V) => { value: V; }, <T>(a: T) => T[]]
>box : <V>(x: V) => { value: V; }
>list : <T>(a: T) => T[]
declare function pipe5<A, B>(f: (a: A) => B): { f: (a: A) => B };
>pipe5 : <A, B>(f: (a: A) => B) => { f: (a: A) => B; }
>f : (a: A) => B
>a : A
>f : (a: A) => B
>a : A
const f50 = pipe5(list); // No higher order inference
>f50 : { f: (a: {}) => {}[]; }
>pipe5(list) : { f: (a: {}) => {}[]; }
>pipe5 : <A, B>(f: (a: A) => B) => { f: (a: A) => B; }
>list : <T>(a: T) => T[]
// #417
function mirror<A, B>(f: (a: A) => B): (a: A) => B { return f; }
>mirror : <A, B>(f: (a: A) => B) => (a: A) => B
>f : (a: A) => B
>a : A
>a : A
>f : (a: A) => B
var identityM = mirror(identity);
>identityM : <T>(a: T) => T
>mirror(identity) : <T>(a: T) => T
>mirror : <A, B>(f: (a: A) => B) => (a: A) => B
>identity : <T>(value: T) => T
var x = 1;
>x : number
>1 : 1
var y = identity(x);
>y : number
>identity(x) : number
>identity : <T>(value: T) => T
>x : number
var z = identityM(x);
>z : number
>identityM(x) : number
>identityM : <T>(a: T) => T
>x : number
// #3038
export function keyOf<a>(value: { key: a; }): a {
>keyOf : <a>(value: { key: a; }) => a
>value : { key: a; }
>key : a
return value.key;
>value.key : a
>value : { key: a; }
>key : a
}
export interface Data {
key: number;
>key : number
value: Date;
>value : Date
}
var data: Data[] = [];
>data : Data[]
>[] : never[]
declare function toKeys<a>(values: a[], toKey: (value: a) => string): string[];
>toKeys : <a>(values: a[], toKey: (value: a) => string) => string[]
>values : a[]
>toKey : (value: a) => string
>value : a
toKeys(data, keyOf); // Error
>toKeys(data, keyOf) : any
>toKeys : <a>(values: a[], toKey: (value: a) => string) => string[]
>data : Data[]
>keyOf : <a>(value: { key: a; }) => a
// #9366
function flip<a, b, c>(f: (a: a, b: b) => c): (b: b, a: a) => c {
>flip : <a, b, c>(f: (a: a, b: b) => c) => (b: b, a: a) => c
>f : (a: a, b: b) => c
>a : a
>b : b
>b : b
>a : a
return (b: b, a: a) => f(a, b);
>(b: b, a: a) => f(a, b) : (b: b, a: a) => c
>b : b
>a : a
>f(a, b) : c
>f : (a: a, b: b) => c
>a : a
>b : b
}
function zip<T, U>(x: T, y: U): [T, U] {
>zip : <T, U>(x: T, y: U) => [T, U]
>x : T
>y : U
return [x, y];
>[x, y] : [T, U]
>x : T
>y : U
}
var expected: <T, U>(y: U, x: T) => [T, U] = flip(zip);
>expected : <T, U>(y: U, x: T) => [T, U]
>y : U
>x : T
>flip(zip) : (b: U, a: T) => [T, U]
>flip : <a, b, c>(f: (a: a, b: b) => c) => (b: b, a: a) => c
>zip : <T, U>(x: T, y: U) => [T, U]
var actual = flip(zip);
>actual : <T, U>(b: U, a: T) => [T, U]
>flip(zip) : <T, U>(b: U, a: T) => [T, U]
>flip : <a, b, c>(f: (a: a, b: b) => c) => (b: b, a: a) => c
>zip : <T, U>(x: T, y: U) => [T, U]
// #9366
const map = <T, U>(transform: (t: T) => U) =>
>map : <T, U>(transform: (t: T) => U) => (arr: T[]) => U[]
><T, U>(transform: (t: T) => U) => (arr: T[]) => arr.map(transform) : <T, U>(transform: (t: T) => U) => (arr: T[]) => U[]
>transform : (t: T) => U
>t : T
(arr: T[]) => arr.map(transform)
>(arr: T[]) => arr.map(transform) : (arr: T[]) => U[]
>arr : T[]
>arr.map(transform) : U[]
>arr.map : <U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any) => U[]
>arr : T[]
>map : <U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any) => U[]
>transform : (t: T) => U
const identityStr = (t: string) => t;
>identityStr : (t: string) => string
>(t: string) => t : (t: string) => string
>t : string
>t : string
const arr: string[] = map(identityStr)(['a']);
>arr : string[]
>map(identityStr)(['a']) : string[]
>map(identityStr) : (arr: string[]) => string[]
>map : <T, U>(transform: (t: T) => U) => (arr: T[]) => U[]
>identityStr : (t: string) => string
>['a'] : string[]
>'a' : "a"
const arr1: string[] = map(identity)(['a']);
>arr1 : string[]
>map(identity)(['a']) : string[]
>map(identity) : <T>(arr: T[]) => T[]
>map : <T, U>(transform: (t: T) => U) => (arr: T[]) => U[]
>identity : <T>(value: T) => T
>['a'] : string[]
>'a' : "a"
// #9949
function of2<a, b>(one: a, two: b): [a, b] {
>of2 : <a, b>(one: a, two: b) => [a, b]
>one : a
>two : b
return [one, two];
>[one, two] : [a, b]
>one : a
>two : b
}
const flipped = flip(of2);
>flipped : <a, b>(b: b, a: a) => [a, b]
>flip(of2) : <a, b>(b: b, a: a) => [a, b]
>flip : <a, b, c>(f: (a: a, b: b) => c) => (b: b, a: a) => c
>of2 : <a, b>(one: a, two: b) => [a, b]
// #29904.1
type Component<P> = (props: P) => {};
>Component : Component<P>
>props : P
declare const myHoc1: <P>(C: Component<P>) => Component<P>;
>myHoc1 : <P>(C: Component<P>) => Component<P>
>C : Component<P>
declare const myHoc2: <P>(C: Component<P>) => Component<P>;
>myHoc2 : <P>(C: Component<P>) => Component<P>
>C : Component<P>
declare const MyComponent1: Component<{ foo: 1 }>;
>MyComponent1 : Component<{ foo: 1; }>
>foo : 1
const enhance = pipe(
>enhance : <P>(C: Component<P>) => Component<P>
>pipe( myHoc1, myHoc2,) : <P>(C: Component<P>) => Component<P>
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
myHoc1,
>myHoc1 : <P>(C: Component<P>) => Component<P>
myHoc2,
>myHoc2 : <P>(C: Component<P>) => Component<P>
);
const MyComponent2 = enhance(MyComponent1);
>MyComponent2 : Component<{ foo: 1; }>
>enhance(MyComponent1) : Component<{ foo: 1; }>
>enhance : <P>(C: Component<P>) => Component<P>
>MyComponent1 : Component<{ foo: 1; }>
// #29904.2
const fn20 = pipe((_a?: {}) => 1);
>fn20 : (_a?: {} | undefined) => number
>pipe((_a?: {}) => 1) : (_a?: {} | undefined) => number
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
>(_a?: {}) => 1 : (_a?: {} | undefined) => number
>_a : {} | undefined
>1 : 1
// #29904.3
type Fn = (n: number) => number;
>Fn : Fn
>n : number
const fn30: Fn = pipe(
>fn30 : Fn
>pipe( x => x + 1, x => x * 2,) : (x: number) => number
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
x => x + 1,
>x => x + 1 : (x: number) => number
>x : number
>x + 1 : number
>x : number
>1 : 1
x => x * 2,
>x => x * 2 : (x: number) => number
>x : number
>x * 2 : number
>x : number
>2 : 2
);
const promise = Promise.resolve(1);
>promise : Promise<number>
>Promise.resolve(1) : Promise<number>
>Promise.resolve : { <T>(value: T | PromiseLike<T>): Promise<T>; (): Promise<void>; }
>Promise : PromiseConstructor
>resolve : { <T>(value: T | PromiseLike<T>): Promise<T>; (): Promise<void>; }
>1 : 1
promise.then(
>promise.then( pipe( x => x + 1, x => x * 2, ),) : Promise<number>
>promise.then : <TResult1 = number, TResult2 = never>(onfulfilled?: ((value: number) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null | undefined) => Promise<TResult1 | TResult2>
>promise : Promise<number>
>then : <TResult1 = number, TResult2 = never>(onfulfilled?: ((value: number) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null | undefined) => Promise<TResult1 | TResult2>
pipe(
>pipe( x => x + 1, x => x * 2, ) : (x: number) => number
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
x => x + 1,
>x => x + 1 : (x: number) => number
>x : number
>x + 1 : number
>x : number
>1 : 1
x => x * 2,
>x => x * 2 : (x: number) => number
>x : number
>x * 2 : number
>x : number
>2 : 2
),
);
// #29904.4
declare const getString: () => string;
>getString : () => string
declare const orUndefined: (name: string) => string | undefined;
>orUndefined : (name: string) => string | undefined
>name : string
declare const identity: <T>(value: T) => T;
>identity : <T>(value: T) => T
>value : T
const fn40 = pipe(
>fn40 : () => string | undefined
>pipe( getString, string => orUndefined(string), identity,) : () => string | undefined
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
getString,
>getString : () => string
string => orUndefined(string),
>string => orUndefined(string) : (string: string) => string | undefined
>string : string
>orUndefined(string) : string | undefined
>orUndefined : (name: string) => string | undefined
>string : string
identity,
>identity : <T>(value: T) => T
);
// #29904.6
declare const getArray: () => string[];
>getArray : () => string[]
declare const first: <T>(ts: T[]) => T;
>first : <T>(ts: T[]) => T
>ts : T[]
const fn60 = pipe(
>fn60 : () => string
>pipe( getArray, x => x, first,) : () => string
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
getArray,
>getArray : () => string[]
x => x,
>x => x : (x: string[]) => string[]
>x : string[]
>x : string[]
first,
>first : <T>(ts: T[]) => T
);
const fn61 = pipe(
>fn61 : () => string
>pipe( getArray, identity, first,) : () => string
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
getArray,
>getArray : () => string[]
identity,
>identity : <T>(value: T) => T
first,
>first : <T>(ts: T[]) => T
);
const fn62 = pipe(
>fn62 : () => string
>pipe( getArray, x => x, x => first(x),) : () => string
>pipe : { <A extends any[], B>(ab: (...args: A) => B): (...args: A) => B; <A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; <A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; }
getArray,
>getArray : () => string[]
x => x,
>x => x : (x: string[]) => string[]
>x : string[]
>x : string[]
x => first(x),
>x => first(x) : (x: string[]) => string
>x : string[]
>first(x) : string
>first : <T>(ts: T[]) => T
>x : string[]
);
@@ -309,7 +309,7 @@ declare function f16<A, B>(a: A, b: B): A | B;
declare let x20: number;
declare let x21: string;
declare let x22: string | number;
declare let x23: unknown;
declare let x23: string | number;
declare let x24: string | number;
declare let x30: string;
declare let x31: string | number;
@@ -462,8 +462,8 @@ let x22 = call(f15, "hello", 42); // string | number
>42 : 42
let x23 = call(f16, "hello", 42); // unknown
>x23 : unknown
>call(f16, "hello", 42) : unknown
>x23 : string | number
>call(f16, "hello", 42) : string | number
>call : <T extends unknown[], U>(f: (...args: T) => U, ...args: T) => U
>f16 : <A, B>(a: A, b: B) => A | B
>"hello" : "hello"
@@ -129,8 +129,8 @@ function curry1<A, B, C>(f: (a: A, b: B) => C): (ax: A) => (bx: B) => C {
}
var cfilter = curry1(filter);
>cfilter : (ax: {}) => (bx: {}) => {}[]
>curry1(filter) : (ax: {}) => (bx: {}) => {}[]
>cfilter : <A>(ax: (a: A) => boolean) => (bx: A[]) => A[]
>curry1(filter) : <A>(ax: (a: A) => boolean) => (bx: A[]) => A[]
>curry1 : <A, B, C>(f: (a: A, b: B) => C) => (ax: A) => (bx: B) => C
>filter : <A>(f: (a: A) => boolean, ar: A[]) => A[]
@@ -149,11 +149,11 @@ function countWhere_1<A>(pred: (a: A) => boolean): (a: A[]) => number {
>a : A[]
return compose(length2, cfilter(pred));
>compose(length2, cfilter(pred)) : (a: {}) => number
>compose(length2, cfilter(pred)) : (a: A[]) => number
>compose : <A, B, C>(f: (b: B) => C, g: (a: A) => B) => (a: A) => C
>length2 : <A>(ar: A[]) => number
>cfilter(pred) : (bx: {}) => {}[]
>cfilter : (ax: {}) => (bx: {}) => {}[]
>cfilter(pred) : (bx: A[]) => A[]
>cfilter : <A>(ax: (a: A) => boolean) => (bx: A[]) => A[]
>pred : (a: A) => boolean
}
@@ -164,14 +164,14 @@ function countWhere_2<A>(pred: (a: A) => boolean): (a: A[]) => number {
>a : A[]
var where = cfilter(pred);
>where : (bx: {}) => {}[]
>cfilter(pred) : (bx: {}) => {}[]
>cfilter : (ax: {}) => (bx: {}) => {}[]
>where : (bx: A[]) => A[]
>cfilter(pred) : (bx: A[]) => A[]
>cfilter : <A>(ax: (a: A) => boolean) => (bx: A[]) => A[]
>pred : (a: A) => boolean
return compose(length2, where);
>compose(length2, where) : (a: {}) => number
>compose(length2, where) : (a: A[]) => number
>compose : <A, B, C>(f: (b: B) => C, g: (a: A) => B) => (a: A) => C
>length2 : <A>(ar: A[]) => number
>where : (bx: {}) => {}[]
>where : (bx: A[]) => A[]
}
@@ -0,0 +1,14 @@
//// [tests/cases/compiler/noCrashUMDMergedWithGlobalValue.ts] ////
//// [other.d.ts]
export as namespace SomeInterface;
export type Action = "PUSH" | "POP" | "REPLACE";
//// [main.ts]
interface SomeInterface {
readonly length: number;
}
declare const value: SomeInterface;
//// [main.js]
@@ -0,0 +1,18 @@
=== /other.d.ts ===
export as namespace SomeInterface;
>SomeInterface : Symbol(SomeInterface, Decl(other.d.ts, 0, 0))
export type Action = "PUSH" | "POP" | "REPLACE";
>Action : Symbol(Action, Decl(other.d.ts, 0, 34))
=== /main.ts ===
interface SomeInterface {
>SomeInterface : Symbol("/other", Decl(other.d.ts, 0, 0), Decl(main.ts, 0, 0))
readonly length: number;
>length : Symbol(length, Decl(main.ts, 0, 25))
}
declare const value: SomeInterface;
>value : Symbol(value, Decl(main.ts, 3, 13))
>SomeInterface : Symbol("/other", Decl(other.d.ts, 0, 0), Decl(main.ts, 0, 0))
@@ -0,0 +1,15 @@
=== /other.d.ts ===
export as namespace SomeInterface;
>SomeInterface : typeof import("/other")
export type Action = "PUSH" | "POP" | "REPLACE";
>Action : Action
=== /main.ts ===
interface SomeInterface {
readonly length: number;
>length : number
}
declare const value: SomeInterface;
>value : import("/other")
@@ -0,0 +1,49 @@
//// [returnTypePredicateIsInstantiateInContextOfTarget.tsx]
/// <reference path="/.lib/react16.d.ts" />
import * as React from "react";
class TestComponent extends React.Component<{ isAny: <T>(obj: any) => obj is T }> {
static defaultProps = {
isAny: TestComponent.isAny
}
// Type guard is defined as a static class property
static isAny<T>(obj: any): obj is T {
return true;
}
}
const TestRender = () => <TestComponent />;
//// [returnTypePredicateIsInstantiateInContextOfTarget.js]
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
exports.__esModule = true;
/// <reference path="react16.d.ts" />
var React = require("react");
var TestComponent = /** @class */ (function (_super) {
__extends(TestComponent, _super);
function TestComponent() {
return _super !== null && _super.apply(this, arguments) || this;
}
// Type guard is defined as a static class property
TestComponent.isAny = function (obj) {
return true;
};
TestComponent.defaultProps = {
isAny: TestComponent.isAny
};
return TestComponent;
}(React.Component));
var TestRender = function () { return React.createElement(TestComponent, null); };
@@ -0,0 +1,42 @@
=== tests/cases/compiler/returnTypePredicateIsInstantiateInContextOfTarget.tsx ===
/// <reference path="react16.d.ts" />
import * as React from "react";
>React : Symbol(React, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 1, 6))
class TestComponent extends React.Component<{ isAny: <T>(obj: any) => obj is T }> {
>TestComponent : Symbol(TestComponent, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 1, 31))
>React.Component : Symbol(React.Component, Decl(react16.d.ts, 345, 54), Decl(react16.d.ts, 349, 94))
>React : Symbol(React, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 1, 6))
>Component : Symbol(React.Component, Decl(react16.d.ts, 345, 54), Decl(react16.d.ts, 349, 94))
>isAny : Symbol(isAny, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 2, 45))
>T : Symbol(T, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 2, 54))
>obj : Symbol(obj, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 2, 57))
>obj : Symbol(obj, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 2, 57))
>T : Symbol(T, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 2, 54))
static defaultProps = {
>defaultProps : Symbol(TestComponent.defaultProps, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 2, 83))
isAny: TestComponent.isAny
>isAny : Symbol(isAny, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 3, 27))
>TestComponent.isAny : Symbol(TestComponent.isAny, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 5, 5))
>TestComponent : Symbol(TestComponent, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 1, 31))
>isAny : Symbol(TestComponent.isAny, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 5, 5))
}
// Type guard is defined as a static class property
static isAny<T>(obj: any): obj is T {
>isAny : Symbol(TestComponent.isAny, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 5, 5))
>T : Symbol(T, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 8, 17))
>obj : Symbol(obj, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 8, 20))
>obj : Symbol(obj, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 8, 20))
>T : Symbol(T, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 8, 17))
return true;
}
}
const TestRender = () => <TestComponent />;
>TestRender : Symbol(TestRender, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 13, 5))
>TestComponent : Symbol(TestComponent, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 1, 31))
@@ -0,0 +1,40 @@
=== tests/cases/compiler/returnTypePredicateIsInstantiateInContextOfTarget.tsx ===
/// <reference path="react16.d.ts" />
import * as React from "react";
>React : typeof React
class TestComponent extends React.Component<{ isAny: <T>(obj: any) => obj is T }> {
>TestComponent : TestComponent
>React.Component : React.Component<{ isAny: <T>(obj: any) => obj is T; }, {}, any>
>React : typeof React
>Component : typeof React.Component
>isAny : <T>(obj: any) => obj is T
>obj : any
static defaultProps = {
>defaultProps : { isAny: <T>(obj: any) => obj is T; }
>{ isAny: TestComponent.isAny } : { isAny: <T>(obj: any) => obj is T; }
isAny: TestComponent.isAny
>isAny : <T>(obj: any) => obj is T
>TestComponent.isAny : <T>(obj: any) => obj is T
>TestComponent : typeof TestComponent
>isAny : <T>(obj: any) => obj is T
}
// Type guard is defined as a static class property
static isAny<T>(obj: any): obj is T {
>isAny : <T>(obj: any) => obj is T
>obj : any
return true;
>true : true
}
}
const TestRender = () => <TestComponent />;
>TestRender : () => JSX.Element
>() => <TestComponent /> : () => JSX.Element
><TestComponent /> : JSX.Element
>TestComponent : typeof TestComponent
@@ -0,0 +1,8 @@
// @declaration: true
// @filename: /Helpers.ts
export type StringKeyOf<TObj> = Extract<string, keyof TObj>;
// @filename: /FromFactor.ts
export type RowToColumns<TColumns> = {
[TName in StringKeyOf<TColumns>]: any;
}
@@ -0,0 +1,187 @@
// @strict: true
// @target: es2015
declare function pipe<A extends any[], B>(ab: (...args: A) => B): (...args: A) => B;
declare function pipe<A extends any[], B, C>(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C;
declare function pipe<A extends any[], B, C, D>(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D;
declare function list<T>(a: T): T[];
declare function box<V>(x: V): { value: V };
declare function foo<T extends { value: T }>(x: T): T;
const f00 = pipe(list);
const f01 = pipe(list, box);
const f02 = pipe(box, list);
const f03 = pipe(x => list(x), box);
const f04 = pipe(list, x => box(x));
const f05 = pipe(x => list(x), x => box(x))
const f06 = pipe(list, pipe(box));
const f07 = pipe(x => list(x), pipe(box));
const f08 = pipe(x => list(x), pipe(x => box(x)));
const f09 = pipe(list, x => x.length);
const f10 = pipe(foo);
const f11 = pipe(foo, foo);
const g00: <T>(x: T) => T[] = pipe(list);
const g01: <T>(x: T) => { value: T[] } = pipe(list, box);
const g02: <T>(x: T) => { value: T }[] = pipe(box, list);
const g03: <T>(x: T) => { value: T[] } = pipe(x => list(x), box);
const g04: <T>(x: T) => { value: T[] } = pipe(list, x => box(x));
const g05: <T>(x: T) => { value: T[] } = pipe(x => list(x), x => box(x))
const g06: <T>(x: T) => { value: T[] } = pipe(list, pipe(box));
const g07: <T>(x: T) => { value: T[] } = pipe(x => list(x), pipe(box));
const g08: <T>(x: T) => { value: T[] } = pipe(x => list(x), pipe(x => box(x)));
const g09: <T>(x: T) => number = pipe(list, x => x.length);
const g10: <T extends { value: T }>(x: T) => T = pipe(foo);
const g12: <T extends { value: T }>(x: T) => T = pipe(foo, foo);
declare function pipe2<A, B, C, D>(ab: (a: A) => B, cd: (c: C) => D): (a: [A, C]) => [B, D];
const f20 = pipe2(list, box);
const f21 = pipe2(box, list);
const f22 = pipe2(list, list);
const f23 = pipe2(box, box);
const f24 = pipe2(f20, f20);
const f25 = pipe2(foo, foo);
const f26 = pipe2(f25, f25);
declare function pipe3<A, B, C>(ab: (a: A) => B, ac: (a: A) => C): (a: A) => [B, C];
const f30 = pipe3(list, box);
const f31 = pipe3(box, list);
const f32 = pipe3(list, list);
declare function pipe4<A, B, C>(funcs: [(a: A) => B, (b: B) => C]): (a: A) => C;
const f40 = pipe4([list, box]);
const f41 = pipe4([box, list]);
declare function pipe5<A, B>(f: (a: A) => B): { f: (a: A) => B };
const f50 = pipe5(list); // No higher order inference
// #417
function mirror<A, B>(f: (a: A) => B): (a: A) => B { return f; }
var identityM = mirror(identity);
var x = 1;
var y = identity(x);
var z = identityM(x);
// #3038
export function keyOf<a>(value: { key: a; }): a {
return value.key;
}
export interface Data {
key: number;
value: Date;
}
var data: Data[] = [];
declare function toKeys<a>(values: a[], toKey: (value: a) => string): string[];
toKeys(data, keyOf); // Error
// #9366
function flip<a, b, c>(f: (a: a, b: b) => c): (b: b, a: a) => c {
return (b: b, a: a) => f(a, b);
}
function zip<T, U>(x: T, y: U): [T, U] {
return [x, y];
}
var expected: <T, U>(y: U, x: T) => [T, U] = flip(zip);
var actual = flip(zip);
// #9366
const map = <T, U>(transform: (t: T) => U) =>
(arr: T[]) => arr.map(transform)
const identityStr = (t: string) => t;
const arr: string[] = map(identityStr)(['a']);
const arr1: string[] = map(identity)(['a']);
// #9949
function of2<a, b>(one: a, two: b): [a, b] {
return [one, two];
}
const flipped = flip(of2);
// #29904.1
type Component<P> = (props: P) => {};
declare const myHoc1: <P>(C: Component<P>) => Component<P>;
declare const myHoc2: <P>(C: Component<P>) => Component<P>;
declare const MyComponent1: Component<{ foo: 1 }>;
const enhance = pipe(
myHoc1,
myHoc2,
);
const MyComponent2 = enhance(MyComponent1);
// #29904.2
const fn20 = pipe((_a?: {}) => 1);
// #29904.3
type Fn = (n: number) => number;
const fn30: Fn = pipe(
x => x + 1,
x => x * 2,
);
const promise = Promise.resolve(1);
promise.then(
pipe(
x => x + 1,
x => x * 2,
),
);
// #29904.4
declare const getString: () => string;
declare const orUndefined: (name: string) => string | undefined;
declare const identity: <T>(value: T) => T;
const fn40 = pipe(
getString,
string => orUndefined(string),
identity,
);
// #29904.6
declare const getArray: () => string[];
declare const first: <T>(ts: T[]) => T;
const fn60 = pipe(
getArray,
x => x,
first,
);
const fn61 = pipe(
getArray,
identity,
first,
);
const fn62 = pipe(
getArray,
x => x,
x => first(x),
);
@@ -0,0 +1,9 @@
//@filename: /other.d.ts
export as namespace SomeInterface;
export type Action = "PUSH" | "POP" | "REPLACE";
//@filename: /main.ts
interface SomeInterface {
readonly length: number;
}
declare const value: SomeInterface;
@@ -0,0 +1,16 @@
// @jsx: react
// @strict: true
/// <reference path="/.lib/react16.d.ts" />
import * as React from "react";
class TestComponent extends React.Component<{ isAny: <T>(obj: any) => obj is T }> {
static defaultProps = {
isAny: TestComponent.isAny
}
// Type guard is defined as a static class property
static isAny<T>(obj: any): obj is T {
return true;
}
}
const TestRender = () => <TestComponent />;
@@ -0,0 +1,17 @@
/// <reference path='fourslash.ts' />
////function f(/*a*/a?: number, b: string = "1"/*b*/): string {
//// return b;
////}
////f();
goTo.select("a", "b");
edit.applyRefactor({
refactorName: "Convert to named parameters",
actionName: "Convert to named parameters",
actionDescription: "Convert to named parameters",
newContent: `function f({ a, b = "1" }: { a?: number; b?: string; } = {}): string {
return b;
}
f();`
});
@@ -0,0 +1,13 @@
/// <reference path='fourslash.ts' />
////const foo = /*a*/(a: number, b: number)/*b*/ => { };
////foo(1, 2);
goTo.select("a", "b");
edit.applyRefactor({
refactorName: "Convert to named parameters",
actionName: "Convert to named parameters",
actionDescription: "Convert to named parameters",
newContent: `const foo = ({ a, b }: { a: number; b: number; }) => { };
foo({ a: 1, b: 2 });`
});
@@ -0,0 +1,7 @@
/// <reference path='fourslash.ts' />
////const foo: (a: number, b: number) => number = /*a*/(a: number, b: number)/*b*/ => a + b;
////foo(1, 2);
goTo.select("a", "b");
verify.not.refactorAvailable("Convert to named parameters");
@@ -0,0 +1,17 @@
/// <reference path='fourslash.ts' />
////function /*a*/foo/*b*/(a: number, b: number, ...rest: number[]) {
//// return a + b;
////}
////foo(/**a*/ 1 /**b*/, /**c*/ 2 /**d*/, /**e*/ 3 /**f*/, /**g*/ 4 /**h*/);
goTo.select("a", "b");
edit.applyRefactor({
refactorName: "Convert to named parameters",
actionName: "Convert to named parameters",
actionDescription: "Convert to named parameters",
newContent: `function foo({ a, b, rest = [] }: { a: number; b: number; rest?: number[]; }) {
return a + b;
}
foo({ /**a*/ a: 1 /**b*/, /**c*/ b: 2 /**d*/, rest: [/**e*/ 3 /**f*/, /**g*/ 4 /**h*/] });`
});
@@ -0,0 +1,34 @@
/// <reference path='fourslash.ts' />
////function /*a*/foo/*b*/(a: number, b: number, ...rest: number[]) {
//// return a + b;
////}
////foo(
//// /**a*/
//// 1,
//// /**c*/
//// 2,
//// /**e*/
//// 3,
//// /**g*/
//// 4);
goTo.select("a", "b");
/* The expected content is currently wrong. The new argument object has the wrong formatting. */
edit.applyRefactor({
refactorName: "Convert to named parameters",
actionName: "Convert to named parameters",
actionDescription: "Convert to named parameters",
newContent: `function foo({ a, b, rest = [] }: { a: number; b: number; rest?: number[]; }) {
return a + b;
}
foo(
{ /**a*/
a: 1, /**c*/
b: 2, rest: [
/**e*/
3,
/**g*/
4]
});`
});
@@ -0,0 +1,17 @@
/// <reference path='fourslash.ts' />
////function foo(/*a*/a: number, b: number/*b*/) {
//// return { bar: () => a + b };
////}
////var x = foo(1, 2).bar();
goTo.select("a", "b");
edit.applyRefactor({
refactorName: "Convert to named parameters",
actionName: "Convert to named parameters",
actionDescription: "Convert to named parameters",
newContent: `function foo({ a, b }: { a: number; b: number; }) {
return { bar: () => a + b };
}
var x = foo({ a: 1, b: 2 }).bar();`
});
@@ -0,0 +1,20 @@
/// <reference path='fourslash.ts' />
////class Foo {
//// /*a*/constructor/*b*/(a: number, b: number) { }
////}
////const fooAlias = Foo;
////const newFoo = new fooAlias(1, 2);
goTo.select("a", "b");
// Refactor should not make changes
edit.applyRefactor({
refactorName: "Convert to named parameters",
actionName: "Convert to named parameters",
actionDescription: "Convert to named parameters",
newContent: `class Foo {
constructor(a: number, b: number) { }
}
const fooAlias = Foo;
const newFoo = new fooAlias(1, 2);`
});
@@ -0,0 +1,31 @@
/// <reference path='fourslash.ts' />
////class C {
//// static a: number = 2;
//// /*a*/constructor/*b*/(a: number, b: number) { }
////}
////const newC = new C(1, 2);
////const b = C.a;
////C["a"] = 3;
////let c: C;
////function f(c: C) { }
////class B extends C { }
////class A implements C { }
goTo.select("a", "b");
edit.applyRefactor({
refactorName: "Convert to named parameters",
actionName: "Convert to named parameters",
actionDescription: "Convert to named parameters",
newContent: `class C {
static a: number = 2;
constructor({ a, b }: { a: number; b: number; }) { }
}
const newC = new C({ a: 1, b: 2 });
const b = C.a;
C["a"] = 3;
let c: C;
function f(c: C) { }
class B extends C { }
class A implements C { }`
});
@@ -0,0 +1,17 @@
/// <reference path='fourslash.ts' />
////const c = class {
//// constructor(/*a*/a: number, b = { x: 1 }/*b*/) { }
////}
////var x = new c(2);
goTo.select("a", "b");
edit.applyRefactor({
refactorName: "Convert to named parameters",
actionName: "Convert to named parameters",
actionDescription: "Convert to named parameters",
newContent: `const c = class {
constructor({ a, b = { x: 1 } }: { a: number; b?: { x: number; }; }) { }
}
var x = new c({ a: 2 });`
});
@@ -0,0 +1,23 @@
/// <reference path='fourslash.ts' />
////const c = class C {
//// static a: number = 2;
//// /*a*/constructor/*b*/(a: number, b: number) { }
////}
////const a = new c(0, 1);
////const b = c.a;
////c["a"] = 3;
goTo.select("a", "b");
edit.applyRefactor({
refactorName: "Convert to named parameters",
actionName: "Convert to named parameters",
actionDescription: "Convert to named parameters",
newContent: `const c = class C {
static a: number = 2;
constructor({ a, b }: { a: number; b: number; }) { }
}
const a = new c({ a: 0, b: 1 });
const b = c.a;
c["a"] = 3;`
});
@@ -0,0 +1,26 @@
/// <reference path='fourslash.ts' />
////const foo = class Foo {
//// /*a*/constructor/*b*/(a: number, b: number) { }
////}
////class Bar extends foo {
//// constructor() {
//// super(1, 2);
//// }
////}
goTo.select("a", "b");
// Refactor should not make changes
edit.applyRefactor({
refactorName: "Convert to named parameters",
actionName: "Convert to named parameters",
actionDescription: "Convert to named parameters",
newContent: `const foo = class Foo {
constructor(a: number, b: number) { }
}
class Bar extends foo {
constructor() {
super(1, 2);
}
}`
});
@@ -0,0 +1,23 @@
/// <reference path='fourslash.ts' />
////class Foo<T> {
//// /*a*/bar/*b*/(t: T, s: T) {
//// return s;
//// }
////}
////var foo = new Foo();
////foo.bar("a", "b");
goTo.select("a", "b");
edit.applyRefactor({
refactorName: "Convert to named parameters",
actionName: "Convert to named parameters",
actionDescription: "Convert to named parameters",
newContent: `class Foo<T> {
bar({ t, s }: { t: T; s: T; }) {
return s;
}
}
var foo = new Foo();
foo.bar({ t: "a", s: "b" });`
});
@@ -0,0 +1,27 @@
/// <reference path='fourslash.ts' />
////class Foo {
//// t: string;
//// s: string;
//// /*a*/constructor/*b*/(t: string, s: string) {
//// this.t = t;
//// this.s = s;
//// }
////}
////var foo = new Foo("a", "b");
goTo.select("a", "b");
edit.applyRefactor({
refactorName: "Convert to named parameters",
actionName: "Convert to named parameters",
actionDescription: "Convert to named parameters",
newContent: `class Foo {
t: string;
s: string;
constructor({ t, s }: { t: string; s: string; }) {
this.t = t;
this.s = s;
}
}
var foo = new Foo({ t: "a", s: "b" });`
});
@@ -0,0 +1,8 @@
/// <reference path='fourslash.ts' />
/////export default class {
//// constructor(/*a*/a: number, b = { x: 1 }/*b*/) {}
////}
goTo.select("a", "b");
verify.not.refactorAvailable("Convert to named parameters");
@@ -0,0 +1,17 @@
/// <reference path='fourslash.ts' />
////function f(/*a*/a: number, b: string/*b*/): string {
//// return b;
////}
////f(4, "b");
goTo.select("a", "b");
edit.applyRefactor({
refactorName: "Convert to named parameters",
actionName: "Convert to named parameters",
actionDescription: "Convert to named parameters",
newContent: `function f({ a, b }: { a: number; b: string; }): string {
return b;
}
f({ a: 4, b: "b" });`
});
@@ -0,0 +1,23 @@
/// <reference path='fourslash.ts' />
////foo(1, 2); /**a*/
/////**b*/ function /*a*/foo/*b*/(/**this1*/ this /**this2*/: /**void1*/ void /**void2*/, /**c*/ a /**d*/: /**e*/ number /**f*/, /**g*/ b /**h*/: /**i*/ number /**j*/ = /**k*/ 1 /**l*/) {
//// // m
//// /**n*/ return a + b; // o
//// // p
////} // q
/////**r*/ foo(1);
goTo.select("a", "b");
edit.applyRefactor({
refactorName: "Convert to named parameters",
actionName: "Convert to named parameters",
actionDescription: "Convert to named parameters",
newContent: `foo({ a: 1, b: 2 }); /**a*/
/**b*/ function foo(/**this1*/ this /**this2*/: /**void1*/ void /**void2*/, { a, b = /**k*/ 1 /**l*/ }: { /**c*/ a /**d*/: /**e*/ number /**f*/; /**g*/ b /**h*/?: /**i*/ number /**j*/; }) {
// m
/**n*/ return a + b; // o
// p
} // q
/**r*/ foo({ a: 1 });`
});
@@ -0,0 +1,15 @@
/// <reference path='fourslash.ts' />
////function /*a*/foo/*b*/(a: number /** a */, b: number /** b */) {
//// return a + b;
////}
goTo.select("a", "b");
edit.applyRefactor({
refactorName: "Convert to named parameters",
actionName: "Convert to named parameters",
actionDescription: "Convert to named parameters",
newContent: `function foo({ a, b }: { a: number /** a */; b: number /** b */; }) {
return a + b;
}`
});
@@ -0,0 +1,26 @@
/// <reference path='fourslash.ts' />
////function /*a*/foo/*b*/(// comment
//// // a comment
//// a: number,
//// // b comment
//// b: number
////) {
//// return a + b;
////}
goTo.select("a", "b");
edit.applyRefactor({
refactorName: "Convert to named parameters",
actionName: "Convert to named parameters",
actionDescription: "Convert to named parameters",
newContent: `function foo(// comment
{ a, b }: {
// a comment
a: number;
// b comment
b: number;
}) {
return a + b;
}`
});
@@ -0,0 +1,13 @@
/// <reference path='fourslash.ts' />
////const foo = /*a*/function/*b*/(a: number, b: number) { };
////foo(1, 2);
goTo.select("a", "b");
edit.applyRefactor({
refactorName: "Convert to named parameters",
actionName: "Convert to named parameters",
actionDescription: "Convert to named parameters",
newContent: `const foo = function({ a, b }: { a: number; b: number; }) { };
foo({ a: 1, b: 2 });`
});
@@ -0,0 +1,17 @@
/// <reference path='fourslash.ts' />
////function foo<T, S>(/*a*/t: T, s: S/*b*/) {
//// return s;
////}
////foo("a", "b");
goTo.select("a", "b");
edit.applyRefactor({
refactorName: "Convert to named parameters",
actionName: "Convert to named parameters",
actionDescription: "Convert to named parameters",
newContent: `function foo<T, S>({ t, s }: { t: T; s: S; }) {
return s;
}
foo({ t: "a", s: "b" });`
});
@@ -0,0 +1,24 @@
/// <reference path='fourslash.ts' />
////class Foo {
//// /*a*/constructor/*b*/(t: string, s: string) { }
////}
////class Bar extends Foo { }
////var bar = new Bar("a", "b");
////var foo = new Foo("c", "d");
goTo.select("a", "b");
/* The expected new content is currently wrong.
`new Bar("a", "b")` should be modified by the refactor to be `new Bar({ t: "a", s: "b" })`
*/
edit.applyRefactor({
refactorName: "Convert to named parameters",
actionName: "Convert to named parameters",
actionDescription: "Convert to named parameters",
newContent: `class Foo {
constructor({ t, s }: { t: string; s: string; }) { }
}
class Bar extends Foo { }
var bar = new Bar("a", "b");
var foo = new Foo({ t: "c", s: "d" });`
});
@@ -0,0 +1,25 @@
/// <reference path='fourslash.ts' />
////class Foo {
//// /*a*/bar/*b*/(t: string, s: string): string {
//// return s + t;
//// }
////}
////class Bar extends Foo { }
////var bar = new Bar();
////bar.bar("a", "b");
goTo.select("a", "b");
edit.applyRefactor({
refactorName: "Convert to named parameters",
actionName: "Convert to named parameters",
actionDescription: "Convert to named parameters",
newContent: `class Foo {
bar({ t, s }: { t: string; s: string; }): string {
return s + t;
}
}
class Bar extends Foo { }
var bar = new Bar();
bar.bar({ t: "a", s: "b" });`
});
@@ -0,0 +1,17 @@
/// <reference path='fourslash.ts' />
////function f(/*a*/a: number, b: string = "1"/*b*/): string {
//// return b;
////}
////f(4, "b");
goTo.select("a", "b");
edit.applyRefactor({
refactorName: "Convert to named parameters",
actionName: "Convert to named parameters",
actionDescription: "Convert to named parameters",
newContent: `function f({ a, b = "1" }: { a: number; b?: string; }): string {
return b;
}
f({ a: 4, b: "b" });`
});
@@ -0,0 +1,17 @@
/// <reference path='fourslash.ts' />
////function f(/*a*/a: number, b = { x: 1, z: { s: true } }/*b*/) {
//// return b;
////}
////f(2);
goTo.select("a", "b");
edit.applyRefactor({
refactorName: "Convert to named parameters",
actionName: "Convert to named parameters",
actionDescription: "Convert to named parameters",
newContent: `function f({ a, b = { x: 1, z: { s: true } } }: { a: number; b?: { x: number; z: { s: boolean; }; }; }) {
return b;
}
f({ a: 2 });`
});
@@ -0,0 +1,23 @@
/// <reference path='fourslash.ts' />
////class Foo {
//// /*a*/bar/*b*/(t: string, s: string): string {
//// return s + t;
//// }
////}
////var foo = new Foo();
////foo.bar("a", "b");
goTo.select("a", "b");
edit.applyRefactor({
refactorName: "Convert to named parameters",
actionName: "Convert to named parameters",
actionDescription: "Convert to named parameters",
newContent: `class Foo {
bar({ t, s }: { t: string; s: string; }): string {
return s + t;
}
}
var foo = new Foo();
foo.bar({ t: "a", s: "b" });`
});
@@ -0,0 +1,29 @@
/// <reference path='fourslash.ts' />
////class A {
//// /*a*/foo/*b*/(a: number, b: number) { return a + b; }
////}
////class B {
//// foo(c: number, d: number) { return c + d; }
////}
////function foo(ab: A | B) {
//// return ab.foo(1, 2);
////}
goTo.select("a", "b");
// Refactor should not make changes
edit.applyRefactor({
refactorName: "Convert to named parameters",
actionName: "Convert to named parameters",
actionDescription: "Convert to named parameters",
newContent: `class A {
foo(a: number, b: number) { return a + b; }
}
class B {
foo(c: number, d: number) { return c + d; }
}
function foo(ab: A | B) {
return ab.foo(1, 2);
}`
});
@@ -0,0 +1,25 @@
/// <reference path='fourslash.ts' />
////class Foo {
//// /*a*/bar/*b*/(t: string, s: string): string {
//// return s + t;
//// }
////}
////var foo = new Foo();
////foo['bar']("a", "b");
////foo.bar("a", "b");
goTo.select("a", "b");
edit.applyRefactor({
refactorName: "Convert to named parameters",
actionName: "Convert to named parameters",
actionDescription: "Convert to named parameters",
newContent: `class Foo {
bar({ t, s }: { t: string; s: string; }): string {
return s + t;
}
}
var foo = new Foo();
foo['bar']({ t: "a", s: "b" });
foo.bar({ t: "a", s: "b" });`
});
@@ -0,0 +1,45 @@
/// <reference path='fourslash.ts' />
////class A {
//// /*a*/foo/*b*/(a: number, b: number) { }
////}
////class B extends A {
//// /*c*/foo/*d*/(c: number, d: number) { }
////}
////var a = new A();
////a.foo(3, 4);
////var b = new B();
////b.foo(5, 6);
goTo.select("a", "b");
edit.applyRefactor({
refactorName: "Convert to named parameters",
actionName: "Convert to named parameters",
actionDescription: "Convert to named parameters",
newContent: `class A {
foo(a: number, b: number) { }
}
class B extends A {
foo(c: number, d: number) { }
}
var a = new A();
a.foo(3, 4);
var b = new B();
b.foo(5, 6);`
});
goTo.select("c", "d");
edit.applyRefactor({
refactorName: "Convert to named parameters",
actionName: "Convert to named parameters",
actionDescription: "Convert to named parameters",
newContent: `class A {
foo(a: number, b: number) { }
}
class B extends A {
foo(c: number, d: number) { }
}
var a = new A();
a.foo(3, 4);
var b = new B();
b.foo(5, 6);`
});
@@ -0,0 +1,10 @@
/// <reference path='fourslash.ts' />
////function f(a: number, b: number);
////function f(/*a*/a: number, b = 1/*b*/) {
//// return b;
////}
////f(2);
goTo.select("a", "b");
verify.not.refactorAvailable("Convert to named parameters");
@@ -0,0 +1,11 @@
/// <reference path='fourslash.ts' />
////declare function required(target: Object, propertyKey: string | symbol, parameterIndex: number)
////class C {
//// /*a*/bar/*b*/(@required a: number, b: number) {
////
//// }
////}
goTo.select("a", "b");
verify.not.refactorAvailable("Convert to named parameters");
@@ -0,0 +1,20 @@
/// <reference path='fourslash.ts' />
////const f = function foo(/*a*/a: number, b: number/*b*/) {
//// foo(1, 2);
////}
////function foo(a: number, b: number) { }
////foo(3, 4);
goTo.select("a", "b");
edit.applyRefactor({
refactorName: "Convert to named parameters",
actionName: "Convert to named parameters",
actionDescription: "Convert to named parameters",
newContent: `const f = function foo({ a, b }: { a: number; b: number; }) {
foo({ a: 1, b: 2 });
}
function foo(a: number, b: number) { }
foo(3, 4);`
});
@@ -0,0 +1,15 @@
/// <reference path='fourslash.ts' />
////function log(/*a*/a: number, b: number, ...args/*b*/) { }
////let l = log(-1, -2, 3, 4, 5);
////let k = log(1, 2);
goTo.select("a", "b");
edit.applyRefactor({
refactorName: "Convert to named parameters",
actionName: "Convert to named parameters",
actionDescription: "Convert to named parameters",
newContent: `function log({ a, b, args = [] }: { a: number; b: number; args?: any[]; }) { }
let l = log({ a: -1, b: -2, args: [3, 4, 5] });
let k = log({ a: 1, b: 2 });`
});

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