Skip to content

Commit f62e3b0

Browse files
committed
Merge remote-tracking branch 'origin/master' into debug-messages
* origin/master: (64 commits) Fix resolution of properties from prototype assignment in JS (microsoft#29302) Include all flow nodes made within `try` blocks as antecedents for `catch` or `finally` blocks (microsoft#29466) Don't treat interfaces as implementations Make the relationship between partial mapped types and the empty object not apply for subtype relationship (microsoft#29384) Add missing arity check on second inference pass (microsoft#29386) renames add missing type annotation PR feedback Illustrate a case that isn't handled correctly Add fourslash tests Consider JSX namespace imports when moving statements between files Fix gulp builds not building some targets Update user baselines (microsoft#29444) Add opt-in user preference for prefix and suffix text on renames (microsoft#29314) Fake up value declaration for synthetic jsx children symbol so they get excess property checked (microsoft#29359) Add regression test. (microsoft#29433) Elaborate jsx children elementwise (microsoft#29264) Add regression test PR feedback Fix trailing whitespace ...
2 parents a4c10a4 + 3a2f6a3 commit f62e3b0

File tree

181 files changed

+5183
-3121
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

181 files changed

+5183
-3121
lines changed

Gulpfile.js

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -488,29 +488,28 @@ gulp.task(
488488
"Runs 'local'",
489489
["local"]);
490490

491-
gulp.task(
492-
"watch-diagnostics",
493-
/*help*/ false,
494-
[processDiagnosticMessagesJs],
495-
() => gulp.watch([diagnosticMessagesJson], [diagnosticInformationMapTs, builtGeneratedDiagnosticMessagesJson]));
496-
497491
gulp.task(
498492
"watch-lib",
499493
/*help*/ false,
500494
() => gulp.watch(["src/lib/**/*"], ["lib"]));
501495

496+
const watchTscPatterns = [
497+
"src/tsconfig-base.json",
498+
"src/lib/**/*",
499+
"src/compiler/**/*",
500+
"src/tsc/**/*",
501+
];
502502
gulp.task(
503503
"watch-tsc",
504504
/*help*/ false,
505-
["watch-diagnostics", "watch-lib"].concat(useCompilerDeps),
506-
() => project.watch(tscProject, { typescript: useCompiler }));
505+
useCompilerDeps,
506+
() => gulp.watch(watchTscPatterns, ["tsc"]));
507507

508508
const watchServicesPatterns = [
509509
"src/compiler/**/*",
510510
"src/jsTypings/**/*",
511511
"src/services/**/*"
512512
];
513-
514513
gulp.task(
515514
"watch-services",
516515
/*help*/ false,
@@ -522,39 +521,49 @@ const watchLsslPatterns = [
522521
"src/server/**/*",
523522
"src/tsserver/tsconfig.json"
524523
];
525-
526524
gulp.task(
527525
"watch-lssl",
528526
/*help*/ false,
529527
() => gulp.watch(watchLsslPatterns, ["lssl"]));
530528

531-
gulp.task(
532-
"watch-server",
533-
/*help*/ false,
534-
["watch-diagnostics", "watch-lib"].concat(useCompilerDeps),
535-
() => project.watch(tsserverProject, { typescript: useCompiler }));
536-
537-
gulp.task(
538-
"watch-runner",
539-
/*help*/ false,
540-
useCompilerDeps,
541-
() => project.watch(testRunnerProject, { typescript: useCompiler }));
542-
529+
const watchLocalPatterns = [
530+
"src/tsconfig-base.json",
531+
"src/lib/**/*",
532+
"src/compiler/**/*",
533+
"src/tsc/**/*",
534+
"src/services/**/*",
535+
"src/jsTyping/**/*",
536+
"src/server/**/*",
537+
"src/tsserver/**/*",
538+
"src/typingsInstallerCore/**/*",
539+
"src/harness/**/*",
540+
"src/testRunner/**/*",
541+
];
543542
gulp.task(
544543
"watch-local",
545544
"Watches for changes to projects in src/ (but does not execute tests).",
546-
["watch-lib", "watch-tsc", "watch-services", "watch-server", "watch-runner", "watch-lssl"]);
545+
() => gulp.watch(watchLocalPatterns, "local"));
547546

