Skip to content
10 changes: 5 additions & 5 deletions src/compiler/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -348,8 +348,8 @@ module ts {
bindChildren(node, symbolKind, isBlockScopeContainer);
}

function bindCatchVariableDeclaration(node: CatchBlock) {
var symbol = createSymbol(SymbolFlags.FunctionScopedVariable, node.variable.text || "__missing");
function bindCatchVariableDeclaration(node: CatchClause) {
var symbol = createSymbol(SymbolFlags.FunctionScopedVariable, node.name.text || "__missing");
addDeclarationToSymbol(symbol, node, SymbolFlags.FunctionScopedVariable);
var saveParent = parent;
var savedBlockScopeContainer = blockScopeContainer;
Expand Down Expand Up @@ -444,8 +444,8 @@ module ts {
case SyntaxKind.ArrowFunction:
bindAnonymousDeclaration(<FunctionExpression>node, SymbolFlags.Function, "__function", /*isBlockScopeContainer*/ true);
break;
case SyntaxKind.CatchBlock:
bindCatchVariableDeclaration(<CatchBlock>node);
case SyntaxKind.CatchClause:
bindCatchVariableDeclaration(<CatchClause>node);
break;
case SyntaxKind.ClassDeclaration:
bindDeclaration(<Declaration>node, SymbolFlags.Class, SymbolFlags.ClassExcludes, /*isBlockScopeContainer*/ false);
Expand Down Expand Up @@ -478,7 +478,7 @@ module ts {

case SyntaxKind.Block:
case SyntaxKind.TryBlock:
case SyntaxKind.CatchBlock:
case SyntaxKind.CatchClause:
case SyntaxKind.FinallyBlock:
case SyntaxKind.ForStatement:
case SyntaxKind.ForInStatement:
Expand Down
81 changes: 50 additions & 31 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -415,8 +415,8 @@ module ts {
break loop;
}
break;
case SyntaxKind.CatchBlock:
var id = (<CatchBlock>location).variable;
case SyntaxKind.CatchClause:
var id = (<CatchClause>location).name;
if (name === id.text) {
result = location.symbol;
break loop;
Expand Down Expand Up @@ -756,7 +756,7 @@ module ts {
//
// x is an optional parameter, but it is a required property.
return propertySymbol.valueDeclaration &&
propertySymbol.valueDeclaration.flags & NodeFlags.QuestionMark &&
hasQuestionToken(propertySymbol.valueDeclaration) &&
propertySymbol.valueDeclaration.kind !== SyntaxKind.Parameter;
}

Expand Down Expand Up @@ -1437,11 +1437,11 @@ module ts {
}

function buildParameterDisplay(p: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
if (getDeclarationFlagsFromSymbol(p) & NodeFlags.Rest) {
if (hasDotDotDotToken(p.valueDeclaration)) {
writePunctuation(writer, SyntaxKind.DotDotDotToken);
}
appendSymbolNameOnly(p, writer);
if (p.valueDeclaration.flags & NodeFlags.QuestionMark || (<VariableDeclaration>p.valueDeclaration).initializer) {
if (hasQuestionToken(p.valueDeclaration) || (<VariableDeclaration>p.valueDeclaration).initializer) {
writePunctuation(writer, SyntaxKind.QuestionToken);
}
writePunctuation(writer, SyntaxKind.ColonToken);
Expand Down Expand Up @@ -1711,7 +1711,7 @@ module ts {
}

// Rest parameters default to type any[], other parameters default to type any
var type = declaration.flags & NodeFlags.Rest ? createArrayType(anyType) : anyType;
var type = hasDotDotDotToken(declaration) ? createArrayType(anyType) : anyType;
checkImplicitAny(type);
return type;

Expand All @@ -1733,9 +1733,9 @@ module ts {
var diagnostic = Diagnostics.Member_0_implicitly_has_an_1_type;
break;
case SyntaxKind.Parameter:
var diagnostic = declaration.flags & NodeFlags.Rest ?
Diagnostics.Rest_parameter_0_implicitly_has_an_any_type :
Diagnostics.Parameter_0_implicitly_has_an_1_type;
var diagnostic = hasDotDotDotToken(declaration)
? Diagnostics.Rest_parameter_0_implicitly_has_an_any_type
: Diagnostics.Parameter_0_implicitly_has_an_1_type;
break;
default:
var diagnostic = Diagnostics.Variable_0_implicitly_has_an_1_type;
Expand All @@ -1753,7 +1753,7 @@ module ts {
}
// Handle catch clause variables
var declaration = symbol.valueDeclaration;
if (declaration.kind === SyntaxKind.CatchBlock) {
if (declaration.kind === SyntaxKind.CatchClause) {
return links.type = anyType;
}
// Handle variable, parameter or property
Expand Down Expand Up @@ -2527,7 +2527,7 @@ module ts {
hasStringLiterals = true;
}
if (minArgumentCount < 0) {
if (param.initializer || param.flags & (NodeFlags.QuestionMark | NodeFlags.Rest)) {
if (param.initializer || param.questionToken || param.dotDotDotToken) {
minArgumentCount = i;
}
}
Expand Down Expand Up @@ -4375,7 +4375,7 @@ module ts {
case SyntaxKind.ThrowStatement:
case SyntaxKind.TryStatement:
case SyntaxKind.TryBlock:
case SyntaxKind.CatchBlock:
case SyntaxKind.CatchClause:
case SyntaxKind.FinallyBlock:
return forEachChild(node, isAssignedIn);
}
Expand Down Expand Up @@ -6673,7 +6673,7 @@ module ts {
!(parameterDeclaration.parent.kind === SyntaxKind.Constructor && (<ConstructorDeclaration>parameterDeclaration.parent).body)) {
error(parameterDeclaration, Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation);
}
if (parameterDeclaration.flags & NodeFlags.Rest) {
if (parameterDeclaration.dotDotDotToken) {
if (!isArrayType(getTypeOfSymbol(parameterDeclaration.symbol))) {
error(parameterDeclaration, Diagnostics.A_rest_parameter_must_be_of_an_array_type);
}
Expand Down Expand Up @@ -7020,20 +7020,23 @@ module ts {
return;
}

function getCanonicalOverload(overloads: Declaration[], implementation: FunctionLikeDeclaration) {
// Consider the canonical set of flags to be the flags of the bodyDeclaration or the first declaration
// Error on all deviations from this canonical set of flags
// The caveat is that if some overloads are defined in lib.d.ts, we don't want to
// report the errors on those. To achieve this, we will say that the implementation is
// the canonical signature only if it is in the same container as the first overload
var implementationSharesContainerWithFirstOverload = implementation !== undefined && implementation.parent === overloads[0].parent;
return implementationSharesContainerWithFirstOverload ? implementation : overloads[0];
}

function checkFlagAgreementBetweenOverloads(overloads: Declaration[], implementation: FunctionLikeDeclaration, flagsToCheck: NodeFlags, someOverloadFlags: NodeFlags, allOverloadFlags: NodeFlags): void {
// Error if some overloads have a flag that is not shared by all overloads. To find the
// deviations, we XOR someOverloadFlags with allOverloadFlags
var someButNotAllOverloadFlags = someOverloadFlags ^ allOverloadFlags;
if (someButNotAllOverloadFlags !== 0) {
// Consider the canonical set of flags to be the flags of the bodyDeclaration or the first declaration
// Error on all deviations from this canonical set of flags
// The caveat is that if some overloads are defined in lib.d.ts, we don't want to
// report the errors on those. To achieve this, we will say that the implementation is
// the canonical signature only if it is in the same container as the first overload
var implementationSharesContainerWithFirstOverload = implementation !== undefined && implementation.parent === overloads[0].parent;
var canonicalFlags = implementationSharesContainerWithFirstOverload
? getEffectiveDeclarationFlags(implementation, flagsToCheck)
: getEffectiveDeclarationFlags(overloads[0], flagsToCheck);
var canonicalFlags = getEffectiveDeclarationFlags(getCanonicalOverload(overloads, implementation), flagsToCheck);

forEach(overloads, o => {
var deviation = getEffectiveDeclarationFlags(o, flagsToCheck) ^ canonicalFlags;
if (deviation & NodeFlags.Export) {
Expand All @@ -7045,16 +7048,27 @@ module ts {
else if (deviation & (NodeFlags.Private | NodeFlags.Protected)) {
error(o.name, Diagnostics.Overload_signatures_must_all_be_public_private_or_protected);
}
else if (deviation & NodeFlags.QuestionMark) {
});
}
}

function checkQuestionTokenAgreementBetweenOverloads(overloads: Declaration[], implementation: FunctionLikeDeclaration, someHaveQuestionToken: boolean, allHaveQuestionToken: boolean): void {
if (someHaveQuestionToken !== allHaveQuestionToken) {
var canonicalHasQuestionToken = hasQuestionToken(getCanonicalOverload(overloads, implementation));
forEach(overloads, o => {
var deviation = hasQuestionToken(o) !== canonicalHasQuestionToken;
if (deviation) {
error(o.name, Diagnostics.Overload_signatures_must_all_be_optional_or_required);
}
});
}
}

var flagsToCheck: NodeFlags = NodeFlags.Export | NodeFlags.Ambient | NodeFlags.Private | NodeFlags.Protected | NodeFlags.QuestionMark;
var flagsToCheck: NodeFlags = NodeFlags.Export | NodeFlags.Ambient | NodeFlags.Private | NodeFlags.Protected;
var someNodeFlags: NodeFlags = 0;
var allNodeFlags = flagsToCheck;
var someHaveQuestionToken = false;
var allHaveQuestionToken = true;
var hasOverloads = false;
var bodyDeclaration: FunctionLikeDeclaration;
var lastSeenNonAmbientDeclaration: FunctionLikeDeclaration;
Expand Down Expand Up @@ -7128,6 +7142,8 @@ module ts {
var currentNodeFlags = getEffectiveDeclarationFlags(node, flagsToCheck);
someNodeFlags |= currentNodeFlags;
allNodeFlags &= currentNodeFlags;
someHaveQuestionToken = someHaveQuestionToken || hasQuestionToken(node);
allHaveQuestionToken = allHaveQuestionToken && hasQuestionToken(node);

if (node.body && bodyDeclaration) {
if (isConstructor) {
Expand Down Expand Up @@ -7176,6 +7192,8 @@ module ts {

if (hasOverloads) {
checkFlagAgreementBetweenOverloads(declarations, bodyDeclaration, flagsToCheck, someNodeFlags, allNodeFlags);
checkQuestionTokenAgreementBetweenOverloads(declarations, bodyDeclaration, someHaveQuestionToken, allHaveQuestionToken);

if (bodyDeclaration) {
var signatures = getSignaturesOfSymbol(symbol);
var bodySignature = getSignatureFromDeclaration(bodyDeclaration);
Expand Down Expand Up @@ -7725,13 +7743,14 @@ module ts {
function checkSwitchStatement(node: SwitchStatement) {
var expressionType = checkExpression(node.expression);
forEach(node.clauses, clause => {
if (fullTypeCheck && clause.expression) {
if (fullTypeCheck && clause.kind === SyntaxKind.CaseClause) {
var caseClause = <CaseClause>clause;
// TypeScript 1.0 spec (April 2014):5.9
// In a 'switch' statement, each 'case' expression must be of a type that is assignable to or from the type of the 'switch' expression.
var caseType = checkExpression(clause.expression);
var caseType = checkExpression(caseClause.expression);
if (!isTypeAssignableTo(expressionType, caseType)) {
// check 'expressionType isAssignableTo caseType' failed, try the reversed check and report errors if it fails
checkTypeAssignableTo(caseType, expressionType, clause.expression, /*headMessage*/ undefined);
checkTypeAssignableTo(caseType, expressionType, caseClause.expression, /*headMessage*/ undefined);
}
}
forEach(clause.statements, checkSourceElement);
Expand All @@ -7748,7 +7767,7 @@ module ts {

function checkTryStatement(node: TryStatement) {
checkBlock(node.tryBlock);
if (node.catchBlock) checkBlock(node.catchBlock);
if (node.catchClause) checkBlock(node.catchClause.block);
if (node.finallyBlock) checkBlock(node.finallyBlock);
}

Expand Down Expand Up @@ -8586,7 +8605,7 @@ module ts {
case SyntaxKind.ThrowStatement:
case SyntaxKind.TryStatement:
case SyntaxKind.TryBlock:
case SyntaxKind.CatchBlock:
case SyntaxKind.CatchClause:
case SyntaxKind.FinallyBlock:
case SyntaxKind.VariableDeclaration:
case SyntaxKind.ClassDeclaration:
Expand Down Expand Up @@ -8748,8 +8767,8 @@ module ts {
copySymbol(location.symbol, meaning);
}
break;
case SyntaxKind.CatchBlock:
if ((<CatchBlock>location).variable.text) {
case SyntaxKind.CatchClause:
if ((<CatchClause>location).name.text) {
copySymbol(location.symbol, meaning);
}
break;
Expand Down
28 changes: 14 additions & 14 deletions src/compiler/emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -943,7 +943,7 @@ module ts {
if (node.kind !== SyntaxKind.VariableDeclaration || resolver.isDeclarationVisible(node)) {
writeTextOfNode(currentSourceFile, node.name);
// If optional property emit ?
if (node.kind === SyntaxKind.Property && (node.flags & NodeFlags.QuestionMark)) {
if (node.kind === SyntaxKind.Property && hasQuestionToken(node)) {
write("?");
}
if (node.kind === SyntaxKind.Property && node.parent.kind === SyntaxKind.TypeLiteral) {
Expand Down Expand Up @@ -1124,7 +1124,7 @@ module ts {
}
else {
writeTextOfNode(currentSourceFile, node.name);
if (node.flags & NodeFlags.QuestionMark) {
if (hasQuestionToken(node)) {
write("?");
}
}
Expand Down Expand Up @@ -1252,11 +1252,11 @@ module ts {
function emitParameterDeclaration(node: ParameterDeclaration) {
increaseIndent();
emitJsDocComments(node);
if (node.flags & NodeFlags.Rest) {
if (node.dotDotDotToken) {
write("...");
}
writeTextOfNode(currentSourceFile, node.name);
if (node.initializer || (node.flags & NodeFlags.QuestionMark)) {
if (node.initializer || hasQuestionToken(node)) {
write("?");
}
decreaseIndent();
Expand Down Expand Up @@ -2142,8 +2142,8 @@ module ts {
return false;
case SyntaxKind.LabeledStatement:
return (<LabeledStatement>node.parent).label === node;
case SyntaxKind.CatchBlock:
return (<CatchBlock>node.parent).variable === node;
case SyntaxKind.CatchClause:
return (<CatchClause>node.parent).name === node;
}
}

Expand Down Expand Up @@ -2624,7 +2624,7 @@ module ts {
function emitCaseOrDefaultClause(node: CaseOrDefaultClause) {
if (node.kind === SyntaxKind.CaseClause) {
write("case ");
emit(node.expression);
emit((<CaseClause>node).expression);
write(":");
}
else {
Expand All @@ -2650,23 +2650,23 @@ module ts {
function emitTryStatement(node: TryStatement) {
write("try ");
emit(node.tryBlock);
emit(node.catchBlock);
emit(node.catchClause);
if (node.finallyBlock) {
writeLine();
write("finally ");
emit(node.finallyBlock);
}
}

function emitCatchBlock(node: CatchBlock) {
function emitCatchClause(node: CatchClause) {
writeLine();
var endPos = emitToken(SyntaxKind.CatchKeyword, node.pos);
write(" ");
emitToken(SyntaxKind.OpenParenToken, endPos);
emit(node.variable);
emitToken(SyntaxKind.CloseParenToken, node.variable.end);
emit(node.name);
emitToken(SyntaxKind.CloseParenToken, node.name.end);
write(" ");
emitBlock(node);
emitBlock(node.block);
}

function emitDebuggerStatement(node: Node) {
Expand Down Expand Up @@ -3599,8 +3599,8 @@ module ts {
return emitThrowStatement(<ThrowStatement>node);
case SyntaxKind.TryStatement:
return emitTryStatement(<TryStatement>node);
case SyntaxKind.CatchBlock:
return emitCatchBlock(<CatchBlock>node);
case SyntaxKind.CatchClause:
return emitCatchClause(<CatchClause>node);
case SyntaxKind.DebuggerStatement:
return emitDebuggerStatement(node);
case SyntaxKind.VariableDeclaration:
Expand Down
Loading