Skip to content

Commit

Permalink
Merge branch 'master' into configFileDiag
Browse files Browse the repository at this point in the history
  • Loading branch information
sheetalkamat committed Oct 11, 2017
2 parents 0e2eb3a + d0168af commit 7f1ddaf
Show file tree
Hide file tree
Showing 124 changed files with 825 additions and 322 deletions.
13 changes: 12 additions & 1 deletion .mailmap
Original file line number Diff line number Diff line change
Expand Up @@ -276,4 +276,15 @@ Francois Wouts <[email protected]>
Jan Melcher <[email protected]> Jan Melcher <[email protected]>
Matt Mitchell <[email protected]>
Maxwell Paul Brickner <[email protected]>
Tycho Grouwstra <[email protected]>
Tycho Grouwstra <[email protected]>
Adrian Leonhard <[email protected]>
Alex Chugaev <[email protected]>
Henry Mercer <[email protected]>
Ivan Enderlin <[email protected]>
Joe Calzaretta <[email protected]>
Magnus Kulke <[email protected]>
Stas Vilchik <[email protected]>
Taras Mankovski <[email protected]>
Thomas den Hollander <[email protected]>
Vakhurin Sergey <[email protected]>
Zeeshan Ahmed <[email protected]>
11 changes: 11 additions & 0 deletions AUTHORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ TypeScript is authored by:
* Abubaker Bashir
* Adam Freidin
* Adi Dahiya
* Adrian Leonhard
* Ahmad Farid
* Akshar Patel
* Alex Chugaev
* Alex Eagle
* Alexander Kuvaev
* Alexander Rusakov
Expand Down Expand Up @@ -105,13 +107,15 @@ TypeScript is authored by:
* Halasi Tamás
* Harald Niesche
* Hendrik Liebau
* Henry Mercer
* Herrington Darkholme
* Homa Wong
* Iain Monro
* Igor Novozhilov
* Ika
* Ingvar Stepanyan
* Isiah Meadows
* Ivan Enderlin
* Ivo Gabe de Wolff
* Iwata Hidetaka
* Jakub Młokosiewicz
Expand All @@ -127,6 +131,7 @@ TypeScript is authored by:
* Jeffrey Morlan
* Jesse Schalken
* Jiri Tobisek
* Joe Calzaretta
* Joe Chung
* Joel Day
* Joey Wilson
Expand Down Expand Up @@ -161,6 +166,7 @@ TypeScript is authored by:
* Lucien Greathouse
* Lukas Elmer
* Magnus Hiie
* Magnus Kulke
* Manish Giri
* Marin Marinov
* Marius Schulz
Expand Down Expand Up @@ -232,13 +238,16 @@ TypeScript is authored by:
* Soo Jae Hwang
* Stan Thomas
* Stanislav Sysoev
* Stas Vilchik
* Steve Lucco
* Sudheesh Singanamalla
* Sébastien Arod
* @T18970237136
* @t_
* Taras Mankovski
* Tarik Ozket
* Tetsuharu Ohzeki
* Thomas den Hollander
* Thomas Loubiou
* Tien Hoanhtien
* Tim Lancina
Expand All @@ -253,6 +262,7 @@ TypeScript is authored by:
* TruongSinh Tran-Nguyen
* Tycho Grouwstra
* Vadi Taslim
* Vakhurin Sergey
* Vidar Tonaas Fauske
* Viktor Zozulyak
* Vilic Vane
Expand All @@ -263,5 +273,6 @@ TypeScript is authored by:
* York Yao
* @yortus
* Yuichi Nukiyama
* Zeeshan Ahmed
* Zev Spitz
* Zhengbo Li
9 changes: 9 additions & 0 deletions src/compiler/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,15 @@ namespace ts {
let subtreeTransformFlags: TransformFlags = TransformFlags.None;
let skipTransformFlagAggregation: boolean;

/**
* Inside the binder, we may create a diagnostic for an as-yet unbound node (with potentially no parent pointers, implying no accessible source file)
* If so, the node _must_ be in the current file (as that's the only way anything could have traversed to it to yield it as the error node)
* This version of `createDiagnosticForNode` uses the binder's context to account for this, and always yields correct diagnostics even in these situations.
*/
function createDiagnosticForNode(node: Node, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number): Diagnostic {
return createDiagnosticForNodeInSourceFile(getSourceFileOfNode(node) || file, node, message, arg0, arg1, arg2);
}

function bindSourceFile(f: SourceFile, opts: CompilerOptions) {
file = f;
options = opts;
Expand Down
4 changes: 2 additions & 2 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20034,7 +20034,7 @@ namespace ts {
function checkJSDocAugmentsTag(node: JSDocAugmentsTag): void {
const classLike = getJSDocHost(node);
if (!isClassDeclaration(classLike) && !isClassExpression(classLike)) {
error(classLike, Diagnostics.JSDoc_augments_is_not_attached_to_a_class_declaration);
error(classLike, Diagnostics.JSDoc_0_is_not_attached_to_a_class, idText(node.tagName));
return;
}

Expand All @@ -20049,7 +20049,7 @@ namespace ts {
if (extend) {
const className = getIdentifierFromEntityNameExpression(extend.expression);
if (className && name.escapedText !== className.escapedText) {
error(name, Diagnostics.JSDoc_augments_0_does_not_match_the_extends_1_clause, idText(name), idText(className));
error(name, Diagnostics.JSDoc_0_1_does_not_match_the_extends_2_clause, idText(node.tagName), idText(name), idText(className));
}
}
}
Expand Down
15 changes: 0 additions & 15 deletions src/compiler/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -356,21 +356,6 @@ namespace ts {
return array;
}

export function removeWhere<T>(array: T[], f: (x: T) => boolean): boolean {
let outIndex = 0;
for (const item of array) {
if (!f(item)) {
array[outIndex] = item;
outIndex++;
}
}
if (outIndex !== array.length) {
array.length = outIndex;
return true;
}
return false;
}

export function filterMutate<T>(array: T[], f: (x: T, i: number, array: T[]) => boolean): void {
let outIndex = 0;
for (let i = 0; i < array.length; i++) {
Expand Down
6 changes: 3 additions & 3 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -3519,11 +3519,11 @@
"category": "Error",
"code": 8021
},
"JSDoc '@augments' is not attached to a class declaration.": {
"JSDoc '@{0}' is not attached to a class.": {
"category": "Error",
"code": 8022
},
"JSDoc '@augments {0}' does not match the 'extends {1}' clause.": {
"JSDoc '@{0} {1}' does not match the 'extends {2}' clause.": {
"category": "Error",
"code": 8023
},
Expand Down Expand Up @@ -3661,7 +3661,7 @@
"category": "Message",
"code": 90013
},
"Change {0} to {1}.": {
"Change '{0}' to '{1}'.": {
"category": "Message",
"code": 90014
},
Expand Down
10 changes: 8 additions & 2 deletions src/compiler/resolutionCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,10 @@ namespace ts {
resolvedModuleNames.clear();
resolvedTypeReferenceDirectives.clear();
allFilesHaveInvalidatedResolution = false;
Debug.assert(perDirectoryResolvedModuleNames.size === 0 && perDirectoryResolvedTypeReferenceDirectives.size === 0);
// perDirectoryResolvedModuleNames and perDirectoryResolvedTypeReferenceDirectives could be non empty if there was exception during program update
// (between startCachingPerDirectoryResolution and finishCachingPerDirectoryResolution)
perDirectoryResolvedModuleNames.clear();
perDirectoryResolvedTypeReferenceDirectives.clear();
}

function startRecordingFilesWithChangedResolutions() {
Expand All @@ -166,7 +169,10 @@ namespace ts {
}

function startCachingPerDirectoryResolution() {
Debug.assert(perDirectoryResolvedModuleNames.size === 0 && perDirectoryResolvedTypeReferenceDirectives.size === 0);
// perDirectoryResolvedModuleNames and perDirectoryResolvedTypeReferenceDirectives could be non empty if there was exception during program update
// (between startCachingPerDirectoryResolution and finishCachingPerDirectoryResolution)
perDirectoryResolvedModuleNames.clear();
perDirectoryResolvedTypeReferenceDirectives.clear();
}

function finishCachingPerDirectoryResolution() {
Expand Down
10 changes: 5 additions & 5 deletions src/compiler/watch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -322,21 +322,21 @@ namespace ts {

if (hasChangedCompilerOptions) {
newLine = getNewLineCharacter(compilerOptions, system);
if (program && changesAffectModuleResolution(program.getCompilerOptions(), compilerOptions)) {
resolutionCache.clear();
}
}

const hasInvalidatedResolution = resolutionCache.createHasInvalidatedResolution();
if (isProgramUptoDate(program, rootFileNames, compilerOptions, getSourceVersion, fileExists, hasInvalidatedResolution, hasChangedAutomaticTypeDirectiveNames)) {
return;
}

if (hasChangedCompilerOptions && changesAffectModuleResolution(program && program.getCompilerOptions(), compilerOptions)) {
resolutionCache.clear();
}
const needsUpdateInTypeRootWatch = hasChangedCompilerOptions || !program;
hasChangedCompilerOptions = false;
beforeCompile(compilerOptions);

// Compile the program
const needsUpdateInTypeRootWatch = hasChangedCompilerOptions || !program;
hasChangedCompilerOptions = false;
resolutionCache.startCachingPerDirectoryResolution();
compilerHost.hasInvalidatedResolution = hasInvalidatedResolution;
compilerHost.hasChangedAutomaticTypeDirectiveNames = hasChangedAutomaticTypeDirectiveNames;
Expand Down
2 changes: 1 addition & 1 deletion src/harness/fourslash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2381,7 +2381,7 @@ Actual: ${stringify(fullActual)}`);
}));

return ts.flatMap(ts.deduplicate(diagnosticsForCodeFix, ts.equalOwnProperties), diagnostic => {
if (errorCode && errorCode !== diagnostic.code) {
if (errorCode !== undefined && errorCode !== diagnostic.code) {
return;
}

Expand Down
48 changes: 36 additions & 12 deletions src/harness/parallel/host.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,20 +38,45 @@ namespace Harness.Parallel.Host {
return undefined;
}

function hashName(runner: TestRunnerKind, test: string) {
function hashName(runner: TestRunnerKind | "unittest", test: string) {
return `tsrunner-${runner}://${test}`;
}

let tasks: { runner: TestRunnerKind | "unittest", file: string, size: number }[] = [];
const newTasks: { runner: TestRunnerKind | "unittest", file: string, size: number }[] = [];
let unknownValue: string | undefined;
export function start() {
const perfData = readSavedPerfData(configOption);
let totalCost = 0;
if (runUnitTests) {
(global as any).describe = (suiteName: string) => {
// Note, sub-suites are not indexed (we assume such granularity is not required)
let size = 0;
if (perfData) {
size = perfData[hashName("unittest", suiteName)];
if (size === undefined) {
newTasks.push({ runner: "unittest", file: suiteName, size: 0 });
unknownValue = suiteName;
return;
}
}
tasks.push({ runner: "unittest", file: suiteName, size });
totalCost += size;
};
}
else {
(global as any).describe = ts.noop;
}

setTimeout(() => startDelayed(perfData, totalCost), 0); // Do real startup on next tick, so all unit tests have been collected
}

function startDelayed(perfData: {[testHash: string]: number}, totalCost: number) {
initializeProgressBarsDependencies();
console.log("Discovering tests...");
console.log(`Discovered ${tasks.length} unittest suites` + (newTasks.length ? ` and ${newTasks.length} new suites.` : "."));
console.log("Discovering runner-based tests...");
const discoverStart = +(new Date());
const { statSync }: { statSync(path: string): { size: number }; } = require("fs");
let tasks: { runner: TestRunnerKind, file: string, size: number }[] = [];
const newTasks: { runner: TestRunnerKind, file: string, size: number }[] = [];
const perfData = readSavedPerfData(configOption);
let totalCost = 0;
let unknownValue: string | undefined;
for (const runner of runners) {
const files = runner.enumerateTestFiles();
for (const file of files) {
Expand Down Expand Up @@ -87,8 +112,7 @@ namespace Harness.Parallel.Host {
}
tasks.sort((a, b) => a.size - b.size);
tasks = tasks.concat(newTasks);
// 1 fewer batches than threads to account for unittests running on the final thread
const batchCount = runners.length === 1 ? workerCount : workerCount - 1;
const batchCount = workerCount;
const packfraction = 0.9;
const chunkSize = 1000; // ~1KB or 1s for sending batches near the end of a test
const batchSize = (totalCost / workerCount) * packfraction; // Keep spare tests for unittest thread in reserve
Expand All @@ -113,7 +137,7 @@ namespace Harness.Parallel.Host {
let closedWorkers = 0;
for (let i = 0; i < workerCount; i++) {
// TODO: Just send the config over the IPC channel or in the command line arguments
const config: TestConfig = { light: Harness.lightMode, listenForWork: true, runUnitTests: runners.length === 1 ? false : i === workerCount - 1 };
const config: TestConfig = { light: Harness.lightMode, listenForWork: true, runUnitTests: runners.length !== 1 };
const configPath = ts.combinePaths(taskConfigsFolder, `task-config${i}.json`);
Harness.IO.writeFile(configPath, JSON.stringify(config));
const child = fork(__filename, [`--config="${configPath}"`]);
Expand Down Expand Up @@ -187,7 +211,7 @@ namespace Harness.Parallel.Host {
// It's only really worth doing an initial batching if there are a ton of files to go through
if (totalFiles > 1000) {
console.log("Batching initial test lists...");
const batches: { runner: TestRunnerKind, file: string, size: number }[][] = new Array(batchCount);
const batches: { runner: TestRunnerKind | "unittest", file: string, size: number }[][] = new Array(batchCount);
const doneBatching = new Array(batchCount);
let scheduledTotal = 0;
batcher: while (true) {
Expand Down Expand Up @@ -230,7 +254,7 @@ namespace Harness.Parallel.Host {
if (payload) {
worker.send({ type: "batch", payload });
}
else { // Unittest thread - send off just one test
else { // Out of batches, send off just one test
const payload = tasks.pop();
ts.Debug.assert(!!payload); // The reserve kept above should ensure there is always an initial task available, even in suboptimal scenarios
worker.send({ type: "test", payload });
Expand Down
4 changes: 2 additions & 2 deletions src/harness/parallel/shared.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
/// <reference path="./host.ts" />
/// <reference path="./worker.ts" />
namespace Harness.Parallel {
export type ParallelTestMessage = { type: "test", payload: { runner: TestRunnerKind, file: string } } | never;
export type ParallelTestMessage = { type: "test", payload: { runner: TestRunnerKind | "unittest", file: string } } | never;
export type ParallelBatchMessage = { type: "batch", payload: ParallelTestMessage["payload"][] } | never;
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 ParallelResultMessage = { type: "result", payload: { passing: number, errors: ErrorInfo[], duration: number, runner: TestRunnerKind, file: string } } | never;
export type ParallelResultMessage = { type: "result", payload: { passing: number, errors: ErrorInfo[], duration: number, runner: TestRunnerKind | "unittest", file: string } } | never;
export type ParallelBatchProgressMessage = { type: "progress", payload: ParallelResultMessage["payload"] } | never;
export type ParallelClientMessage = ParallelErrorMessage | ParallelResultMessage | ParallelBatchProgressMessage;
}
Loading

0 comments on commit 7f1ddaf

Please sign in to comment.