Skip to content

Commit 25da965

Browse files
committed
Merge branch 'tsserverVS-WIP' into reuseTrees
2 parents a45ac24 + c5189dd commit 25da965

264 files changed

Lines changed: 8854 additions & 2860 deletions

File tree

Some content is hidden

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

Jakefile.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ var languageServiceLibrarySources = [
128128

129129
var harnessCoreSources = [
130130
"harness.ts",
131+
"virtualFileSystem.ts",
131132
"sourceMapRecorder.ts",
132133
"harnessLanguageService.ts",
133134
"fourslash.ts",
@@ -162,7 +163,8 @@ var harnessSources = harnessCoreSources.concat([
162163
"commandLineParsing.ts",
163164
"convertCompilerOptionsFromJson.ts",
164165
"convertTypingOptionsFromJson.ts",
165-
"tsserverProjectSystem.ts"
166+
"tsserverProjectSystem.ts",
167+
"matchFiles.ts"
166168
].map(function (f) {
167169
return path.join(unittestsDirectory, f);
168170
})).concat([

src/compiler/binder.ts

Lines changed: 90 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -578,20 +578,14 @@ namespace ts {
578578
}
579579
}
580580

581-
function isNarrowableReference(expr: Expression): boolean {
582-
return expr.kind === SyntaxKind.Identifier ||
583-
expr.kind === SyntaxKind.ThisKeyword ||
584-
expr.kind === SyntaxKind.PropertyAccessExpression && isNarrowableReference((<PropertyAccessExpression>expr).expression);
585-
}
586-
587581
function isNarrowingExpression(expr: Expression): boolean {
588582
switch (expr.kind) {
589583
case SyntaxKind.Identifier:
590584
case SyntaxKind.ThisKeyword:
591585
case SyntaxKind.PropertyAccessExpression:
592586
return isNarrowableReference(expr);
593587
case SyntaxKind.CallExpression:
594-
return true;
588+
return hasNarrowableArgument(<CallExpression>expr);
595589
case SyntaxKind.ParenthesizedExpression:
596590
return isNarrowingExpression((<ParenthesizedExpression>expr).expression);
597591
case SyntaxKind.BinaryExpression:
@@ -602,6 +596,39 @@ namespace ts {
602596
return false;
603597
}
604598

599+
function isNarrowableReference(expr: Expression): boolean {
600+
return expr.kind === SyntaxKind.Identifier ||
601+
expr.kind === SyntaxKind.ThisKeyword ||
602+
expr.kind === SyntaxKind.PropertyAccessExpression && isNarrowableReference((<PropertyAccessExpression>expr).expression);
603+
}
604+
605+
function hasNarrowableArgument(expr: CallExpression) {
606+
if (expr.arguments) {
607+
for (const argument of expr.arguments) {
608+
if (isNarrowableReference(argument)) {
609+
return true;
610+
}
611+
}
612+
}
613+
if (expr.expression.kind === SyntaxKind.PropertyAccessExpression &&
614+
isNarrowableReference((<PropertyAccessExpression>expr.expression).expression)) {
615+
return true;
616+
}
617+
return false;
618+
}
619+
620+
function isNarrowingNullCheckOperands(expr1: Expression, expr2: Expression) {
621+
return (expr1.kind === SyntaxKind.NullKeyword || expr1.kind === SyntaxKind.Identifier && (<Identifier>expr1).text === "undefined") && isNarrowableOperand(expr2);
622+
}
623+
624+
function isNarrowingTypeofOperands(expr1: Expression, expr2: Expression) {
625+
return expr1.kind === SyntaxKind.TypeOfExpression && isNarrowableOperand((<TypeOfExpression>expr1).expression) && expr2.kind === SyntaxKind.StringLiteral;
626+
}
627+
628+
function isNarrowingDiscriminant(expr: Expression) {
629+
return expr.kind === SyntaxKind.PropertyAccessExpression && isNarrowableReference((<PropertyAccessExpression>expr).expression);
630+
}
631+
605632
function isNarrowingBinaryExpression(expr: BinaryExpression) {
606633
switch (expr.operatorToken.kind) {
607634
case SyntaxKind.EqualsToken:
@@ -610,34 +637,35 @@ namespace ts {
610637
case SyntaxKind.ExclamationEqualsToken:
611638
case SyntaxKind.EqualsEqualsEqualsToken:
612639
case SyntaxKind.ExclamationEqualsEqualsToken:
613-
if ((isNarrowingExpression(expr.left) && (expr.right.kind === SyntaxKind.NullKeyword || expr.right.kind === SyntaxKind.Identifier)) ||
614-
(isNarrowingExpression(expr.right) && (expr.left.kind === SyntaxKind.NullKeyword || expr.left.kind === SyntaxKind.Identifier))) {
615-
return true;
616-
}
617-
if (isTypeOfNarrowingBinaryExpression(expr)) {
618-
return true;
619-
}
620-
return false;
640+
return isNarrowingNullCheckOperands(expr.right, expr.left) || isNarrowingNullCheckOperands(expr.left, expr.right) ||
641+
isNarrowingTypeofOperands(expr.right, expr.left) || isNarrowingTypeofOperands(expr.left, expr.right) ||
642+
isNarrowingDiscriminant(expr.left) || isNarrowingDiscriminant(expr.right);
621643
case SyntaxKind.InstanceOfKeyword:
622-
return isNarrowingExpression(expr.left);
644+
return isNarrowableOperand(expr.left);
623645
case SyntaxKind.CommaToken:
624646
return isNarrowingExpression(expr.right);
625647
}
626648
return false;
627649
}
628650

629-
function isTypeOfNarrowingBinaryExpression(expr: BinaryExpression) {
630-
let typeOf: Expression;
631-
if (expr.left.kind === SyntaxKind.StringLiteral) {
632-
typeOf = expr.right;
633-
}
634-
else if (expr.right.kind === SyntaxKind.StringLiteral) {
635-
typeOf = expr.left;
636-
}
637-
else {
638-
typeOf = undefined;
651+
function isNarrowableOperand(expr: Expression): boolean {
652+
switch (expr.kind) {
653+
case SyntaxKind.ParenthesizedExpression:
654+
return isNarrowableOperand((<ParenthesizedExpression>expr).expression);
655+
case SyntaxKind.BinaryExpression:
656+
switch ((<BinaryExpression>expr).operatorToken.kind) {
657+
case SyntaxKind.EqualsToken:
658+
return isNarrowableOperand((<BinaryExpression>expr).left);
659+
case SyntaxKind.CommaToken:
660+
return isNarrowableOperand((<BinaryExpression>expr).right);
661+
}
639662
}
640-
return typeOf && typeOf.kind === SyntaxKind.TypeOfExpression && isNarrowingExpression((<TypeOfExpression>typeOf).expression);
663+
return isNarrowableReference(expr);
664+
}
665+
666+
function isNarrowingSwitchStatement(switchStatement: SwitchStatement) {
667+
const expr = switchStatement.expression;
668+
return expr.kind === SyntaxKind.PropertyAccessExpression && isNarrowableReference((<PropertyAccessExpression>expr).expression);
641669
}
642670

643671
function createBranchLabel(): FlowLabel {
@@ -683,8 +711,22 @@ namespace ts {
683711
setFlowNodeReferenced(antecedent);
684712
return <FlowCondition>{
685713
flags,
686-
antecedent,
687714
expression,
715+
antecedent
716+
};
717+
}
718+
719+
function createFlowSwitchClause(antecedent: FlowNode, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number): FlowNode {
720+
if (!isNarrowingSwitchStatement(switchStatement)) {
721+
return antecedent;
722+
}
723+
setFlowNodeReferenced(antecedent);
724+
return <FlowSwitchClause>{
725+
flags: FlowFlags.SwitchClause,
726+
switchStatement,
727+
clauseStart,
728+
clauseEnd,
729+
antecedent
688730
};
689731
}
690732

@@ -913,9 +955,12 @@ namespace ts {
913955
preSwitchCaseFlow = currentFlow;
914956
bind(node.caseBlock);
915957
addAntecedent(postSwitchLabel, currentFlow);
916-
const hasNonEmptyDefault = forEach(node.caseBlock.clauses, c => c.kind === SyntaxKind.DefaultClause && c.statements.length);
917-
if (!hasNonEmptyDefault) {
918-
addAntecedent(postSwitchLabel, preSwitchCaseFlow);
958+
const hasDefault = forEach(node.caseBlock.clauses, c => c.kind === SyntaxKind.DefaultClause);
959+
// We mark a switch statement as possibly exhaustive if it has no default clause and if all
960+
// case clauses have unreachable end points (e.g. they all return).
961+
node.possiblyExhaustive = !hasDefault && !postSwitchLabel.antecedents;
962+
if (!hasDefault) {
963+
addAntecedent(postSwitchLabel, createFlowSwitchClause(preSwitchCaseFlow, node, 0, 0));
919964
}
920965
currentBreakTarget = saveBreakTarget;
921966
preSwitchCaseFlow = savePreSwitchCaseFlow;
@@ -924,25 +969,22 @@ namespace ts {
924969

925970
function bindCaseBlock(node: CaseBlock): void {
926971
const clauses = node.clauses;
972+
let fallthroughFlow = unreachableFlow;
927973
for (let i = 0; i < clauses.length; i++) {
928-
const clause = clauses[i];
929-
if (clause.statements.length) {
930-
if (currentFlow.flags & FlowFlags.Unreachable) {
931-
currentFlow = preSwitchCaseFlow;
932-
}
933-
else {
934-
const preCaseLabel = createBranchLabel();
935-
addAntecedent(preCaseLabel, preSwitchCaseFlow);
936-
addAntecedent(preCaseLabel, currentFlow);
937-
currentFlow = finishFlowLabel(preCaseLabel);
938-
}
939-
bind(clause);
940-
if (!(currentFlow.flags & FlowFlags.Unreachable) && i !== clauses.length - 1 && options.noFallthroughCasesInSwitch) {
941-
errorOnFirstToken(clause, Diagnostics.Fallthrough_case_in_switch);
942-
}
974+
const clauseStart = i;
975+
while (!clauses[i].statements.length && i + 1 < clauses.length) {
976+
bind(clauses[i]);
977+
i++;
943978
}
944-
else {
945-
bind(clause);
979+
const preCaseLabel = createBranchLabel();
980+
addAntecedent(preCaseLabel, createFlowSwitchClause(preSwitchCaseFlow, <SwitchStatement>node.parent, clauseStart, i + 1));
981+
addAntecedent(preCaseLabel, fallthroughFlow);
982+
currentFlow = finishFlowLabel(preCaseLabel);
983+
const clause = clauses[i];
984+
bind(clause);
985+
fallthroughFlow = currentFlow;
986+
if (!(currentFlow.flags & FlowFlags.Unreachable) && i !== clauses.length - 1 && options.noFallthroughCasesInSwitch) {
987+
errorOnFirstToken(clause, Diagnostics.Fallthrough_case_in_switch);
946988
}
947989
}
948990
}

0 commit comments

Comments
 (0)