Skip to content

Commit 766010e

Browse files
committed
Parentheses in type literals
1 parent ad6203f commit 766010e

File tree

3 files changed

+70
-12
lines changed

3 files changed

+70
-12
lines changed

src/compiler/checker.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2831,6 +2831,8 @@ module ts {
28312831
return getTypeFromTupleTypeNode(<TupleTypeNode>node);
28322832
case SyntaxKind.UnionType:
28332833
return getTypeFromUnionTypeNode(<UnionTypeNode>node);
2834+
case SyntaxKind.ParenType:
2835+
return getTypeFromTypeNode((<ParenTypeNode>node).type);
28342836
case SyntaxKind.TypeLiteral:
28352837
return getTypeFromTypeLiteralNode(<TypeLiteralNode>node);
28362838
// This function assumes that an identifier or qualified name is a type expression
@@ -7480,6 +7482,8 @@ module ts {
74807482
return checkTupleType(<TupleTypeNode>node);
74817483
case SyntaxKind.UnionType:
74827484
return checkUnionType(<UnionTypeNode>node);
7485+
case SyntaxKind.ParenType:
7486+
return checkSourceElement((<ParenTypeNode>node).type);
74837487
case SyntaxKind.FunctionDeclaration:
74847488
return checkFunctionDeclaration(<FunctionDeclaration>node);
74857489
case SyntaxKind.Block:

src/compiler/parser.ts

Lines changed: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,8 @@ module ts {
227227
return children((<TupleTypeNode>node).elementTypes);
228228
case SyntaxKind.UnionType:
229229
return children((<UnionTypeNode>node).types);
230+
case SyntaxKind.ParenType:
231+
return child((<ParenTypeNode>node).type);
230232
case SyntaxKind.ArrayLiteral:
231233
return children((<ArrayLiteral>node).elements);
232234
case SyntaxKind.ObjectLiteral:
@@ -1660,6 +1662,14 @@ module ts {
16601662
return finishNode(node);
16611663
}
16621664

1665+
function parseParenType(): ParenTypeNode {
1666+
var node = <ParenTypeNode>createNode(SyntaxKind.ParenType);
1667+
parseExpected(SyntaxKind.OpenParenToken);
1668+
node.type = parseType();
1669+
parseExpected(SyntaxKind.CloseParenToken);
1670+
return finishNode(node);
1671+
}
1672+
16631673
function parseFunctionType(signatureKind: SyntaxKind): TypeLiteralNode {
16641674
var node = <TypeLiteralNode>createNode(SyntaxKind.TypeLiteral);
16651675
var member = <SignatureDeclaration>createNode(signatureKind);
@@ -1693,10 +1703,7 @@ module ts {
16931703
case SyntaxKind.OpenBracketToken:
16941704
return parseTupleType();
16951705
case SyntaxKind.OpenParenToken:
1696-
case SyntaxKind.LessThanToken:
1697-
return parseFunctionType(SyntaxKind.CallSignature);
1698-
case SyntaxKind.NewKeyword:
1699-
return parseFunctionType(SyntaxKind.ConstructSignature);
1706+
return parseParenType();
17001707
default:
17011708
if (isIdentifier()) {
17021709
return parseTypeReference();
@@ -1720,18 +1727,18 @@ module ts {
17201727
case SyntaxKind.NewKeyword:
17211728
return true;
17221729
case SyntaxKind.OpenParenToken:
1723-
// Only consider an ( as the start of a type if we have () or (id
1724-
// We don't want to consider things like (1) as a function type.
1730+
// Only consider '(' the start of a type if followed by ')', '...', an identifier, a modifier,
1731+
// or something that starts a type. We don't want to consider things like '(1)' a type.
17251732
return lookAhead(() => {
17261733
nextToken();
1727-
return token === SyntaxKind.CloseParenToken || isParameter();
1734+
return token === SyntaxKind.CloseParenToken || isParameter() || isType();
17281735
});
17291736
default:
17301737
return isIdentifier();
17311738
}
17321739
}
17331740

1734-
function parseNonUnionType(): TypeNode {
1741+
function parsePrimaryType(): TypeNode {
17351742
var type = parseNonArrayType();
17361743
while (!scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind.OpenBracketToken)) {
17371744
parseExpected(SyntaxKind.CloseBracketToken);
@@ -1742,13 +1749,13 @@ module ts {
17421749
return type;
17431750
}
17441751

1745-
function parseType(): TypeNode {
1746-
var type = parseNonUnionType();
1752+
function parseUnionType(): TypeNode {
1753+
var type = parsePrimaryType();
17471754
if (token === SyntaxKind.BarToken) {
17481755
var types = <NodeArray<TypeNode>>[type];
17491756
types.pos = type.pos;
17501757
while (parseOptional(SyntaxKind.BarToken)) {
1751-
types.push(parseNonUnionType());
1758+
types.push(parsePrimaryType());
17521759
}
17531760
types.end = getNodeEnd();
17541761
var node = <UnionTypeNode>createNode(SyntaxKind.UnionType, type.pos);
@@ -1758,6 +1765,48 @@ module ts {
17581765
return type;
17591766
}
17601767

1768+
function isFunctionType(): boolean {
1769+
return token === SyntaxKind.LessThanToken || token === SyntaxKind.OpenParenToken && lookAhead(() => {
1770+
nextToken();
1771+
if (token === SyntaxKind.CloseParenToken || token === SyntaxKind.DotDotDotToken) {
1772+
// ( )
1773+
// ( ...
1774+
return true;
1775+
}
1776+
if (isIdentifier() || isModifier(token)) {
1777+
nextToken();
1778+
if (token === SyntaxKind.ColonToken || token === SyntaxKind.CommaToken ||
1779+
token === SyntaxKind.QuestionToken || token === SyntaxKind.EqualsToken ||
1780+
isIdentifier() || isModifier(token)) {
1781+
// ( id :
1782+
// ( id ,
1783+
// ( id ?
1784+
// ( id =
1785+
// ( modifier id
1786+
return true;
1787+
}
1788+
if (token === SyntaxKind.CloseParenToken) {
1789+
nextToken();
1790+
if (token === SyntaxKind.EqualsGreaterThanToken) {
1791+
// ( id ) =>
1792+
return true;
1793+
}
1794+
}
1795+
}
1796+
return false;
1797+
});
1798+
}
1799+
1800+
function parseType(): TypeNode {
1801+
if (isFunctionType()) {
1802+
return parseFunctionType(SyntaxKind.CallSignature);
1803+
}
1804+
if (token === SyntaxKind.NewKeyword) {
1805+
return parseFunctionType(SyntaxKind.ConstructSignature);
1806+
}
1807+
return parseUnionType();
1808+
}
1809+
17611810
function parseTypeAnnotation(): TypeNode {
17621811
return parseOptional(SyntaxKind.ColonToken) ? parseType() : undefined;
17631812
}

src/compiler/types.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ module ts {
155155
ArrayType,
156156
TupleType,
157157
UnionType,
158+
ParenType,
158159
// Expression
159160
ArrayLiteral,
160161
ObjectLiteral,
@@ -225,7 +226,7 @@ module ts {
225226
FirstFutureReservedWord = ImplementsKeyword,
226227
LastFutureReservedWord = YieldKeyword,
227228
FirstTypeNode = TypeReference,
228-
LastTypeNode = UnionType,
229+
LastTypeNode = ParenType,
229230
FirstPunctuation = OpenBraceToken,
230231
LastPunctuation = CaretEqualsToken,
231232
FirstToken = EndOfFileToken,
@@ -342,6 +343,10 @@ module ts {
342343
types: NodeArray<TypeNode>;
343344
}
344345

346+
export interface ParenTypeNode extends TypeNode {
347+
type: TypeNode;
348+
}
349+
345350
export interface StringLiteralTypeNode extends TypeNode {
346351
text: string;
347352
}

0 commit comments

Comments
 (0)