547+
const watchPatterns = [
548+
"src/tsconfig-base.json",
549+
"src/lib/**/*",
550+
"src/compiler/**/*",
551+
"src/services/**/*",
552+
"src/jsTyping/**/*",
553+
"src/server/**/*",
554+
"src/tsserver/**/*",
555+
"src/typingsInstallerCore/**/*",
556+
"src/harness/**/*",
557+
"src/testRunner/**/*",
558+
];
548559
gulp.task(
549560
"watch",
550561
"Watches for changes to the build inputs for built/local/run.js, then runs tests.",
551-
["build-rules", "watch-runner", "watch-services", "watch-lssl"],
562+
["build-rules"],
552563
() => {
553564
const sem = new Semaphore(1);
554565

555-
gulp.watch([runJs, typescriptDts, tsserverlibraryDts], () => {
556-
runTests();
557-
});
566+
gulp.watch(watchPatterns, () => { runTests(); });
558567

559568
// NOTE: gulp.watch is far too slow when watching tests/cases/**/* as it first enumerates *every* file
560569
const testFilePattern = /(\.ts|[\\/]tsconfig\.json)$/;

scripts/build/options.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ module.exports = minimist(process.argv.slice(2), {
3434
workers: process.env.workerCount || os.cpus().length,
3535
failed: false,
3636
keepFailed: false,
37-
lkg: false,
37+
lkg: true,
3838
dirty: false
3939
}
4040
});

scripts/build/project.js

Lines changed: 39 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -14,78 +14,54 @@ const ts = require("../../lib/typescript");
1414
const del = require("del");
1515
const needsUpdate = require("./needsUpdate");
1616
const mkdirp = require("./mkdirp");
17-
const prettyTime = require("pretty-hrtime");
1817
const { reportDiagnostics } = require("./diagnostics");
19-
const { CountdownEvent, ManualResetEvent } = require("prex");
18+
const { CountdownEvent, ManualResetEvent, Semaphore } = require("prex");
2019

2120
const workStartedEvent = new ManualResetEvent();
2221
const countdown = new CountdownEvent(0);
2322

24-
class CompilationGulp extends gulp.Gulp {
25-
/**
26-
* @param {boolean} [verbose]
27-
*/
28-
fork(verbose) {
29-
const child = new ForkedGulp(this.tasks);
30-
child.on("task_start", e => {
31-
if (countdown.remainingCount === 0) {
32-
countdown.reset(1);
33-
workStartedEvent.set();
34-
workStartedEvent.reset();
35-
}
36-
else {
37-
countdown.add();
38-
}
39-
if (verbose) {
40-
log('Starting', `'${chalk.cyan(e.task)}' ${chalk.gray(`(${countdown.remainingCount} remaining)`)}...`);
41-
}
42-
});
43-
child.on("task_stop", e => {
44-
countdown.signal();
45-
if (verbose) {
46-
log('Finished', `'${chalk.cyan(e.task)}' after ${chalk.magenta(prettyTime(/** @type {*}*/(e).hrDuration))} ${chalk.gray(`(${countdown.remainingCount} remaining)`)}`);
47-
}
48-
});
49-
child.on("task_err", e => {
50-
countdown.signal();
51-
if (verbose) {
52-
log(`'${chalk.cyan(e.task)}' ${chalk.red("errored after")} ${chalk.magenta(prettyTime(/** @type {*}*/(e).hrDuration))} ${chalk.gray(`(${countdown.remainingCount} remaining)`)}`);
53-
log(e.err ? e.err.stack : e.message);
54-
}
55-
});
56-
return child;
57-
}
58-
59-
// @ts-ignore
60-
start() {
61-
throw new Error("Not supported, use fork.");
62-
}
63-
}
64-
65-
class ForkedGulp extends gulp.Gulp {
66-
/**
67-
* @param {gulp.Gulp["tasks"]} tasks
68-
*/
69-
constructor(tasks) {
70-
super();
71-
this.tasks = tasks;
72-
}
73-
74-
// Do not reset tasks
75-
_resetAllTasks() {}
76-
_resetSpecificTasks() {}
77-
_resetTask() {}
78-
}
79-
8023
// internal `Gulp` instance for compilation artifacts.
81-
const compilationGulp = new CompilationGulp();
24+
const compilationGulp = new gulp.Gulp();
8225

8326
/** @type {Map<ResolvedProjectSpec, ProjectGraph>} */
8427
const projectGraphCache = new Map();
8528

8629
/** @type {Map<string, { typescript: string, alias: string, paths: ResolvedPathOptions }>} */
8730
const typescriptAliasMap = new Map();
8831

32+
// TODO: allow concurrent outer builds to be run in parallel
33+
const sem = new Semaphore(1);
34+
35+
/**
36+
* @param {string|string[]} taskName
37+
* @param {() => any} [cb]
38+
*/
39+
function start(taskName, cb) {
40+
return sem.wait().then(() => new Promise((resolve, reject) => {
41+
compilationGulp.start(taskName, err => {
42+
if (err) {
43+
reject(err);
44+
}
45+
else if (cb) {
46+
try {
47+
resolve(cb());
48+
}
49+
catch (e) {
50+
reject(err);
51+
}
52+
}
53+
else {
54+
resolve();
55+
}
56+
});
57+
})).then(() => {
58+
sem.release()
59+
}, e => {
60+
sem.release();
61+
throw e;
62+
});
63+
}
64+
8965
/**
9066
* Defines a gulp orchestration for a TypeScript project, returning a callback that can be used to trigger compilation.
9167
* @param {string} projectSpec The path to a tsconfig.json file or its containing directory.
@@ -98,9 +74,7 @@ function createCompiler(projectSpec, options) {
9874
const projectGraph = getOrCreateProjectGraph(resolvedProjectSpec, resolvedOptions.paths);
9975
projectGraph.isRoot = true;
10076
const taskName = compileTaskName(ensureCompileTask(projectGraph, resolvedOptions), resolvedOptions.typescript);
101-
return () => new Promise((resolve, reject) => compilationGulp
102-
.fork(resolvedOptions.verbose)
103-
.start(taskName, err => err ? reject(err) : resolve()));
77+
return () => start(taskName);
10478
}
10579
exports.createCompiler = createCompiler;
10680

@@ -139,9 +113,7 @@ function createCleaner(projectSpec, options) {
139113
const projectGraph = getOrCreateProjectGraph(resolvedProjectSpec, paths);
140114
projectGraph.isRoot = true;
141115
const taskName = cleanTaskName(ensureCleanTask(projectGraph));
142-
return () => new Promise((resolve, reject) => compilationGulp
143-
.fork()
144-
.start(taskName, err => err ? reject(err) : resolve()));
116+
return () => start(taskName);
145117
}
146118
exports.createCleaner = createCleaner;
147119

@@ -811,7 +783,7 @@ function possiblyTriggerRecompilation(config, task) {
811783
function triggerRecompilation(task, config) {
812784
compilationGulp._resetTask(task);
813785
if (config.watchers && config.watchers.size) {
814-
compilationGulp.fork().start(task.name, () => {
786+
start(task.name, () => {
815787
/** @type {Set<string>} */
816788
const taskNames = new Set();
817789
/** @type {((err?: any) => void)[]} */
@@ -831,7 +803,7 @@ function triggerRecompilation(task, config) {
831803
});
832804
}
833805
else {
834-
compilationGulp.fork(/*verbose*/ true).start(task.name);
806+
start(task.name);
835807
}
836808
}
837809

