Merge branch 'master' into dynamicNames

This commit is contained in:
Ron Buckton
2017-10-04 14:57:24 -07:00
229 changed files with 4003 additions and 3043 deletions
+2 -2
View File
@@ -394,7 +394,7 @@ gulp.task(generateLocalizedDiagnosticMessagesJs, /*help*/ false, [], () => {
.pipe(sourcemaps.init())
.pipe(tsc(settings))
.pipe(sourcemaps.write("."))
.pipe(gulp.dest("."));
.pipe(gulp.dest(scriptsDirectory));
});
// Localize diagnostics
@@ -1091,7 +1091,7 @@ gulp.task("lint", "Runs tslint on the compiler sources. Optional arguments are:
const fileMatcher = cmdLineOptions["files"];
const files = fileMatcher
? `src/**/${fileMatcher}`
: "Gulpfile.ts 'scripts/generateLocalizedDiagnosticMessages.ts' scripts/tslint/**/*.ts' 'src/**/*.ts' --exclude src/lib/es5.d.ts --exclude 'src/lib/*.generated.d.ts'";
: "Gulpfile.ts 'scripts/generateLocalizedDiagnosticMessages.ts' 'scripts/tslint/**/*.ts' 'src/**/*.ts' --exclude src/lib/es5.d.ts --exclude 'src/lib/*.generated.d.ts'";
const cmd = `node node_modules/tslint/bin/tslint ${files} --formatters-dir ./built/local/tslint/formatters --format autolinkableStylish`;
console.log("Linting: " + cmd);
child_process.execSync(cmd, { stdio: [0, 1, 2] });
+1
View File
@@ -129,6 +129,7 @@ var harnessSources = harnessCoreSources.concat([
"textStorage.ts",
"moduleResolution.ts",
"tsconfigParsing.ts",
"builder.ts",
"commandLineParsing.ts",
"configurationExtension.ts",
"convertCompilerOptionsFromJson.ts",
+37 -27
View File
@@ -93,12 +93,14 @@ namespace ts {
signature: string;
}
export function createBuilder(
getCanonicalFileName: (fileName: string) => string,
getEmitOutput: (program: Program, sourceFile: SourceFile, emitOnlyDtsFiles: boolean, isDetailed: boolean) => EmitOutput | EmitOutputDetailed,
computeHash: (data: string) => string,
shouldEmitFile: (sourceFile: SourceFile) => boolean
): Builder {
export interface BuilderOptions {
getCanonicalFileName: (fileName: string) => string;
getEmitOutput: (program: Program, sourceFile: SourceFile, emitOnlyDtsFiles: boolean, isDetailed: boolean) => EmitOutput | EmitOutputDetailed;
computeHash: (data: string) => string;
shouldEmitFile: (sourceFile: SourceFile) => boolean;
}
export function createBuilder(options: BuilderOptions): Builder {
let isModuleEmit: boolean | undefined;
const fileInfos = createMap<FileInfo>();
const semanticDiagnosticsPerFile = createMap<ReadonlyArray<Diagnostic>>();
@@ -181,7 +183,7 @@ namespace ts {
ensureProgramGraph(program);
const sourceFile = program.getSourceFile(path);
const singleFileResult = sourceFile && shouldEmitFile(sourceFile) ? [sourceFile.fileName] : [];
const singleFileResult = sourceFile && options.shouldEmitFile(sourceFile) ? [sourceFile.fileName] : [];
const info = fileInfos.get(path);
if (!info || !updateShapeSignature(program, sourceFile, info)) {
return singleFileResult;
@@ -197,7 +199,7 @@ namespace ts {
return { outputFiles: [], emitSkipped: true };
}
return getEmitOutput(program, program.getSourceFileByPath(path), /*emitOnlyDtsFiles*/ false, /*isDetailed*/ false);
return options.getEmitOutput(program, program.getSourceFileByPath(path), /*emitOnlyDtsFiles*/ false, /*isDetailed*/ false);
}
function enumerateChangedFilesSet(
@@ -220,21 +222,21 @@ namespace ts {
onChangedFile: (fileName: string, path: Path) => void,
onEmitOutput: (emitOutput: EmitOutputDetailed, sourceFile: SourceFile) => void
) {
const seenFiles = createMap<SourceFile>();
const seenFiles = createMap<true>();
enumerateChangedFilesSet(program, onChangedFile, (fileName, sourceFile) => {
if (!seenFiles.has(fileName)) {
seenFiles.set(fileName, sourceFile);
seenFiles.set(fileName, true);
if (sourceFile) {
// Any affected file shouldnt have the cached diagnostics
semanticDiagnosticsPerFile.delete(sourceFile.path);
const emitOutput = getEmitOutput(program, sourceFile, emitOnlyDtsFiles, /*isDetailed*/ true) as EmitOutputDetailed;
const emitOutput = options.getEmitOutput(program, sourceFile, emitOnlyDtsFiles, /*isDetailed*/ true) as EmitOutputDetailed;
onEmitOutput(emitOutput, sourceFile);
// mark all the emitted source files as seen
if (emitOutput.emittedSourceFiles) {
for (const file of emitOutput.emittedSourceFiles) {
seenFiles.set(file.fileName, file);
seenFiles.set(file.fileName, true);
}
}
}
@@ -309,13 +311,13 @@ namespace ts {
const prevSignature = info.signature;
let latestSignature: string;
if (sourceFile.isDeclarationFile) {
latestSignature = computeHash(sourceFile.text);
latestSignature = options.computeHash(sourceFile.text);
info.signature = latestSignature;
}
else {
const emitOutput = getEmitOutput(program, sourceFile, /*emitOnlyDtsFiles*/ true, /*isDetailed*/ false);
const emitOutput = options.getEmitOutput(program, sourceFile, /*emitOnlyDtsFiles*/ true, /*isDetailed*/ false);
if (emitOutput.outputFiles && emitOutput.outputFiles.length > 0) {
latestSignature = computeHash(emitOutput.outputFiles[0].text);
latestSignature = options.computeHash(emitOutput.outputFiles[0].text);
info.signature = latestSignature;
}
else {
@@ -352,7 +354,7 @@ namespace ts {
// Handle triple slash references
if (sourceFile.referencedFiles && sourceFile.referencedFiles.length > 0) {
for (const referencedFile of sourceFile.referencedFiles) {
const referencedPath = toPath(referencedFile.fileName, sourceFileDirectory, getCanonicalFileName);
const referencedPath = toPath(referencedFile.fileName, sourceFileDirectory, options.getCanonicalFileName);
addReferencedFile(referencedPath);
}
}
@@ -365,7 +367,7 @@ namespace ts {
}
const fileName = resolvedTypeReferenceDirective.resolvedFileName;
const typeFilePath = toPath(fileName, sourceFileDirectory, getCanonicalFileName);
const typeFilePath = toPath(fileName, sourceFileDirectory, options.getCanonicalFileName);
addReferencedFile(typeFilePath);
});
}
@@ -381,18 +383,26 @@ namespace ts {
}
/**
* Gets all the emittable files from the program
* Gets all the emittable files from the program.
* @param firstSourceFile This one will be emitted first. See https://github.com/Microsoft/TypeScript/issues/16888
*/
function getAllEmittableFiles(program: Program) {
function getAllEmittableFiles(program: Program, firstSourceFile: SourceFile): string[] {
const defaultLibraryFileName = getDefaultLibFileName(program.getCompilerOptions());
const sourceFiles = program.getSourceFiles();
const result: string[] = [];
add(firstSourceFile);
for (const sourceFile of sourceFiles) {
if (getBaseFileName(sourceFile.fileName) !== defaultLibraryFileName && shouldEmitFile(sourceFile)) {
result.push(sourceFile.fileName);
if (sourceFile !== firstSourceFile) {
add(sourceFile);
}
}
return result;
function add(sourceFile: SourceFile): void {
if (getBaseFileName(sourceFile.fileName) !== defaultLibraryFileName && options.shouldEmitFile(sourceFile)) {
result.push(sourceFile.fileName);
}
}
}
function getNonModuleEmitHandler(): EmitHandler {
@@ -404,14 +414,14 @@ namespace ts {
getFilesAffectedByUpdatedShape
};
function getFilesAffectedByUpdatedShape(program: Program, _sourceFile: SourceFile, singleFileResult: string[]): string[] {
function getFilesAffectedByUpdatedShape(program: Program, sourceFile: SourceFile, singleFileResult: string[]): string[] {
const options = program.getCompilerOptions();
// If `--out` or `--outFile` is specified, any new emit will result in re-emitting the entire project,
// so returning the file itself is good enough.
if (options && (options.out || options.outFile)) {
return singleFileResult;
}
return getAllEmittableFiles(program);
return getAllEmittableFiles(program, sourceFile);
}
}
@@ -484,11 +494,11 @@ namespace ts {
function getFilesAffectedByUpdatedShape(program: Program, sourceFile: SourceFile, singleFileResult: string[]): string[] {
if (!isExternalModule(sourceFile) && !containsOnlyAmbientModules(sourceFile)) {
return getAllEmittableFiles(program);
return getAllEmittableFiles(program, sourceFile);
}
const options = program.getCompilerOptions();
if (options && (options.isolatedModules || options.out || options.outFile)) {
const compilerOptions = program.getCompilerOptions();
if (compilerOptions && (compilerOptions.isolatedModules || compilerOptions.out || compilerOptions.outFile)) {
return singleFileResult;
}
@@ -498,7 +508,7 @@ namespace ts {
const seenFileNamesMap = createMap<string>();
const setSeenFileName = (path: Path, sourceFile: SourceFile) => {
seenFileNamesMap.set(path, sourceFile && shouldEmitFile(sourceFile) ? sourceFile.fileName : undefined);
seenFileNamesMap.set(path, sourceFile && options.shouldEmitFile(sourceFile) ? sourceFile.fileName : undefined);
};
// Start with the paths this file was referenced by
+18 -6
View File
@@ -13512,13 +13512,25 @@ namespace ts {
const binaryExpression = <BinaryExpression>node.parent;
const operator = binaryExpression.operatorToken.kind;
if (isAssignmentOperator(operator)) {
// Don't do this for special property assignments to avoid circularity
if (getSpecialPropertyAssignmentKind(binaryExpression) !== SpecialPropertyAssignmentKind.None) {
return undefined;
}
// In an assignment expression, the right operand is contextually typed by the type of the left operand.
if (node === binaryExpression.right) {
// Don't do this for special property assignments to avoid circularity
switch (getSpecialPropertyAssignmentKind(binaryExpression)) {
case SpecialPropertyAssignmentKind.None:
break;
case SpecialPropertyAssignmentKind.Property:
// If `binaryExpression.left` was assigned a symbol, then this is a new declaration; otherwise it is an assignment to an existing declaration.
// See `bindStaticPropertyAssignment` in `binder.ts`.
if (!binaryExpression.left.symbol) {
break;
}
// falls through
case SpecialPropertyAssignmentKind.ExportsProperty:
case SpecialPropertyAssignmentKind.ModuleExports:
case SpecialPropertyAssignmentKind.PrototypeProperty:
case SpecialPropertyAssignmentKind.ThisProperty:
return undefined;
}
// In an assignment expression, the right operand is contextually typed by the type of the left operand.
return getTypeOfExpression(binaryExpression.left);
}
}
+2
View File
@@ -247,6 +247,8 @@ namespace ts {
}
/** Works like Array.prototype.find, returning `undefined` if no element satisfying the predicate is found. */
export function find<T, U extends T>(array: ReadonlyArray<T>, predicate: (element: T, index: number) => element is U): U | undefined;
export function find<T>(array: ReadonlyArray<T>, predicate: (element: T, index: number) => boolean): T | undefined;
export function find<T>(array: ReadonlyArray<T>, predicate: (element: T, index: number) => boolean): T | undefined {
for (let i = 0; i < array.length; i++) {
const value = array[i];
+10
View File
@@ -3785,5 +3785,15 @@
"Extract constant": {
"category": "Message",
"code": 95006
},
"Extract to {0} in enclosing scope": {
"category": "Message",
"code": 95007
},
"Extract to {0} in {1} scope": {
"category": "Message",
"code": 95008
}
}
+1 -1
View File
@@ -6646,7 +6646,7 @@ namespace ts {
function parsePropertyAccessEntityNameExpression() {
let node: Identifier | PropertyAccessEntityNameExpression = parseJSDocIdentifierName(/*createIfMissing*/ true);
while (token() === SyntaxKind.DotToken) {
while (parseOptional(SyntaxKind.DotToken)) {
const prop: PropertyAccessEntityNameExpression = createNode(SyntaxKind.PropertyAccessExpression, node.pos) as PropertyAccessEntityNameExpression;
prop.expression = node;
prop.name = parseJSDocIdentifierName();
+1 -1
View File
@@ -308,7 +308,7 @@ namespace ts {
getCurrentDirectory()
);
// There is no extra check needed since we can just rely on the program to decide emit
const builder = createBuilder(getCanonicalFileName, getFileEmitOutput, computeHash, _sourceFile => true);
const builder = createBuilder({ getCanonicalFileName, getEmitOutput: getFileEmitOutput, computeHash, shouldEmitFile: () => true });
synchronizeProgram();
+3
View File
@@ -312,6 +312,9 @@ namespace Harness.Parallel.Host {
function makeMochaTest(test: ErrorInfo) {
return {
fullTitle: () => {
return test.name.join(" ");
},
titlePath: () => {
return test.name;
},
err: {
+2 -2
View File
@@ -6,8 +6,8 @@ namespace Harness.Parallel {
export type ParallelCloseMessage = { type: "close" } | never;
export type ParallelHostMessage = ParallelTestMessage | ParallelCloseMessage | ParallelBatchMessage;
export type ParallelErrorMessage = { type: "error", payload: { error: string, stack: string, name?: string } } | never;
export type ErrorInfo = ParallelErrorMessage["payload"] & { name: string };
export type ParallelErrorMessage = { type: "error", payload: { error: string, stack: string, name?: string[] } } | never;
export type ErrorInfo = ParallelErrorMessage["payload"] & { name: string[] };
export type ParallelResultMessage = { type: "result", payload: { passing: number, errors: ErrorInfo[], duration: number, runner: TestRunnerKind, file: string } } | never;
export type ParallelBatchProgressMessage = { type: "progress", payload: ParallelResultMessage["payload"] } | never;
export type ParallelClientMessage = ParallelErrorMessage | ParallelResultMessage | ParallelBatchProgressMessage;
+14 -10
View File
@@ -12,6 +12,11 @@ namespace Harness.Parallel.Worker {
testList.length = 0;
}
reportedUnitTests = true;
if (testList.length) {
// Execute unit tests
testList.forEach(({ name, callback, kind }) => executeCallback(name, callback, kind));
testList.length = 0;
}
const start = +(new Date());
runner.initializeTests();
testList.forEach(({ name, callback, kind }) => executeCallback(name, callback, kind));
@@ -57,14 +62,14 @@ namespace Harness.Parallel.Worker {
callback.call(fakeContext);
}
catch (e) {
errors.push({ error: `Error executing suite: ${e.message}`, stack: e.stack, name: namestack.join(" ") });
errors.push({ error: `Error executing suite: ${e.message}`, stack: e.stack, name: [...namestack] });
return cleanup();
}
try {
beforeFunc && beforeFunc();
}
catch (e) {
errors.push({ error: `Error executing before function: ${e.message}`, stack: e.stack, name: namestack.join(" ") });
errors.push({ error: `Error executing before function: ${e.message}`, stack: e.stack, name: [...namestack] });
return cleanup();
}
finally {
@@ -76,7 +81,7 @@ namespace Harness.Parallel.Worker {
afterFunc && afterFunc();
}
catch (e) {
errors.push({ error: `Error executing after function: ${e.message}`, stack: e.stack, name: namestack.join(" ") });
errors.push({ error: `Error executing after function: ${e.message}`, stack: e.stack, name: [...namestack] });
}
finally {
afterFunc = undefined;
@@ -107,13 +112,12 @@ namespace Harness.Parallel.Worker {
slow() { return this; },
};
namestack.push(name);
name = namestack.join(" ");
if (beforeEachFunc) {
try {
beforeEachFunc();
}
catch (error) {
errors.push({ error: error.message, stack: error.stack, name });
errors.push({ error: error.message, stack: error.stack, name: [...namestack] });
namestack.pop();
return;
}
@@ -124,7 +128,7 @@ namespace Harness.Parallel.Worker {
callback.call(fakeContext);
}
catch (error) {
errors.push({ error: error.message, stack: error.stack, name });
errors.push({ error: error.message, stack: error.stack, name: [...namestack] });
return;
}
finally {
@@ -141,7 +145,7 @@ namespace Harness.Parallel.Worker {
throw new Error(`done() callback called multiple times; ensure it is only called once.`);
}
if (err) {
errors.push({ error: err.toString(), stack: "", name });
errors.push({ error: err.toString(), stack: "", name: [...namestack] });
}
else {
passing++;
@@ -150,14 +154,14 @@ namespace Harness.Parallel.Worker {
});
}
catch (error) {
errors.push({ error: error.message, stack: error.stack, name });
errors.push({ error: error.message, stack: error.stack, name: [...namestack] });
return;
}
finally {
namestack.pop();
}
if (!completed) {
errors.push({ error: "Test completes asynchronously, which is unsupported by the parallel harness", stack: "", name });
errors.push({ error: "Test completes asynchronously, which is unsupported by the parallel harness", stack: "", name: [...namestack] });
}
}
}
@@ -204,7 +208,7 @@ namespace Harness.Parallel.Worker {
}
});
process.on("uncaughtException", error => {
const message: ParallelErrorMessage = { type: "error", payload: { error: error.message, stack: error.stack, name: namestack.join(" ") } };
const message: ParallelErrorMessage = { type: "error", payload: { error: error.message, stack: error.stack, name: [...namestack] } };
try {
process.send(message);
}
+1
View File
@@ -116,6 +116,7 @@
"./unittests/reuseProgramStructure.ts",
"./unittests/moduleResolution.ts",
"./unittests/tsconfigParsing.ts",
"./unittests/builder.ts",
"./unittests/commandLineParsing.ts",
"./unittests/configurationExtension.ts",
"./unittests/convertCompilerOptionsFromJson.ts",
+73
View File
@@ -0,0 +1,73 @@
/// <reference path="reuseProgramStructure.ts" />
namespace ts {
describe("builder", () => {
it("emits dependent files", () => {
const files: NamedSourceText[] = [
{ name: "/a.ts", text: SourceText.New("", 'import { b } from "./b";', "") },
{ name: "/b.ts", text: SourceText.New("", ' import { c } from "./c";', "export const b = c;") },
{ name: "/c.ts", text: SourceText.New("", "", "export const c = 0;") },
];
let program = newProgram(files, ["/a.ts"], {});
const assertChanges = makeAssertChanges(() => program);
assertChanges(["/c.js", "/b.js", "/a.js"]);
program = updateProgramFile(program, "/a.ts", "//comment");
assertChanges(["/a.js"]);
program = updateProgramFile(program, "/b.ts", "export const b = c + 1;");
assertChanges(["/b.js", "/a.js"]);
program = updateProgramFile(program, "/c.ts", "export const c = 1;");
assertChanges(["/c.js", "/b.js"]);
});
it("if emitting all files, emits the changed file first", () => {
const files: NamedSourceText[] = [
{ name: "/a.ts", text: SourceText.New("", "", "namespace A { export const x = 0; }") },
{ name: "/b.ts", text: SourceText.New("", "", "namespace B { export const x = 0; }") },
];
let program = newProgram(files, ["/a.ts", "/b.ts"], {});
const assertChanges = makeAssertChanges(() => program);
assertChanges(["/a.js", "/b.js"]);
program = updateProgramFile(program, "/a.ts", "namespace A { export const x = 1; }");
assertChanges(["/a.js", "/b.js"]);
program = updateProgramFile(program, "/b.ts", "namespace B { export const x = 1; }");
assertChanges(["/b.js", "/a.js"]);
});
});
function makeAssertChanges(getProgram: () => Program): (fileNames: ReadonlyArray<string>) => void {
const builder = createBuilder({
getCanonicalFileName: identity,
getEmitOutput: getFileEmitOutput,
computeHash: identity,
shouldEmitFile: returnTrue,
});
return fileNames => {
const program = getProgram();
builder.updateProgram(program);
const changedFiles = builder.emitChangedFiles(program);
assert.deepEqual(changedFileNames(changedFiles), fileNames);
};
}
function updateProgramFile(program: ProgramWithSourceTexts, fileName: string, fileContent: string): ProgramWithSourceTexts {
return updateProgram(program, program.getRootFileNames(), program.getCompilerOptions(), files => {
updateProgramText(files, fileName, fileContent);
});
}
function changedFileNames(changedFiles: ReadonlyArray<EmitOutputDetailed>): string[] {
return changedFiles.map(f => {
assert.lengthOf(f.outputFiles, 1);
return f.outputFiles[0].name;
});
}
}
+34
View File
@@ -33,6 +33,20 @@ namespace ts {
testExtractConstant("extractConstant_ExpressionStatementExpression",
`[#|"hello"|];`);
testExtractConstant("extractConstant_ExpressionStatementInNestedScope", `
let i = 0;
function F() {
[#|i++|];
}
`);
testExtractConstant("extractConstant_ExpressionStatementConsumesLocal", `
function F() {
let i = 0;
[#|i++|];
}
`);
testExtractConstant("extractConstant_BlockScopes_NoDependencies",
`for (let i = 0; i < 10; i++) {
for (let j = 0; j < 10; j++) {
@@ -200,9 +214,29 @@ const x = [#|2 + 1|];
/* About x */
const x = [#|2 + 1|];
`);
testExtractConstant("extractConstant_ArrowFunction_Block", `
const f = () => {
return [#|2 + 1|];
};`);
testExtractConstant("extractConstant_ArrowFunction_Expression",
`const f = () => [#|2 + 1|];`);
testExtractConstantFailed("extractConstant_Void", `
function f(): void { }
[#|f();|]`);
testExtractConstantFailed("extractConstant_Never", `
function f(): never { }
[#|f();|]`);
});
function testExtractConstant(caption: string, text: string) {
testExtractSymbol(caption, text, "extractConstant", Diagnostics.Extract_constant);
}
function testExtractConstantFailed(caption: string, text: string) {
testExtractSymbolFailed(caption, text, Diagnostics.Extract_constant);
}
}
+1 -1
View File
@@ -135,7 +135,7 @@ namespace ts {
Harness.Baseline.runBaseline(`${baselineFolder}/${caption}${extension}`, () => {
const data: string[] = [];
data.push(`// ==ORIGINAL==`);
data.push(sourceFile.text);
data.push(text.replace("[#|", "/*[#|*/").replace("|]", "/*|]*/"));
for (const action of actions) {
const { renameLocation, edits } = refactor.extractSymbol.getEditsForAction(context, action.name);
assert.lengthOf(edits, 1);
@@ -15,12 +15,12 @@ namespace ts {
sourceText?: SourceText;
}
interface NamedSourceText {
export interface NamedSourceText {
name: string;
text: SourceText;
}
interface ProgramWithSourceTexts extends Program {
export interface ProgramWithSourceTexts extends Program {
sourceTexts?: ReadonlyArray<NamedSourceText>;
host: TestCompilerHost;
}
@@ -29,7 +29,7 @@ namespace ts {
getTrace(): string[];
}
class SourceText implements IScriptSnapshot {
export class SourceText implements IScriptSnapshot {
private fullText: string;
constructor(private references: string,
@@ -103,10 +103,11 @@ namespace ts {
function createSourceFileWithText(fileName: string, sourceText: SourceText, target: ScriptTarget) {
const file = <SourceFileWithText>createSourceFile(fileName, sourceText.getFullText(), target);
file.sourceText = sourceText;
file.version = "" + sourceText.getVersion();
return file;
}
function createTestCompilerHost(texts: ReadonlyArray<NamedSourceText>, target: ScriptTarget, oldProgram?: ProgramWithSourceTexts): TestCompilerHost {
export function createTestCompilerHost(texts: ReadonlyArray<NamedSourceText>, target: ScriptTarget, oldProgram?: ProgramWithSourceTexts): TestCompilerHost {
const files = arrayToMap(texts, t => t.name, t => {
if (oldProgram) {
let oldFile = <SourceFileWithText>oldProgram.getSourceFile(t.name);
@@ -154,7 +155,7 @@ namespace ts {
};
}
function newProgram(texts: NamedSourceText[], rootNames: string[], options: CompilerOptions): ProgramWithSourceTexts {
export function newProgram(texts: NamedSourceText[], rootNames: string[], options: CompilerOptions): ProgramWithSourceTexts {
const host = createTestCompilerHost(texts, options.target);
const program = <ProgramWithSourceTexts>createProgram(rootNames, options, host);
program.sourceTexts = texts;
@@ -162,7 +163,7 @@ namespace ts {
return program;
}
function updateProgram(oldProgram: ProgramWithSourceTexts, rootNames: ReadonlyArray<string>, options: CompilerOptions, updater: (files: NamedSourceText[]) => void, newTexts?: NamedSourceText[]) {
export function updateProgram(oldProgram: ProgramWithSourceTexts, rootNames: ReadonlyArray<string>, options: CompilerOptions, updater: (files: NamedSourceText[]) => void, newTexts?: NamedSourceText[]) {
if (!newTexts) {
newTexts = (<ProgramWithSourceTexts>oldProgram).sourceTexts.slice(0);
}
@@ -174,7 +175,7 @@ namespace ts {
return program;
}
function updateProgramText(files: ReadonlyArray<NamedSourceText>, fileName: string, newProgramText: string) {
export function updateProgramText(files: ReadonlyArray<NamedSourceText>, fileName: string, newProgramText: string) {
const file = find(files, f => f.name === fileName)!;
file.text = file.text.updateProgram(newProgramText);
}
+13 -7
View File
@@ -167,6 +167,8 @@ namespace ts.server {
private typingFiles: SortedReadonlyArray<string>;
private readonly cancellationToken: ThrottledCancellationToken;
public isNonTsProject() {
this.updateGraph();
return allFilesAreJsOrDts(this);
@@ -206,6 +208,7 @@ namespace ts.server {
/*@internal*/public directoryStructureHost: DirectoryStructureHost,
rootDirectoryForResolution: string | undefined) {
this.cancellationToken = new ThrottledCancellationToken(this.projectService.cancellationToken, this.projectService.throttleWaitMilliseconds);
if (!this.compilerOptions) {
this.compilerOptions = getDefaultCompilerOptions();
this.compilerOptions.allowNonTsExtensions = true;
@@ -294,7 +297,7 @@ namespace ts.server {
}
getCancellationToken() {
return this.projectService.cancellationToken;
return this.cancellationToken;
}
getCurrentDirectory(): string {
@@ -417,12 +420,15 @@ namespace ts.server {
private ensureBuilder() {
if (!this.builder) {
this.builder = createBuilder(
this.projectService.toCanonicalFileName,
(_program, sourceFile, emitOnlyDts, isDetailed) => this.getFileEmitOutput(sourceFile, emitOnlyDts, isDetailed),
data => this.projectService.host.createHash(data),
sourceFile => !this.projectService.getScriptInfoForPath(sourceFile.path).isDynamicOrHasMixedContent()
);
this.builder = createBuilder({
getCanonicalFileName: this.projectService.toCanonicalFileName,
getEmitOutput: (_program, sourceFile, emitOnlyDts, isDetailed) =>
this.getFileEmitOutput(sourceFile, emitOnlyDts, isDetailed),
computeHash: data =>
this.projectService.host.createHash(data),
shouldEmitFile: sourceFile =>
!this.projectService.getScriptInfoForPath(sourceFile.path).isDynamicOrHasMixedContent()
});
}
}
+48 -69
View File
@@ -265,104 +265,83 @@ namespace ts.DocumentHighlights {
}
function getModifierOccurrences(modifier: SyntaxKind, declaration: Node): Node[] {
const container = declaration.parent;
// Make sure we only highlight the keyword when it makes sense to do so.
if (isAccessibilityModifier(modifier)) {
if (!(container.kind === SyntaxKind.ClassDeclaration ||
container.kind === SyntaxKind.ClassExpression ||
(declaration.kind === SyntaxKind.Parameter && hasKind(container, SyntaxKind.Constructor)))) {
return undefined;
}
}
else if (modifier === SyntaxKind.StaticKeyword) {
if (!(container.kind === SyntaxKind.ClassDeclaration || container.kind === SyntaxKind.ClassExpression)) {
return undefined;
}
}
else if (modifier === SyntaxKind.ExportKeyword || modifier === SyntaxKind.DeclareKeyword) {
if (!(container.kind === SyntaxKind.ModuleBlock || container.kind === SyntaxKind.SourceFile)) {
return undefined;
}
}
else if (modifier === SyntaxKind.AbstractKeyword) {
if (!(container.kind === SyntaxKind.ClassDeclaration || declaration.kind === SyntaxKind.ClassDeclaration)) {
return undefined;
}
}
else {
// unsupported modifier
if (!isLegalModifier(modifier, declaration)) {
return undefined;
}
const keywords: Node[] = [];
const modifierFlag: ModifierFlags = getFlagFromModifier(modifier);
const modifierFlag = modifierToFlag(modifier);
return mapDefined(getNodesToSearchForModifier(declaration, modifierFlag), node => {
if (getModifierFlags(node) & modifierFlag) {
const mod = find(node.modifiers, m => m.kind === modifier);
Debug.assert(!!mod);
return mod;
}
});
}
let nodes: ReadonlyArray<Node>;
function getNodesToSearchForModifier(declaration: Node, modifierFlag: ModifierFlags): ReadonlyArray<Node> {
const container = declaration.parent;
switch (container.kind) {
case SyntaxKind.ModuleBlock:
case SyntaxKind.SourceFile:
case SyntaxKind.Block:
case SyntaxKind.CaseClause:
case SyntaxKind.DefaultClause:
// Container is either a class declaration or the declaration is a classDeclaration
if (modifierFlag & ModifierFlags.Abstract) {
nodes = [...(<ClassDeclaration>declaration).members, declaration];
return [...(<ClassDeclaration>declaration).members, declaration];
}
else {
nodes = (<Block>container).statements;
return (<ModuleBlock | SourceFile | Block | CaseClause | DefaultClause>container).statements;
}
break;
case SyntaxKind.Constructor:
nodes = [...(<ConstructorDeclaration>container).parameters, ...(<ClassDeclaration>container.parent).members];
break;
return [...(<ConstructorDeclaration>container).parameters, ...(<ClassDeclaration>container.parent).members];
case SyntaxKind.ClassDeclaration:
case SyntaxKind.ClassExpression:
nodes = (<ClassLikeDeclaration>container).members;
const nodes = (<ClassLikeDeclaration>container).members;
// If we're an accessibility modifier, we're in an instance member and should search
// the constructor's parameter list for instance members as well.
if (modifierFlag & ModifierFlags.AccessibilityModifier) {
const constructor = forEach((<ClassLikeDeclaration>container).members, member => {
return member.kind === SyntaxKind.Constructor && <ConstructorDeclaration>member;
});
const constructor = find((<ClassLikeDeclaration>container).members, isConstructorDeclaration);
if (constructor) {
nodes = [...nodes, ...constructor.parameters];
return [...nodes, ...constructor.parameters];
}
}
else if (modifierFlag & ModifierFlags.Abstract) {
nodes = [...nodes, container];
return [...nodes, container];
}
break;
return nodes;
default:
Debug.fail("Invalid container kind.");
}
}
forEach(nodes, node => {
if (getModifierFlags(node) & modifierFlag) {
forEach(node.modifiers, child => pushKeywordIf(keywords, child, modifier));
}
});
return keywords;
function getFlagFromModifier(modifier: SyntaxKind) {
switch (modifier) {
case SyntaxKind.PublicKeyword:
return ModifierFlags.Public;
case SyntaxKind.PrivateKeyword:
return ModifierFlags.Private;
case SyntaxKind.ProtectedKeyword:
return ModifierFlags.Protected;
case SyntaxKind.StaticKeyword:
return ModifierFlags.Static;
case SyntaxKind.ExportKeyword:
return ModifierFlags.Export;
case SyntaxKind.DeclareKeyword:
return ModifierFlags.Ambient;
case SyntaxKind.AbstractKeyword:
return ModifierFlags.Abstract;
default:
Debug.fail();
}
function isLegalModifier(modifier: SyntaxKind, declaration: Node): boolean {
const container = declaration.parent;
switch (modifier) {
case SyntaxKind.PrivateKeyword:
case SyntaxKind.ProtectedKeyword:
case SyntaxKind.PublicKeyword:
switch (container.kind) {
case SyntaxKind.ClassDeclaration:
case SyntaxKind.ClassExpression:
return true;
case SyntaxKind.Constructor:
return declaration.kind === SyntaxKind.Parameter;
default:
return false;
}
case SyntaxKind.StaticKeyword:
return container.kind === SyntaxKind.ClassDeclaration || container.kind === SyntaxKind.ClassExpression;
case SyntaxKind.ExportKeyword:
case SyntaxKind.DeclareKeyword:
return container.kind === SyntaxKind.ModuleBlock || container.kind === SyntaxKind.SourceFile;
case SyntaxKind.AbstractKeyword:
return container.kind === SyntaxKind.ClassDeclaration || declaration.kind === SyntaxKind.ClassDeclaration;
default:
return false;
}
}
+1 -1
View File
@@ -1,7 +1,7 @@
/* @internal */
namespace ts.OutliningElementsCollector {
const collapseText = "...";
const maxDepth = 20;
const maxDepth = 40;
const defaultLabel = "#region";
const regionMatch = new RegExp("^\\s*//\\s*#(end)?region(?:\\s+(.*))?$");
+78 -30
View File
@@ -5,7 +5,7 @@
namespace ts.refactor.extractSymbol {
const extractSymbol: Refactor = {
name: "Extract Symbol",
description: Diagnostics.Extract_symbol.message,
description: getLocaleSpecificMessage(Diagnostics.Extract_symbol),
getAvailableActions,
getEditsForAction,
};
@@ -43,7 +43,7 @@ namespace ts.refactor.extractSymbol {
// Don't issue refactorings with duplicated names.
// Scopes come back in "innermost first" order, so extractions will
// preferentially go into nearer scopes
const description = formatStringFromArgs(Diagnostics.Extract_to_0_in_1.message, [functionExtraction.description, functionExtraction.scopeDescription]);
const description = functionExtraction.description;
if (!usedFunctionNames.has(description)) {
usedFunctionNames.set(description, true);
functionActions.push({
@@ -58,7 +58,7 @@ namespace ts.refactor.extractSymbol {
// Don't issue refactorings with duplicated names.
// Scopes come back in "innermost first" order, so extractions will
// preferentially go into nearer scopes
const description = formatStringFromArgs(Diagnostics.Extract_to_0_in_1.message, [constantExtraction.description, constantExtraction.scopeDescription]);
const description = constantExtraction.description;
if (!usedConstantNames.has(description)) {
usedConstantNames.set(description, true);
constantActions.push({
@@ -78,7 +78,7 @@ namespace ts.refactor.extractSymbol {
if (functionActions.length) {
infos.push({
name: extractSymbol.name,
description: Diagnostics.Extract_function.message,
description: getLocaleSpecificMessage(Diagnostics.Extract_function),
actions: functionActions
});
}
@@ -86,7 +86,7 @@ namespace ts.refactor.extractSymbol {
if (constantActions.length) {
infos.push({
name: extractSymbol.name,
description: Diagnostics.Extract_constant.message,
description: getLocaleSpecificMessage(Diagnostics.Extract_constant),
actions: constantActions
});
}
@@ -127,6 +127,7 @@ namespace ts.refactor.extractSymbol {
export const CannotExtractSuper: DiagnosticMessage = createMessage("Cannot extract super call.");
export const CannotExtractEmpty: DiagnosticMessage = createMessage("Cannot extract empty range.");
export const ExpressionExpected: DiagnosticMessage = createMessage("expression expected.");
export const UselessConstantType: DiagnosticMessage = createMessage("No reason to extract constant of type.");
export const StatementOrExpressionExpected: DiagnosticMessage = createMessage("Statement or expression expected.");
export const CannotExtractRangeContainingConditionalBreakOrContinueStatements: DiagnosticMessage = createMessage("Cannot extract range containing conditional break or continue statements.");
export const CannotExtractRangeContainingConditionalReturnStatement: DiagnosticMessage = createMessage("Cannot extract range containing conditional return statement.");
@@ -142,6 +143,7 @@ namespace ts.refactor.extractSymbol {
export const CannotAccessVariablesFromNestedScopes = createMessage("Cannot access variables from nested scopes");
export const CannotExtractToOtherFunctionLike = createMessage("Cannot extract method to a function-like scope that is not a function");
export const CannotExtractToJSClass = createMessage("Cannot extract constant to a class scope in JS");
export const CannotExtractToExpressionArrowFunction = createMessage("Cannot extract constant to an arrow function without a block");
}
enum RangeFacts {
@@ -523,7 +525,6 @@ namespace ts.refactor.extractSymbol {
interface Extraction {
readonly description: string;
readonly scopeDescription: string;
readonly errors: ReadonlyArray<Diagnostic>;
}
@@ -541,23 +542,43 @@ namespace ts.refactor.extractSymbol {
const { scopes, readsAndWrites: { functionErrorsPerScope, constantErrorsPerScope } } = getPossibleExtractionsWorker(targetRange, context);
// Need the inner type annotation to avoid https://github.com/Microsoft/TypeScript/issues/7547
const extractions = scopes.map((scope, i): ScopeExtractions => {
const functionDescriptionPart = getDescriptionForFunctionInScope(scope);
const constantDescriptionPart = getDescriptionForConstantInScope(scope);
const scopeDescription = isFunctionLikeDeclaration(scope)
? getDescriptionForFunctionLikeDeclaration(scope)
: isClassLike(scope)
? getDescriptionForClassLikeDeclaration(scope)
: getDescriptionForModuleLikeDeclaration(scope);
let functionDescription: string;
let constantDescription: string;
if (scopeDescription === SpecialScope.Global) {
functionDescription = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Extract_to_0_in_1_scope), [functionDescriptionPart, "global"]);
constantDescription = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Extract_to_0_in_1_scope), [constantDescriptionPart, "global"]);
}
else if (scopeDescription === SpecialScope.Module) {
functionDescription = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Extract_to_0_in_1_scope), [functionDescriptionPart, "module"]);
constantDescription = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Extract_to_0_in_1_scope), [constantDescriptionPart, "module"]);
}
else {
functionDescription = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Extract_to_0_in_1), [functionDescriptionPart, scopeDescription]);
constantDescription = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Extract_to_0_in_1), [constantDescriptionPart, scopeDescription]);
}
// Customize the phrasing for the innermost scope to increase clarity.
if (i === 0 && !isClassLike(scope)) {
constantDescription = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Extract_to_0_in_enclosing_scope), [constantDescriptionPart]);
}
return {
functionExtraction: {
description: getDescriptionForFunctionInScope(scope),
description: functionDescription,
errors: functionErrorsPerScope[i],
scopeDescription,
},
constantExtraction: {
description: getDescriptionForConstantInScope(scope),
description: constantDescription,
errors: constantErrorsPerScope[i],
scopeDescription: (i === 0 && !isClassLike(scope))
? "enclosing scope" // Like "global scope" and "module scope", this is not localized.
: scopeDescription,
},
};
});
@@ -626,10 +647,15 @@ namespace ts.refactor.extractSymbol {
? `class '${scope.name.text}'`
: scope.name ? `class expression '${scope.name.text}'` : "anonymous class expression";
}
function getDescriptionForModuleLikeDeclaration(scope: SourceFile | ModuleBlock): string {
function getDescriptionForModuleLikeDeclaration(scope: SourceFile | ModuleBlock): string | SpecialScope {
return scope.kind === SyntaxKind.ModuleBlock
? `namespace '${scope.parent.name.getText()}'`
: scope.externalModuleIndicator ? "module scope" : "global scope";
: scope.externalModuleIndicator ? SpecialScope.Module : SpecialScope.Global;
}
const enum SpecialScope {
Module,
Global,
}
function getUniqueName(baseName: string, fileText: string): string {
@@ -911,12 +937,13 @@ namespace ts.refactor.extractSymbol {
const localReference = createIdentifier(localNameText);
changeTracker.replaceRange(context.file, { pos: node.getStart(), end: node.end }, localReference);
}
else if (node.parent.kind === SyntaxKind.ExpressionStatement) {
// If the parent is an expression statement, replace the statement with the declaration.
else if (node.parent.kind === SyntaxKind.ExpressionStatement && scope === findAncestor(node, isScope)) {
// If the parent is an expression statement and the target scope is the immediately enclosing one,
// replace the statement with the declaration.
const newVariableStatement = createVariableStatement(
/*modifiers*/ undefined,
createVariableDeclarationList([newVariableDeclaration], NodeFlags.Const));
changeTracker.replaceNodeWithNodes(context.file, node.parent, [newVariableStatement], { nodeSeparator: context.newLineCharacter });
changeTracker.replaceRange(context.file, { pos: node.parent.getStart(), end: node.parent.end }, newVariableStatement);
}
else {
const newVariableStatement = createVariableStatement(
@@ -940,8 +967,14 @@ namespace ts.refactor.extractSymbol {
}
// Consume
const localReference = createIdentifier(localNameText);
changeTracker.replaceRange(context.file, { pos: node.getStart(), end: node.end }, localReference);
if (node.parent.kind === SyntaxKind.ExpressionStatement) {
// If the parent is an expression statement, delete it.
changeTracker.deleteRange(context.file, { pos: node.parent.getStart(), end: node.parent.end });
}
else {
const localReference = createIdentifier(localNameText);
changeTracker.replaceRange(context.file, { pos: node.getStart(), end: node.end }, localReference);
}
}
}
@@ -1270,11 +1303,23 @@ namespace ts.refactor.extractSymbol {
const constantErrorsPerScope: Diagnostic[][] = [];
const visibleDeclarationsInExtractedRange: Symbol[] = [];
const expressionDiagnostic =
isReadonlyArray(targetRange.range) && !(targetRange.range.length === 1 && isExpressionStatement(targetRange.range[0]))
? ((start, end) => createFileDiagnostic(sourceFile, start, end - start, Messages.ExpressionExpected))(first(targetRange.range).getStart(), last(targetRange.range).end)
const expression = !isReadonlyArray(targetRange.range)
? targetRange.range
: targetRange.range.length === 1 && isExpressionStatement(targetRange.range[0])
? (targetRange.range[0] as ExpressionStatement).expression
: undefined;
let expressionDiagnostic: Diagnostic | undefined = undefined;
if (expression === undefined) {
const statements = targetRange.range as ReadonlyArray<Statement>;
const start = first(statements).getStart();
const end = last(statements).end;
expressionDiagnostic = createFileDiagnostic(sourceFile, start, end - start, Messages.ExpressionExpected);
}
else if (checker.getTypeAtLocation(expression).flags & (TypeFlags.Void | TypeFlags.Never)) {
expressionDiagnostic = createDiagnosticForNode(expression, Messages.UselessConstantType);
}
// initialize results
for (const scope of scopes) {
usagesPerScope.push({ usages: createMap<UsageEntry>(), typeParameterUsages: createMap<TypeParameter>(), substitutions: createMap<() => Expression>() });
@@ -1292,6 +1337,10 @@ namespace ts.refactor.extractSymbol {
if (isClassLike(scope) && isInJavaScriptFile(scope)) {
constantErrors.push(createDiagnosticForNode(scope, Messages.CannotExtractToJSClass));
}
if (isArrowFunction(scope) && !isBlock(scope.body)) {
// TODO (https://github.com/Microsoft/TypeScript/issues/18924): allow this
constantErrors.push(createDiagnosticForNode(scope, Messages.CannotExtractToExpressionArrowFunction));
}
constantErrorsPerScope.push(constantErrors);
}
@@ -1344,14 +1393,13 @@ namespace ts.refactor.extractSymbol {
}
for (let i = 0; i < scopes.length; i++) {
if (!isReadonlyArray(targetRange.range)) {
const scopeUsages = usagesPerScope[i];
// Special case: in the innermost scope, all usages are available.
// (The computed value reflects the value at the top-level of the scope, but the
// local will actually be declared at the same level as the extracted expression).
if (i > 0 && (scopeUsages.usages.size > 0 || scopeUsages.typeParameterUsages.size > 0)) {
constantErrorsPerScope[i].push(createDiagnosticForNode(targetRange.range, Messages.CannotAccessVariablesFromNestedScopes));
}
const scopeUsages = usagesPerScope[i];
// Special case: in the innermost scope, all usages are available.
// (The computed value reflects the value at the top-level of the scope, but the
// local will actually be declared at the same level as the extracted expression).
if (i > 0 && (scopeUsages.usages.size > 0 || scopeUsages.typeParameterUsages.size > 0)) {
const errorNode = isReadonlyArray(targetRange.range) ? targetRange.range[0] : targetRange.range;
constantErrorsPerScope[i].push(createDiagnosticForNode(errorNode, Messages.CannotAccessVariablesFromNestedScopes));
}
let hasWrite = false;
+2 -1
View File
@@ -7103,6 +7103,7 @@ declare namespace ts.server {
*/
private projectStateVersion;
private typingFiles;
private readonly cancellationToken;
isNonTsProject(): boolean;
isJsOnlyProject(): boolean;
getCachedUnresolvedImportsPerFile_TestOnly(): UnresolvedImportsMap;
@@ -7115,7 +7116,7 @@ declare namespace ts.server {
getScriptKind(fileName: string): ScriptKind;
getScriptVersion(filename: string): string;
getScriptSnapshot(filename: string): IScriptSnapshot;
getCancellationToken(): HostCancellationToken;
getCancellationToken(): ThrottledCancellationToken;
getCurrentDirectory(): string;
getDefaultLibFileName(): string;
useCaseSensitiveFileNames(): boolean;
@@ -1,18 +1,18 @@
tests/cases/compiler/immutable.d.ts(341,22): error TS2430: Interface 'Keyed<K, V>' incorrectly extends interface 'Collection<K, V>'.
tests/cases/compiler/immutable.ts(341,22): error TS2430: Interface 'Keyed<K, V>' incorrectly extends interface 'Collection<K, V>'.
Types of property 'toSeq' are incompatible.
Type '() => Keyed<K, V>' is not assignable to type '() => this'.
Type 'Keyed<K, V>' is not assignable to type 'this'.
tests/cases/compiler/immutable.d.ts(359,22): error TS2430: Interface 'Indexed<T>' incorrectly extends interface 'Collection<number, T>'.
tests/cases/compiler/immutable.ts(359,22): error TS2430: Interface 'Indexed<T>' incorrectly extends interface 'Collection<number, T>'.
Types of property 'toSeq' are incompatible.
Type '() => Indexed<T>' is not assignable to type '() => this'.
Type 'Indexed<T>' is not assignable to type 'this'.
tests/cases/compiler/immutable.d.ts(391,22): error TS2430: Interface 'Set<T>' incorrectly extends interface 'Collection<never, T>'.
tests/cases/compiler/immutable.ts(391,22): error TS2430: Interface 'Set<T>' incorrectly extends interface 'Collection<never, T>'.
Types of property 'toSeq' are incompatible.
Type '() => Set<T>' is not assignable to type '() => this'.
Type 'Set<T>' is not assignable to type 'this'.
==== tests/cases/compiler/complex.d.ts (0 errors) ====
==== tests/cases/compiler/complex.ts (0 errors) ====
interface Ara<T> { t: T }
interface Collection<K, V> {
map<M>(mapper: (value: V, key: K, iter: this) => M): Collection<K, M>;
@@ -33,7 +33,7 @@ tests/cases/compiler/immutable.d.ts(391,22): error TS2430: Interface 'Set<T>' in
flatMap<M>(mapper: (value: T, key: void, iter: this) => Ara<M>, context?: any): N2<M>;
toSeq(): N2<T>;
}
==== tests/cases/compiler/immutable.d.ts (3 errors) ====
==== tests/cases/compiler/immutable.ts (3 errors) ====
// Test that complex recursive collections can pass the `extends` assignability check without
// running out of memory. This bug was exposed in Typescript 2.4 when more generic signatures
// started being checked.
@@ -0,0 +1,538 @@
//// [tests/cases/compiler/complexRecursiveCollections.ts] ////
//// [complex.ts]
interface Ara<T> { t: T }
interface Collection<K, V> {
map<M>(mapper: (value: V, key: K, iter: this) => M): Collection<K, M>;
flatMap<M>(mapper: (value: V, key: K, iter: this) => Ara<M>, context?: any): Collection<K, M>;
// these seem necessary to push it over the top for memory usage
reduce<R>(reducer: (reduction: R, value: V, key: K, iter: this) => R, initialReduction: R, context?: any): R;
reduce<R>(reducer: (reduction: V | R, value: V, key: K, iter: this) => R): R;
toSeq(): Seq<K, V>;
}
interface Seq<K, V> extends Collection<K, V> {
}
interface N1<T> extends Collection<void, T> {
map<M>(mapper: (value: T, key: void, iter: this) => M): N1<M>;
flatMap<M>(mapper: (value: T, key: void, iter: this) => Ara<M>, context?: any): N1<M>;
}
interface N2<T> extends N1<T> {
map<M>(mapper: (value: T, key: void, iter: this) => M): N2<M>;
flatMap<M>(mapper: (value: T, key: void, iter: this) => Ara<M>, context?: any): N2<M>;
toSeq(): N2<T>;
}
//// [immutable.ts]
// Test that complex recursive collections can pass the `extends` assignability check without
// running out of memory. This bug was exposed in Typescript 2.4 when more generic signatures
// started being checked.
declare module Immutable {
export function fromJS(jsValue: any, reviver?: (key: string | number, sequence: Collection.Keyed<string, any> | Collection.Indexed<any>, path?: Array<string | number>) => any): any;
export function is(first: any, second: any): boolean;
export function hash(value: any): number;
export function isImmutable(maybeImmutable: any): maybeImmutable is Collection<any, any>;
export function isCollection(maybeCollection: any): maybeCollection is Collection<any, any>;
export function isKeyed(maybeKeyed: any): maybeKeyed is Collection.Keyed<any, any>;
export function isIndexed(maybeIndexed: any): maybeIndexed is Collection.Indexed<any>;
export function isAssociative(maybeAssociative: any): maybeAssociative is Collection.Keyed<any, any> | Collection.Indexed<any>;
export function isOrdered(maybeOrdered: any): boolean;
export function isValueObject(maybeValue: any): maybeValue is ValueObject;
export interface ValueObject {
equals(other: any): boolean;
hashCode(): number;
}
export module List {
function isList(maybeList: any): maybeList is List<any>;
function of<T>(...values: Array<T>): List<T>;
}
export function List(): List<any>;
export function List<T>(): List<T>;
export function List<T>(collection: Iterable<T>): List<T>;
export interface List<T> extends Collection.Indexed<T> {
// Persistent changes
set(index: number, value: T): List<T>;
delete(index: number): List<T>;
remove(index: number): List<T>;
insert(index: number, value: T): List<T>;
clear(): List<T>;
push(...values: Array<T>): List<T>;
pop(): List<T>;
unshift(...values: Array<T>): List<T>;
shift(): List<T>;
update(index: number, notSetValue: T, updater: (value: T) => T): this;
update(index: number, updater: (value: T) => T): this;
update<R>(updater: (value: this) => R): R;
merge(...collections: Array<Collection.Indexed<T> | Array<T>>): this;
mergeWith(merger: (oldVal: T, newVal: T, key: number) => T, ...collections: Array<Collection.Indexed<T> | Array<T>>): this;
mergeDeep(...collections: Array<Collection.Indexed<T> | Array<T>>): this;
mergeDeepWith(merger: (oldVal: T, newVal: T, key: number) => T, ...collections: Array<Collection.Indexed<T> | Array<T>>): this;
setSize(size: number): List<T>;
// Deep persistent changes
setIn(keyPath: Iterable<any>, value: any): this;
deleteIn(keyPath: Iterable<any>): this;
removeIn(keyPath: Iterable<any>): this;
updateIn(keyPath: Iterable<any>, notSetValue: any, updater: (value: any) => any): this;
updateIn(keyPath: Iterable<any>, updater: (value: any) => any): this;
mergeIn(keyPath: Iterable<any>, ...collections: Array<any>): this;
mergeDeepIn(keyPath: Iterable<any>, ...collections: Array<any>): this;
// Transient changes
withMutations(mutator: (mutable: this) => any): this;
asMutable(): this;
asImmutable(): this;
// Sequence algorithms
concat<C>(...valuesOrCollections: Array<Iterable<C> | C>): List<T | C>;
map<M>(mapper: (value: T, key: number, iter: this) => M, context?: any): List<M>;
flatMap<M>(mapper: (value: T, key: number, iter: this) => Iterable<M>, context?: any): List<M>;
filter<F extends T>(predicate: (value: T, index: number, iter: this) => value is F, context?: any): List<F>;
filter(predicate: (value: T, index: number, iter: this) => any, context?: any): this;
}
export module Map {
function isMap(maybeMap: any): maybeMap is Map<any, any>;
function of(...keyValues: Array<any>): Map<any, any>;
}
export function Map<K, V>(collection: Iterable<[K, V]>): Map<K, V>;
export function Map<T>(collection: Iterable<Iterable<T>>): Map<T, T>;
export function Map<V>(obj: {[key: string]: V}): Map<string, V>;
export function Map<K, V>(): Map<K, V>;
export function Map(): Map<any, any>;
export interface Map<K, V> extends Collection.Keyed<K, V> {
// Persistent changes
set(key: K, value: V): this;
delete(key: K): this;
remove(key: K): this;
deleteAll(keys: Iterable<K>): this;
removeAll(keys: Iterable<K>): this;
clear(): this;
update(key: K, notSetValue: V, updater: (value: V) => V): this;
update(key: K, updater: (value: V) => V): this;
update<R>(updater: (value: this) => R): R;
merge(...collections: Array<Collection<K, V> | {[key: string]: V}>): this;
mergeWith(merger: (oldVal: V, newVal: V, key: K) => V, ...collections: Array<Collection<K, V> | {[key: string]: V}>): this;
mergeDeep(...collections: Array<Collection<K, V> | {[key: string]: V}>): this;
mergeDeepWith(merger: (oldVal: V, newVal: V, key: K) => V, ...collections: Array<Collection<K, V> | {[key: string]: V}>): this;
// Deep persistent changes
setIn(keyPath: Iterable<any>, value: any): this;
deleteIn(keyPath: Iterable<any>): this;
removeIn(keyPath: Iterable<any>): this;
updateIn(keyPath: Iterable<any>, notSetValue: any, updater: (value: any) => any): this;
updateIn(keyPath: Iterable<any>, updater: (value: any) => any): this;
mergeIn(keyPath: Iterable<any>, ...collections: Array<any>): this;
mergeDeepIn(keyPath: Iterable<any>, ...collections: Array<any>): this;
// Transient changes
withMutations(mutator: (mutable: this) => any): this;
asMutable(): this;
asImmutable(): this;
// Sequence algorithms
concat<KC, VC>(...collections: Array<Iterable<[KC, VC]>>): Map<K | KC, V | VC>;
concat<C>(...collections: Array<{[key: string]: C}>): Map<K | string, V | C>;
map<M>(mapper: (value: V, key: K, iter: this) => M, context?: any): Map<K, M>;
mapKeys<M>(mapper: (key: K, value: V, iter: this) => M, context?: any): Map<M, V>;
mapEntries<KM, VM>(mapper: (entry: [K, V], index: number, iter: this) => [KM, VM], context?: any): Map<KM, VM>;
flatMap<M>(mapper: (value: V, key: K, iter: this) => Iterable<M>, context?: any): Map<any, any>;
filter<F extends V>(predicate: (value: V, key: K, iter: this) => value is F, context?: any): Map<K, F>;
filter(predicate: (value: V, key: K, iter: this) => any, context?: any): this;
}
export module OrderedMap {
function isOrderedMap(maybeOrderedMap: any): maybeOrderedMap is OrderedMap<any, any>;
}
export function OrderedMap<K, V>(collection: Iterable<[K, V]>): OrderedMap<K, V>;
export function OrderedMap<T>(collection: Iterable<Iterable<T>>): OrderedMap<T, T>;
export function OrderedMap<V>(obj: {[key: string]: V}): OrderedMap<string, V>;
export function OrderedMap<K, V>(): OrderedMap<K, V>;
export function OrderedMap(): OrderedMap<any, any>;
export interface OrderedMap<K, V> extends Map<K, V> {
// Sequence algorithms
concat<KC, VC>(...collections: Array<Iterable<[KC, VC]>>): OrderedMap<K | KC, V | VC>;
concat<C>(...collections: Array<{[key: string]: C}>): OrderedMap<K | string, V | C>;
map<M>(mapper: (value: V, key: K, iter: this) => M, context?: any): OrderedMap<K, M>;
mapKeys<M>(mapper: (key: K, value: V, iter: this) => M, context?: any): OrderedMap<M, V>;
mapEntries<KM, VM>(mapper: (entry: [K, V], index: number, iter: this) => [KM, VM], context?: any): OrderedMap<KM, VM>;
flatMap<M>(mapper: (value: V, key: K, iter: this) => Iterable<M>, context?: any): OrderedMap<any, any>;
filter<F extends V>(predicate: (value: V, key: K, iter: this) => value is F, context?: any): OrderedMap<K, F>;
filter(predicate: (value: V, key: K, iter: this) => any, context?: any): this;
}
export module Set {
function isSet(maybeSet: any): maybeSet is Set<any>;
function of<T>(...values: Array<T>): Set<T>;
function fromKeys<T>(iter: Collection<T, any>): Set<T>;
function fromKeys(obj: {[key: string]: any}): Set<string>;
function intersect<T>(sets: Iterable<Iterable<T>>): Set<T>;
function union<T>(sets: Iterable<Iterable<T>>): Set<T>;
}
export function Set(): Set<any>;
export function Set<T>(): Set<T>;
export function Set<T>(collection: Iterable<T>): Set<T>;
export interface Set<T> extends Collection.Set<T> {
// Persistent changes
add(value: T): this;
delete(value: T): this;
remove(value: T): this;
clear(): this;
union(...collections: Array<Collection<any, T> | Array<T>>): this;
merge(...collections: Array<Collection<any, T> | Array<T>>): this;
intersect(...collections: Array<Collection<any, T> | Array<T>>): this;
subtract(...collections: Array<Collection<any, T> | Array<T>>): this;
// Transient changes
withMutations(mutator: (mutable: this) => any): this;
asMutable(): this;
asImmutable(): this;
// Sequence algorithms
concat<C>(...valuesOrCollections: Array<Iterable<C> | C>): Set<T | C>;
map<M>(mapper: (value: T, key: never, iter: this) => M, context?: any): Set<M>;
flatMap<M>(mapper: (value: T, key: never, iter: this) => Iterable<M>, context?: any): Set<M>;
filter<F extends T>(predicate: (value: T, key: never, iter: this) => value is F, context?: any): Set<F>;
filter(predicate: (value: T, key: never, iter: this) => any, context?: any): this;
}
export module OrderedSet {
function isOrderedSet(maybeOrderedSet: any): boolean;
function of<T>(...values: Array<T>): OrderedSet<T>;
function fromKeys<T>(iter: Collection<T, any>): OrderedSet<T>;
function fromKeys(obj: {[key: string]: any}): OrderedSet<string>;
}
export function OrderedSet(): OrderedSet<any>;
export function OrderedSet<T>(): OrderedSet<T>;
export function OrderedSet<T>(collection: Iterable<T>): OrderedSet<T>;
export interface OrderedSet<T> extends Set<T> {
// Sequence algorithms
concat<C>(...valuesOrCollections: Array<Iterable<C> | C>): OrderedSet<T | C>;
map<M>(mapper: (value: T, key: never, iter: this) => M, context?: any): OrderedSet<M>;
flatMap<M>(mapper: (value: T, key: never, iter: this) => Iterable<M>, context?: any): OrderedSet<M>;
filter<F extends T>(predicate: (value: T, key: never, iter: this) => value is F, context?: any): OrderedSet<F>;
filter(predicate: (value: T, key: never, iter: this) => any, context?: any): this;
zip(...collections: Array<Collection<any, any>>): OrderedSet<any>;
zipWith<U, Z>(zipper: (value: T, otherValue: U) => Z, otherCollection: Collection<any, U>): OrderedSet<Z>;
zipWith<U, V, Z>(zipper: (value: T, otherValue: U, thirdValue: V) => Z, otherCollection: Collection<any, U>, thirdCollection: Collection<any, V>): OrderedSet<Z>;
zipWith<Z>(zipper: (...any: Array<any>) => Z, ...collections: Array<Collection<any, any>>): OrderedSet<Z>;
}
export module Stack {
function isStack(maybeStack: any): maybeStack is Stack<any>;
function of<T>(...values: Array<T>): Stack<T>;
}
export function Stack(): Stack<any>;
export function Stack<T>(): Stack<T>;
export function Stack<T>(collection: Iterable<T>): Stack<T>;
export interface Stack<T> extends Collection.Indexed<T> {
// Reading values
peek(): T | undefined;
// Persistent changes
clear(): Stack<T>;
unshift(...values: Array<T>): Stack<T>;
unshiftAll(iter: Iterable<T>): Stack<T>;
shift(): Stack<T>;
push(...values: Array<T>): Stack<T>;
pushAll(iter: Iterable<T>): Stack<T>;
pop(): Stack<T>;
// Transient changes
withMutations(mutator: (mutable: this) => any): this;
asMutable(): this;
asImmutable(): this;
// Sequence algorithms
concat<C>(...valuesOrCollections: Array<Iterable<C> | C>): Stack<T | C>;
map<M>(mapper: (value: T, key: number, iter: this) => M, context?: any): Stack<M>;
flatMap<M>(mapper: (value: T, key: number, iter: this) => Iterable<M>, context?: any): Stack<M>;
filter<F extends T>(predicate: (value: T, index: number, iter: this) => value is F, context?: any): Set<F>;
filter(predicate: (value: T, index: number, iter: this) => any, context?: any): this;
}
export function Range(start?: number, end?: number, step?: number): Seq.Indexed<number>;
export function Repeat<T>(value: T, times?: number): Seq.Indexed<T>;
export module Record {
export function isRecord(maybeRecord: any): maybeRecord is Record.Instance<any>;
export function getDescriptiveName(record: Instance<any>): string;
export interface Class<T extends Object> {
(values?: Partial<T> | Iterable<[string, any]>): Instance<T> & Readonly<T>;
new (values?: Partial<T> | Iterable<[string, any]>): Instance<T> & Readonly<T>;
}
export interface Instance<T extends Object> {
readonly size: number;
// Reading values
has(key: string): boolean;
get<K extends keyof T>(key: K): T[K];
// Reading deep values
hasIn(keyPath: Iterable<any>): boolean;
getIn(keyPath: Iterable<any>): any;
// Value equality
equals(other: any): boolean;
hashCode(): number;
// Persistent changes
set<K extends keyof T>(key: K, value: T[K]): this;
update<K extends keyof T>(key: K, updater: (value: T[K]) => T[K]): this;
merge(...collections: Array<Partial<T> | Iterable<[string, any]>>): this;
mergeDeep(...collections: Array<Partial<T> | Iterable<[string, any]>>): this;
mergeWith(merger: (oldVal: any, newVal: any, key: keyof T) => any, ...collections: Array<Partial<T> | Iterable<[string, any]>>): this;
mergeDeepWith(merger: (oldVal: any, newVal: any, key: any) => any, ...collections: Array<Partial<T> | Iterable<[string, any]>>): this;
delete<K extends keyof T>(key: K): this;
remove<K extends keyof T>(key: K): this;
clear(): this;
// Deep persistent changes
setIn(keyPath: Iterable<any>, value: any): this;
updateIn(keyPath: Iterable<any>, updater: (value: any) => any): this;
mergeIn(keyPath: Iterable<any>, ...collections: Array<any>): this;
mergeDeepIn(keyPath: Iterable<any>, ...collections: Array<any>): this;
deleteIn(keyPath: Iterable<any>): this;
removeIn(keyPath: Iterable<any>): this;
// Conversion to JavaScript types
toJS(): { [K in keyof T]: any };
toJSON(): T;
toObject(): T;
// Transient changes
withMutations(mutator: (mutable: this) => any): this;
asMutable(): this;
asImmutable(): this;
// Sequence algorithms
toSeq(): Seq.Keyed<keyof T, T[keyof T]>;
[Symbol.iterator](): IterableIterator<[keyof T, T[keyof T]]>;
}
}
export function Record<T>(defaultValues: T, name?: string): Record.Class<T>;
export module Seq {
function isSeq(maybeSeq: any): maybeSeq is Seq.Indexed<any> | Seq.Keyed<any, any>;
function of<T>(...values: Array<T>): Seq.Indexed<T>;
export module Keyed {}
export function Keyed<K, V>(collection: Iterable<[K, V]>): Seq.Keyed<K, V>;
export function Keyed<V>(obj: {[key: string]: V}): Seq.Keyed<string, V>;
export function Keyed<K, V>(): Seq.Keyed<K, V>;
export function Keyed(): Seq.Keyed<any, any>;
export interface Keyed<K, V> extends Seq<K, V>, Collection.Keyed<K, V> {
toJS(): Object;
toJSON(): { [key: string]: V };
toSeq(): this;
concat<KC, VC>(...collections: Array<Iterable<[KC, VC]>>): Seq.Keyed<K | KC, V | VC>;
concat<C>(...collections: Array<{[key: string]: C}>): Seq.Keyed<K | string, V | C>;
map<M>(mapper: (value: V, key: K, iter: this) => M, context?: any): Seq.Keyed<K, M>;
mapKeys<M>(mapper: (key: K, value: V, iter: this) => M, context?: any): Seq.Keyed<M, V>;
mapEntries<KM, VM>(mapper: (entry: [K, V], index: number, iter: this) => [KM, VM], context?: any): Seq.Keyed<KM, VM>;
flatMap<M>(mapper: (value: V, key: K, iter: this) => Iterable<M>, context?: any): Seq.Keyed<any, any>;
filter<F extends V>(predicate: (value: V, key: K, iter: this) => value is F, context?: any): Seq.Keyed<K, F>;
filter(predicate: (value: V, key: K, iter: this) => any, context?: any): this;
}
module Indexed {
function of<T>(...values: Array<T>): Seq.Indexed<T>;
}
export function Indexed(): Seq.Indexed<any>;
export function Indexed<T>(): Seq.Indexed<T>;
export function Indexed<T>(collection: Iterable<T>): Seq.Indexed<T>;
export interface Indexed<T> extends Seq<number, T>, Collection.Indexed<T> {
toJS(): Array<any>;
toJSON(): Array<T>;
toSeq(): this;
concat<C>(...valuesOrCollections: Array<Iterable<C> | C>): Seq.Indexed<T | C>;
map<M>(mapper: (value: T, key: number, iter: this) => M, context?: any): Seq.Indexed<M>;
flatMap<M>(mapper: (value: T, key: number, iter: this) => Iterable<M>, context?: any): Seq.Indexed<M>;
filter<F extends T>(predicate: (value: T, index: number, iter: this) => value is F, context?: any): Seq.Indexed<F>;
filter(predicate: (value: T, index: number, iter: this) => any, context?: any): this;
}
export module Set {
function of<T>(...values: Array<T>): Seq.Set<T>;
}
export function Set(): Seq.Set<any>;
export function Set<T>(): Seq.Set<T>;
export function Set<T>(collection: Iterable<T>): Seq.Set<T>;
export interface Set<T> extends Seq<never, T>, Collection.Set<T> {
toJS(): Array<any>;
toJSON(): Array<T>;
toSeq(): this;
concat<C>(...valuesOrCollections: Array<Iterable<C> | C>): Seq.Set<T | C>;
map<M>(mapper: (value: T, key: never, iter: this) => M, context?: any): Seq.Set<M>;
flatMap<M>(mapper: (value: T, key: never, iter: this) => Iterable<M>, context?: any): Seq.Set<M>;
filter<F extends T>(predicate: (value: T, key: never, iter: this) => value is F, context?: any): Seq.Set<F>;
filter(predicate: (value: T, key: never, iter: this) => any, context?: any): this;
}
}
export function Seq<S extends Seq<any, any>>(seq: S): S;
export function Seq<K, V>(collection: Collection.Keyed<K, V>): Seq.Keyed<K, V>;
export function Seq<T>(collection: Collection.Indexed<T>): Seq.Indexed<T>;
export function Seq<T>(collection: Collection.Set<T>): Seq.Set<T>;
export function Seq<T>(collection: Iterable<T>): Seq.Indexed<T>;
export function Seq<V>(obj: {[key: string]: V}): Seq.Keyed<string, V>;
export function Seq(): Seq<any, any>;
export interface Seq<K, V> extends Collection<K, V> {
readonly size: number | undefined;
// Force evaluation
cacheResult(): this;
// Sequence algorithms
map<M>(mapper: (value: V, key: K, iter: this) => M, context?: any): Seq<K, M>;
flatMap<M>(mapper: (value: V, key: K, iter: this) => Iterable<M>, context?: any): Seq<K, M>;
filter<F extends V>(predicate: (value: V, key: K, iter: this) => value is F, context?: any): Seq<K, F>;
filter(predicate: (value: V, key: K, iter: this) => any, context?: any): this;
}
export module Collection {
function isKeyed(maybeKeyed: any): maybeKeyed is Collection.Keyed<any, any>;
function isIndexed(maybeIndexed: any): maybeIndexed is Collection.Indexed<any>;
function isAssociative(maybeAssociative: any): maybeAssociative is Collection.Keyed<any, any> | Collection.Indexed<any>;
function isOrdered(maybeOrdered: any): boolean;
export module Keyed {}
export function Keyed<K, V>(collection: Iterable<[K, V]>): Collection.Keyed<K, V>;
export function Keyed<V>(obj: {[key: string]: V}): Collection.Keyed<string, V>;
export interface Keyed<K, V> extends Collection<K, V> {
toJS(): Object;
toJSON(): { [key: string]: V };
toSeq(): Seq.Keyed<K, V>;
// Sequence functions
flip(): this;
concat<KC, VC>(...collections: Array<Iterable<[KC, VC]>>): Collection.Keyed<K | KC, V | VC>;
concat<C>(...collections: Array<{[key: string]: C}>): Collection.Keyed<K | string, V | C>;
map<M>(mapper: (value: V, key: K, iter: this) => M, context?: any): Collection.Keyed<K, M>;
mapKeys<M>(mapper: (key: K, value: V, iter: this) => M, context?: any): Collection.Keyed<M, V>;
mapEntries<KM, VM>(mapper: (entry: [K, V], index: number, iter: this) => [KM, VM], context?: any): Collection.Keyed<KM, VM>;
flatMap<M>(mapper: (value: V, key: K, iter: this) => Iterable<M>, context?: any): Collection.Keyed<any, any>;
filter<F extends V>(predicate: (value: V, key: K, iter: this) => value is F, context?: any): Collection.Keyed<K, F>;
filter(predicate: (value: V, key: K, iter: this) => any, context?: any): this;
[Symbol.iterator](): IterableIterator<[K, V]>;
}
export module Indexed {}
export function Indexed<T>(collection: Iterable<T>): Collection.Indexed<T>;
export interface Indexed<T> extends Collection<number, T> {
toJS(): Array<any>;
toJSON(): Array<T>;
// Reading values
get<NSV>(index: number, notSetValue: NSV): T | NSV;
get(index: number): T | undefined;
// Conversion to Seq
toSeq(): Seq.Indexed<T>;
fromEntrySeq(): Seq.Keyed<any, any>;
// Combination
interpose(separator: T): this;
interleave(...collections: Array<Collection<any, T>>): this;
splice(index: number, removeNum: number, ...values: Array<T>): this;
zip(...collections: Array<Collection<any, any>>): Collection.Indexed<any>;
zipWith<U, Z>(zipper: (value: T, otherValue: U) => Z, otherCollection: Collection<any, U>): Collection.Indexed<Z>;
zipWith<U, V, Z>(zipper: (value: T, otherValue: U, thirdValue: V) => Z, otherCollection: Collection<any, U>, thirdCollection: Collection<any, V>): Collection.Indexed<Z>;
zipWith<Z>(zipper: (...any: Array<any>) => Z, ...collections: Array<Collection<any, any>>): Collection.Indexed<Z>;
// Search for value
indexOf(searchValue: T): number;
lastIndexOf(searchValue: T): number;
findIndex(predicate: (value: T, index: number, iter: this) => boolean, context?: any): number;
findLastIndex(predicate: (value: T, index: number, iter: this) => boolean, context?: any): number;
// Sequence algorithms
concat<C>(...valuesOrCollections: Array<Iterable<C> | C>): Collection.Indexed<T | C>;
map<M>(mapper: (value: T, key: number, iter: this) => M, context?: any): Collection.Indexed<M>;
flatMap<M>(mapper: (value: T, key: number, iter: this) => Iterable<M>, context?: any): Collection.Indexed<M>;
filter<F extends T>(predicate: (value: T, index: number, iter: this) => value is F, context?: any): Collection.Indexed<F>;
filter(predicate: (value: T, index: number, iter: this) => any, context?: any): this;
[Symbol.iterator](): IterableIterator<T>;
}
export module Set {}
export function Set<T>(collection: Iterable<T>): Collection.Set<T>;
export interface Set<T> extends Collection<never, T> {
toJS(): Array<any>;
toJSON(): Array<T>;
toSeq(): Seq.Set<T>;
// Sequence algorithms
concat<C>(...valuesOrCollections: Array<Iterable<C> | C>): Collection.Set<T | C>;
map<M>(mapper: (value: T, key: never, iter: this) => M, context?: any): Collection.Set<M>;
flatMap<M>(mapper: (value: T, key: never, iter: this) => Iterable<M>, context?: any): Collection.Set<M>;
filter<F extends T>(predicate: (value: T, key: never, iter: this) => value is F, context?: any): Collection.Set<F>;
filter(predicate: (value: T, key: never, iter: this) => any, context?: any): this;
[Symbol.iterator](): IterableIterator<T>;
}
}
export function Collection<I extends Collection<any, any>>(collection: I): I;
export function Collection<T>(collection: Iterable<T>): Collection.Indexed<T>;
export function Collection<V>(obj: {[key: string]: V}): Collection.Keyed<string, V>;
export interface Collection<K, V> extends ValueObject {
// Value equality
equals(other: any): boolean;
hashCode(): number;
// Reading values
get<NSV>(key: K, notSetValue: NSV): V | NSV;
get(key: K): V | undefined;
has(key: K): boolean;
includes(value: V): boolean;
contains(value: V): boolean;
first(): V | undefined;
last(): V | undefined;
// Reading deep values
getIn(searchKeyPath: Iterable<any>, notSetValue?: any): any;
hasIn(searchKeyPath: Iterable<any>): boolean;
// Persistent changes
update<R>(updater: (value: this) => R): R;
// Conversion to JavaScript types
toJS(): Array<any> | { [key: string]: any };
toJSON(): Array<V> | { [key: string]: V };
toArray(): Array<V>;
toObject(): { [key: string]: V };
// Conversion to Collections
toMap(): Map<K, V>;
toOrderedMap(): OrderedMap<K, V>;
toSet(): Set<V>;
toOrderedSet(): OrderedSet<V>;
toList(): List<V>;
toStack(): Stack<V>;
// Conversion to Seq
toSeq(): this;
toKeyedSeq(): Seq.Keyed<K, V>;
toIndexedSeq(): Seq.Indexed<V>;
toSetSeq(): Seq.Set<V>;
// Iterators
keys(): IterableIterator<K>;
values(): IterableIterator<V>;
entries(): IterableIterator<[K, V]>;
// Collections (Seq)
keySeq(): Seq.Indexed<K>;
valueSeq(): Seq.Indexed<V>;
entrySeq(): Seq.Indexed<[K, V]>;
// Sequence algorithms
map<M>(mapper: (value: V, key: K, iter: this) => M, context?: any): Collection<K, M>;
filter<F extends V>(predicate: (value: V, key: K, iter: this) => value is F, context?: any): Collection<K, F>;
filter(predicate: (value: V, key: K, iter: this) => any, context?: any): this;
filterNot(predicate: (value: V, key: K, iter: this) => boolean, context?: any): this;
reverse(): this;
sort(comparator?: (valueA: V, valueB: V) => number): this;
sortBy<C>(comparatorValueMapper: (value: V, key: K, iter: this) => C, comparator?: (valueA: C, valueB: C) => number): this;
groupBy<G>(grouper: (value: V, key: K, iter: this) => G, context?: any): /*Map*/Seq.Keyed<G, /*this*/Collection<K, V>>;
// Side effects
forEach(sideEffect: (value: V, key: K, iter: this) => any, context?: any): number;
// Creating subsets
slice(begin?: number, end?: number): this;
rest(): this;
butLast(): this;
skip(amount: number): this;
skipLast(amount: number): this;
skipWhile(predicate: (value: V, key: K, iter: this) => boolean, context?: any): this;
skipUntil(predicate: (value: V, key: K, iter: this) => boolean, context?: any): this;
take(amount: number): this;
takeLast(amount: number): this;
takeWhile(predicate: (value: V, key: K, iter: this) => boolean, context?: any): this;
takeUntil(predicate: (value: V, key: K, iter: this) => boolean, context?: any): this;
// Combination
concat(...valuesOrCollections: Array<any>): Collection<any, any>;
flatten(depth?: number): Collection<any, any>;
flatten(shallow?: boolean): Collection<any, any>;
flatMap<M>(mapper: (value: V, key: K, iter: this) => Iterable<M>, context?: any): Collection<K, M>;
// Reducing a value
reduce<R>(reducer: (reduction: R, value: V, key: K, iter: this) => R, initialReduction: R, context?: any): R;
reduce<R>(reducer: (reduction: V | R, value: V, key: K, iter: this) => R): R;
reduceRight<R>(reducer: (reduction: R, value: V, key: K, iter: this) => R, initialReduction: R, context?: any): R;
reduceRight<R>(reducer: (reduction: V | R, value: V, key: K, iter: this) => R): R;
every(predicate: (value: V, key: K, iter: this) => boolean, context?: any): boolean;
some(predicate: (value: V, key: K, iter: this) => boolean, context?: any): boolean;
join(separator?: string): string;
isEmpty(): boolean;
count(): number;
count(predicate: (value: V, key: K, iter: this) => boolean, context?: any): number;
countBy<G>(grouper: (value: V, key: K, iter: this) => G, context?: any): Map<G, number>;
// Search for value
find(predicate: (value: V, key: K, iter: this) => boolean, context?: any, notSetValue?: V): V | undefined;
findLast(predicate: (value: V, key: K, iter: this) => boolean, context?: any, notSetValue?: V): V | undefined;
findEntry(predicate: (value: V, key: K, iter: this) => boolean, context?: any, notSetValue?: V): [K, V] | undefined;
findLastEntry(predicate: (value: V, key: K, iter: this) => boolean, context?: any, notSetValue?: V): [K, V] | undefined;
findKey(predicate: (value: V, key: K, iter: this) => boolean, context?: any): K | undefined;
findLastKey(predicate: (value: V, key: K, iter: this) => boolean, context?: any): K | undefined;
keyOf(searchValue: V): K | undefined;
lastKeyOf(searchValue: V): K | undefined;
max(comparator?: (valueA: V, valueB: V) => number): V | undefined;
maxBy<C>(comparatorValueMapper: (value: V, key: K, iter: this) => C, comparator?: (valueA: C, valueB: C) => number): V | undefined;
min(comparator?: (valueA: V, valueB: V) => number): V | undefined;
minBy<C>(comparatorValueMapper: (value: V, key: K, iter: this) => C, comparator?: (valueA: C, valueB: C) => number): V | undefined;
// Comparison
isSubset(iter: Iterable<V>): boolean;
isSuperset(iter: Iterable<V>): boolean;
readonly size: number;
}
}
declare module "immutable" {
export = Immutable
}
//// [complex.js]
//// [immutable.js]
File diff suppressed because it is too large Load Diff
@@ -1,4 +1,4 @@
=== tests/cases/compiler/complex.d.ts ===
=== tests/cases/compiler/complex.ts ===
interface Ara<T> { t: T }
>Ara : Ara<T>
>T : T
@@ -156,7 +156,7 @@ interface N2<T> extends N1<T> {
>N2 : N2<T>
>T : T
}
=== tests/cases/compiler/immutable.d.ts ===
=== tests/cases/compiler/immutable.ts ===
// Test that complex recursive collections can pass the `extends` assignability check without
// running out of memory. This bug was exposed in Typescript 2.4 when more generic signatures
// started being checked.
@@ -0,0 +1,18 @@
// ==ORIGINAL==
const f = () => {
return /*[#|*/2 + 1/*|]*/;
};
// ==SCOPE::Extract to constant in enclosing scope==
const f = () => {
const newLocal = 2 + 1;
return /*RENAME*/newLocal;
};
// ==SCOPE::Extract to constant in global scope==
const newLocal = 2 + 1;
const f = () => {
return /*RENAME*/newLocal;
};
@@ -0,0 +1,18 @@
// ==ORIGINAL==
const f = () => {
return /*[#|*/2 + 1/*|]*/;
};
// ==SCOPE::Extract to constant in enclosing scope==
const f = () => {
const newLocal = 2 + 1;
return /*RENAME*/newLocal;
};
// ==SCOPE::Extract to constant in global scope==
const newLocal = 2 + 1;
const f = () => {
return /*RENAME*/newLocal;
};
@@ -0,0 +1,6 @@
// ==ORIGINAL==
const f = () => /*[#|*/2 + 1/*|]*/;
// ==SCOPE::Extract to constant in global scope==
const newLocal = 2 + 1;
const f = () => /*RENAME*/newLocal;
@@ -0,0 +1,6 @@
// ==ORIGINAL==
const f = () => /*[#|*/2 + 1/*|]*/;
// ==SCOPE::Extract to constant in global scope==
const newLocal = 2 + 1;
const f = () => /*RENAME*/newLocal;
@@ -2,7 +2,7 @@
for (let i = 0; i < 10; i++) {
for (let j = 0; j < 10; j++) {
const x = i + 1;
const x = /*[#|*/i + 1/*|]*/;
}
}
@@ -2,7 +2,7 @@
for (let i = 0; i < 10; i++) {
for (let j = 0; j < 10; j++) {
const x = i + 1;
const x = /*[#|*/i + 1/*|]*/;
}
}
@@ -1,7 +1,7 @@
// ==ORIGINAL==
for (let i = 0; i < 10; i++) {
for (let j = 0; j < 10; j++) {
let x = 1;
let x = /*[#|*/1/*|]*/;
}
}
// ==SCOPE::Extract to constant in enclosing scope==
@@ -1,7 +1,7 @@
// ==ORIGINAL==
for (let i = 0; i < 10; i++) {
for (let j = 0; j < 10; j++) {
let x = 1;
let x = /*[#|*/1/*|]*/;
}
}
// ==SCOPE::Extract to constant in enclosing scope==
@@ -1,6 +1,6 @@
// ==ORIGINAL==
class C {
x = 1;
x = /*[#|*/1/*|]*/;
}
// ==SCOPE::Extract to constant in global scope==
const newLocal = 1;
@@ -1,6 +1,6 @@
// ==ORIGINAL==
class C {
x = 1;
x = /*[#|*/1/*|]*/;
}
// ==SCOPE::Extract to readonly field in class 'C'==
class C {
@@ -5,7 +5,7 @@ class C {
M1() { }
M2() { }
M3() {
let x = 1;
let x = /*[#|*/1/*|]*/;
}
}
// ==SCOPE::Extract to constant in enclosing scope==
@@ -5,7 +5,7 @@ class C {
M1() { }
M2() { }
M3() {
let x = 1;
let x = /*[#|*/1/*|]*/;
}
}
// ==SCOPE::Extract to constant in enclosing scope==
@@ -5,7 +5,7 @@ class C {
b = 2;
M2() { }
M3() {
let x = 1;
let x = /*[#|*/1/*|]*/;
}
}
// ==SCOPE::Extract to constant in enclosing scope==
@@ -5,7 +5,7 @@ class C {
b = 2;
M2() { }
M3() {
let x = 1;
let x = /*[#|*/1/*|]*/;
}
}
// ==SCOPE::Extract to constant in enclosing scope==
@@ -5,7 +5,7 @@ class C {
b = 2;
M2() { }
M3() {
let x = 1;
let x = /*[#|*/1/*|]*/;
}
}
// ==SCOPE::Extract to constant in enclosing scope==
@@ -5,7 +5,7 @@ class C {
b = 2;
M2() { }
M3() {
let x = 1;
let x = /*[#|*/1/*|]*/;
}
}
// ==SCOPE::Extract to constant in enclosing scope==
@@ -2,7 +2,7 @@
"strict";
const x = 2 + 1;
const x = /*[#|*/2 + 1/*|]*/;
// ==SCOPE::Extract to constant in enclosing scope==
@@ -2,7 +2,7 @@
"strict";
const x = 2 + 1;
const x = /*[#|*/2 + 1/*|]*/;
// ==SCOPE::Extract to constant in enclosing scope==
@@ -1,4 +1,4 @@
// ==ORIGINAL==
"hello";
/*[#|*/"hello";/*|]*/
// ==SCOPE::Extract to constant in enclosing scope==
const /*RENAME*/newLocal = "hello";
@@ -1,4 +1,4 @@
// ==ORIGINAL==
"hello";
/*[#|*/"hello";/*|]*/
// ==SCOPE::Extract to constant in enclosing scope==
const /*RENAME*/newLocal = "hello";
@@ -0,0 +1,14 @@
// ==ORIGINAL==
function F() {
let i = 0;
/*[#|*/i++/*|]*/;
}
// ==SCOPE::Extract to constant in enclosing scope==
function F() {
let i = 0;
const /*RENAME*/newLocal = i++;
}
@@ -0,0 +1,14 @@
// ==ORIGINAL==
function F() {
let i = 0;
/*[#|*/i++/*|]*/;
}
// ==SCOPE::Extract to constant in enclosing scope==
function F() {
let i = 0;
const /*RENAME*/newLocal = i++;
}
@@ -1,4 +1,4 @@
// ==ORIGINAL==
"hello";
/*[#|*/"hello"/*|]*/;
// ==SCOPE::Extract to constant in enclosing scope==
const /*RENAME*/newLocal = "hello";
@@ -1,4 +1,4 @@
// ==ORIGINAL==
"hello";
/*[#|*/"hello"/*|]*/;
// ==SCOPE::Extract to constant in enclosing scope==
const /*RENAME*/newLocal = "hello";
@@ -0,0 +1,23 @@
// ==ORIGINAL==
let i = 0;
function F() {
/*[#|*/i++/*|]*/;
}
// ==SCOPE::Extract to constant in enclosing scope==
let i = 0;
function F() {
const /*RENAME*/newLocal = i++;
}
// ==SCOPE::Extract to constant in global scope==
let i = 0;
const /*RENAME*/newLocal = i++;
function F() {
}
@@ -0,0 +1,23 @@
// ==ORIGINAL==
let i = 0;
function F() {
/*[#|*/i++/*|]*/;
}
// ==SCOPE::Extract to constant in enclosing scope==
let i = 0;
function F() {
const /*RENAME*/newLocal = i++;
}
// ==SCOPE::Extract to constant in global scope==
let i = 0;
const /*RENAME*/newLocal = i++;
function F() {
}
@@ -1,6 +1,6 @@
// ==ORIGINAL==
function F() {
let x = 1;
let x = /*[#|*/1/*|]*/;
}
// ==SCOPE::Extract to constant in enclosing scope==
function F() {
@@ -1,6 +1,6 @@
// ==ORIGINAL==
function F() {
let x = 1;
let x = /*[#|*/1/*|]*/;
}
// ==SCOPE::Extract to constant in enclosing scope==
function F() {
@@ -1,7 +1,7 @@
// ==ORIGINAL==
class C {
M() {
let x = 1;
let x = /*[#|*/1/*|]*/;
}
}
// ==SCOPE::Extract to constant in enclosing scope==
@@ -1,7 +1,7 @@
// ==ORIGINAL==
class C {
M() {
let x = 1;
let x = /*[#|*/1/*|]*/;
}
}
// ==SCOPE::Extract to constant in enclosing scope==
@@ -6,7 +6,7 @@
"strict";
const x = 2 + 1;
const x = /*[#|*/2 + 1/*|]*/;
// ==SCOPE::Extract to constant in enclosing scope==
@@ -6,7 +6,7 @@
"strict";
const x = 2 + 1;
const x = /*[#|*/2 + 1/*|]*/;
// ==SCOPE::Extract to constant in enclosing scope==
@@ -1,6 +1,6 @@
// ==ORIGINAL==
namespace N {
let x = 1;
let x = /*[#|*/1/*|]*/;
}
// ==SCOPE::Extract to constant in enclosing scope==
namespace N {
@@ -1,7 +1,7 @@
// ==ORIGINAL==
function F() {
let w = 1;
let x = w + 1;
let x = /*[#|*/w + 1/*|]*/;
}
// ==SCOPE::Extract to constant in enclosing scope==
function F() {
@@ -1,7 +1,7 @@
// ==ORIGINAL==
function F() {
let w = 1;
let x = w + 1;
let x = /*[#|*/w + 1/*|]*/;
}
// ==SCOPE::Extract to constant in enclosing scope==
function F() {
@@ -2,7 +2,7 @@
/*! Copyright */
const x = 2 + 1;
const x = /*[#|*/2 + 1/*|]*/;
// ==SCOPE::Extract to constant in enclosing scope==
@@ -2,7 +2,7 @@
/*! Copyright */
const x = 2 + 1;
const x = /*[#|*/2 + 1/*|]*/;
// ==SCOPE::Extract to constant in enclosing scope==
@@ -3,7 +3,7 @@
/*! Copyright */
/* About x */
const x = 2 + 1;
const x = /*[#|*/2 + 1/*|]*/;
// ==SCOPE::Extract to constant in enclosing scope==
@@ -3,7 +3,7 @@
/*! Copyright */
/* About x */
const x = 2 + 1;
const x = /*[#|*/2 + 1/*|]*/;
// ==SCOPE::Extract to constant in enclosing scope==
@@ -1,7 +1,7 @@
// ==ORIGINAL==
namespace X {
export const j = 10;
export const y = j * j;
export const y = /*[#|*/j * j/*|]*/;
}
// ==SCOPE::Extract to constant in enclosing scope==
namespace X {
@@ -2,7 +2,7 @@
const i = 0;
for (let j = 0; j < 10; j++) {
const x = i + 1;
const x = /*[#|*/i + 1/*|]*/;
}
// ==SCOPE::Extract to constant in enclosing scope==
@@ -2,7 +2,7 @@
const i = 0;
for (let j = 0; j < 10; j++) {
const x = i + 1;
const x = /*[#|*/i + 1/*|]*/;
}
// ==SCOPE::Extract to constant in enclosing scope==
@@ -3,7 +3,7 @@
const i = 0;
function F() {
for (let j = 0; j < 10; j++) {
const x = i + 1;
const x = /*[#|*/i + 1/*|]*/;
}
}
@@ -3,7 +3,7 @@
const i = 0;
function F() {
for (let j = 0; j < 10; j++) {
const x = i + 1;
const x = /*[#|*/i + 1/*|]*/;
}
}
@@ -1,7 +1,7 @@
// ==ORIGINAL==
for (let j = 0; j < 10; j++) {
const x = 2 + 1;
const x = /*[#|*/2 + 1/*|]*/;
}
// ==SCOPE::Extract to constant in enclosing scope==
@@ -1,7 +1,7 @@
// ==ORIGINAL==
for (let j = 0; j < 10; j++) {
const x = 2 + 1;
const x = /*[#|*/2 + 1/*|]*/;
}
// ==SCOPE::Extract to constant in enclosing scope==
@@ -2,7 +2,7 @@
function F() {
for (let j = 0; j < 10; j++) {
const x = 2 + 1;
const x = /*[#|*/2 + 1/*|]*/;
}
}
@@ -2,7 +2,7 @@
function F() {
for (let j = 0; j < 10; j++) {
const x = 2 + 1;
const x = /*[#|*/2 + 1/*|]*/;
}
}
@@ -2,7 +2,7 @@
function F0() {
function F1() {
function F2(x = 2 + 1) {
function F2(x = /*[#|*/2 + 1/*|]*/) {
}
}
}
@@ -2,7 +2,7 @@
function F0() {
function F1() {
function F2(x = 2 + 1) {
function F2(x = /*[#|*/2 + 1/*|]*/) {
}
}
}
@@ -1,7 +1,7 @@
// ==ORIGINAL==
class C {
x = 2 + 1;
x = /*[#|*/2 + 1/*|]*/;
}
// ==SCOPE::Extract to constant in global scope==
@@ -1,7 +1,7 @@
// ==ORIGINAL==
class C {
x = 2 + 1;
x = /*[#|*/2 + 1/*|]*/;
}
// ==SCOPE::Extract to readonly field in class 'C'==
@@ -4,7 +4,7 @@ const i = 0;
class C {
M() {
for (let j = 0; j < 10; j++) {
x = i + 1;
x = /*[#|*/i + 1/*|]*/;
}
}
}
@@ -4,7 +4,7 @@ const i = 0;
class C {
M() {
for (let j = 0; j < 10; j++) {
x = i + 1;
x = /*[#|*/i + 1/*|]*/;
}
}
}
@@ -1,5 +1,5 @@
// ==ORIGINAL==
let x = 1;
let x = /*[#|*/1/*|]*/;
// ==SCOPE::Extract to constant in enclosing scope==
const newLocal = 1;
@@ -1,5 +1,5 @@
// ==ORIGINAL==
let x = 1;
let x = /*[#|*/1/*|]*/;
// ==SCOPE::Extract to constant in enclosing scope==
const newLocal = 1;
@@ -2,7 +2,7 @@
/// <reference path="path.js"/>
const x = 2 + 1;
const x = /*[#|*/2 + 1/*|]*/;
// ==SCOPE::Extract to constant in enclosing scope==
@@ -2,7 +2,7 @@
/// <reference path="path.js"/>
const x = 2 + 1;
const x = /*[#|*/2 + 1/*|]*/;
// ==SCOPE::Extract to constant in enclosing scope==
@@ -1,6 +1,6 @@
// ==ORIGINAL==
function F<T>(t: T) {
let x = t + 1;
let x = /*[#|*/t + 1/*|]*/;
}
// ==SCOPE::Extract to constant in enclosing scope==
function F<T>(t: T) {
@@ -1,6 +1,6 @@
// ==ORIGINAL==
const /*About A*/a = 1,
/*About B*/b = a + 1;
/*About B*/b = /*[#|*/a + 1/*|]*/;
// ==SCOPE::Extract to constant in enclosing scope==
const /*About A*/a = 1,
/*About B*/newLocal = a + 1, b = /*RENAME*/newLocal;
@@ -1,6 +1,6 @@
// ==ORIGINAL==
const /*About A*/a = 1,
/*About B*/b = a + 1;
/*About B*/b = /*[#|*/a + 1/*|]*/;
// ==SCOPE::Extract to constant in enclosing scope==
const /*About A*/a = 1,
/*About B*/newLocal = a + 1, b = /*RENAME*/newLocal;
@@ -1,4 +1,4 @@
// ==ORIGINAL==
const a = 1, b = a + 1;
const a = 1, b = /*[#|*/a + 1/*|]*/;
// ==SCOPE::Extract to constant in enclosing scope==
const a = 1, newLocal = a + 1, b = /*RENAME*/newLocal;
@@ -1,4 +1,4 @@
// ==ORIGINAL==
const a = 1, b = a + 1;
const a = 1, b = /*[#|*/a + 1/*|]*/;
// ==SCOPE::Extract to constant in enclosing scope==
const a = 1, newLocal = a + 1, b = /*RENAME*/newLocal;
@@ -1,4 +1,4 @@
// ==ORIGINAL==
let a = 1, b = a + 1;
let a = 1, b = /*[#|*/a + 1/*|]*/;
// ==SCOPE::Extract to constant in enclosing scope==
let a = 1, newLocal = a + 1, b = /*RENAME*/newLocal;
@@ -1,4 +1,4 @@
// ==ORIGINAL==
let a = 1, b = a + 1;
let a = 1, b = /*[#|*/a + 1/*|]*/;
// ==SCOPE::Extract to constant in enclosing scope==
let a = 1, newLocal = a + 1, b = /*RENAME*/newLocal;
@@ -6,11 +6,11 @@ namespace A {
namespace B {
function a() {
let a = 1;
/*[#|*/
let y = 5;
let z = x;
a = y;
foo();
foo();/*|]*/
}
}
}
@@ -4,8 +4,8 @@ namespace A {
class C {
a() {
let z = 1;
let a1: I = { x: 1 };
return a1.x + 10;
/*[#|*/let a1: I = { x: 1 };
return a1.x + 10;/*|]*/
}
}
}
@@ -4,10 +4,10 @@ namespace A {
class C {
a() {
let z = 1;
let a1 = { x: 1 };
/*[#|*/let a1 = { x: 1 };
y = 10;
z = 42;
return a1.x + 10;
return a1.x + 10;/*|]*/
}
}
}
@@ -5,11 +5,11 @@ namespace A {
b() {}
a() {
let z = 1;
let a1 = { x: 1 };
/*[#|*/let a1 = { x: 1 };
y = 10;
z = 42;
this.b();
return a1.x + 10;
return a1.x + 10;/*|]*/
}
}
}
@@ -4,11 +4,11 @@
<U2a, U2b>(u2a: U2a, u2b: U2b) => {
function F2<T2a, T2b>(t2a: T2a, t2b: T2b) {
<U3a, U3b>(u3a: U3a, u3b: U3b) => {
t1a.toString();
/*[#|*/t1a.toString();
t2a.toString();
u1a.toString();
u2a.toString();
u3a.toString();
u3a.toString();/*|]*/
}
}
}
@@ -1,8 +1,8 @@
// ==ORIGINAL==
function F<T>(t1: T) {
function G<T>(t2: T) {
t1.toString();
t2.toString();
/*[#|*/t1.toString();
t2.toString();/*|]*/
}
}
// ==SCOPE::Extract to inner function in function 'G'==
@@ -1,7 +1,7 @@
// ==ORIGINAL==
function F<T>(t1: T) {
function G<U extends T[]>(t2: U) {
t2.toString();
/*[#|*/t2.toString();/*|]*/
}
}
// ==SCOPE::Extract to inner function in function 'G'==
@@ -1,6 +1,6 @@
// ==ORIGINAL==
function F<T>() {
const array: T[] = [];
const array: T[] = /*[#|*/[]/*|]*/;
}
// ==SCOPE::Extract to inner function in function 'F'==
function F<T>() {
@@ -1,7 +1,7 @@
// ==ORIGINAL==
class C<T1, T2> {
M(t1: T1, t2: T2) {
t1.toString();
/*[#|*/t1.toString()/*|]*/;
}
}
// ==SCOPE::Extract to method in class 'C'==
@@ -1,7 +1,7 @@
// ==ORIGINAL==
class C {
M<T1, T2>(t1: T1, t2: T2) {
t1.toString();
/*[#|*/t1.toString()/*|]*/;
}
}
// ==SCOPE::Extract to method in class 'C'==

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