src/compiler/binder.ts

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ namespace ts {
100100
IsObjectLiteralOrClassExpressionMethod = 1 << 7,
101101
}
102102

103+
let flowNodeCreated: <T extends FlowNode>(node: T) => T = identity;
104+
103105
const binder = createBinder();
104106

105107
export function bindSourceFile(file: SourceFile, options: CompilerOptions) {
@@ -530,6 +532,7 @@ namespace ts {
530532
blockScopeContainer.locals = undefined;
531533
}
532534
if (containerFlags & ContainerFlags.IsControlFlowContainer) {
535+
const saveFlowNodeCreated = flowNodeCreated;
533536
const saveCurrentFlow = currentFlow;
534537
const saveBreakTarget = currentBreakTarget;
535538
const saveContinueTarget = currentContinueTarget;
@@ -553,6 +556,7 @@ namespace ts {
553556
currentContinueTarget = undefined;
554557
activeLabels = undefined;
555558
hasExplicitReturn = false;
559+
flowNodeCreated = identity;
556560
bindChildren(node);
557561
// Reset all reachability check related flags on node (for incremental scenarios)
558562
node.flags &= ~NodeFlags.ReachabilityAndEmitFlags;
@@ -579,6 +583,7 @@ namespace ts {
579583
currentReturnTarget = saveReturnTarget;
580584
activeLabels = saveActiveLabels;
581585
hasExplicitReturn = saveHasExplicitReturn;
586+
flowNodeCreated = saveFlowNodeCreated;
582587
}
583588
else if (containerFlags & ContainerFlags.IsInterface) {
584589
seenThisKeyword = false;
@@ -858,25 +863,25 @@ namespace ts {
858863
return antecedent;
859864
}
860865
setFlowNodeReferenced(antecedent);
861-
return { flags, expression, antecedent };
866+
return flowNodeCreated({ flags, expression, antecedent });
862867
}
863868

864869
function createFlowSwitchClause(antecedent: FlowNode, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number): FlowNode {
865870
if (!isNarrowingExpression(switchStatement.expression)) {
866871
return antecedent;
867872
}
868873
setFlowNodeReferenced(antecedent);
869-
return { flags: FlowFlags.SwitchClause, switchStatement, clauseStart, clauseEnd, antecedent };
874+
return flowNodeCreated({ flags: FlowFlags.SwitchClause, switchStatement, clauseStart, clauseEnd, antecedent });
870875
}
871876

872877
function createFlowAssignment(antecedent: FlowNode, node: Expression | VariableDeclaration | BindingElement): FlowNode {
873878
setFlowNodeReferenced(antecedent);
874-
return { flags: FlowFlags.Assignment, antecedent, node };
879+
return flowNodeCreated({ flags: FlowFlags.Assignment, antecedent, node });
875880
}
876881

877882
function createFlowArrayMutation(antecedent: FlowNode, node: CallExpression | BinaryExpression): FlowNode {
878883
setFlowNodeReferenced(antecedent);
879-
const res: FlowArrayMutation = { flags: FlowFlags.ArrayMutation, antecedent, node };
884+
const res: FlowArrayMutation = flowNodeCreated({ flags: FlowFlags.ArrayMutation, antecedent, node });
880885
return res;
881886
}
882887

@@ -1080,21 +1085,49 @@ namespace ts {
10801085
function bindTryStatement(node: TryStatement): void {
10811086
const preFinallyLabel = createBranchLabel();
10821087
const preTryFlow = currentFlow;
1083-
// TODO: Every statement in try block is potentially an exit point!
1088+
const tryPriors: FlowNode[] = [];
1089+
const oldFlowNodeCreated = flowNodeCreated;
1090+
// We hook the creation of all flow nodes within the `try` scope and store them so we can add _all_ of them
1091+
// as possible antecedents of the start of the `catch` or `finally` blocks.
1092+
// Don't bother intercepting the call if there's no finally or catch block that needs the information
1093+
if (node.catchClause || node.finallyBlock) {
1094+
flowNodeCreated = node => (tryPriors.push(node), node);
1095+
}
10841096
bind(node.tryBlock);
1097+
flowNodeCreated = oldFlowNodeCreated;
10851098
addAntecedent(preFinallyLabel, currentFlow);
10861099

10871100
const flowAfterTry = currentFlow;
10881101
let flowAfterCatch = unreachableFlow;
10891102

10901103
if (node.catchClause) {
10911104
currentFlow = preTryFlow;
1105+
if (tryPriors.length) {
1106+
const preCatchFlow = createBranchLabel();
1107+
addAntecedent(preCatchFlow, currentFlow);
1108+
for (const p of tryPriors) {
1109+
addAntecedent(preCatchFlow, p);
1110+
}
1111+
currentFlow = finishFlowLabel(preCatchFlow);
1112+
}
1113+
10921114
bind(node.catchClause);
10931115
addAntecedent(preFinallyLabel, currentFlow);
10941116

10951117
flowAfterCatch = currentFlow;
10961118
}
10971119
if (node.finallyBlock) {
1120+
// We add the nodes within the `try` block to the `finally`'s antecedents if there's no catch block
1121+
// (If there is a `catch` block, it will have all these antecedents instead, and the `finally` will
1122+
// have the end of the `try` block and the end of the `catch` block)
1123+
if (!node.catchClause) {
1124+
if (tryPriors.length) {
1125+
for (const p of tryPriors) {
1126+
addAntecedent(preFinallyLabel, p);
1127+
}
1128+
}
1129+
}
1130+
10981131
// in finally flow is combined from pre-try/flow from try/flow from catch
10991132
// pre-flow is necessary to make sure that finally is reachable even if finally flows in both try and finally blocks are unreachable
11001133

@@ -1142,7 +1175,7 @@ namespace ts {
11421175
}
11431176
}
11441177
if (!(currentFlow.flags & FlowFlags.Unreachable)) {
1145-
const afterFinallyFlow: AfterFinallyFlow = { flags: FlowFlags.AfterFinally, antecedent: currentFlow };
1178+
const afterFinallyFlow: AfterFinallyFlow = flowNodeCreated({ flags: FlowFlags.AfterFinally, antecedent: currentFlow });
11461179
preFinallyFlow.lock = afterFinallyFlow;
11471180
currentFlow = afterFinallyFlow;
11481181
}

0 commit comments

Comments
 (0)