@@ -1472,7 +1472,7 @@ module ts {
1472
1472
return appendParentTypeArgumentsAndSymbolName(symbol);
1473
1473
}
1474
1474
1475
- function buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, globalFlags?: TypeFormatFlags, typeStack ?: Type []) {
1475
+ function buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, globalFlags?: TypeFormatFlags, symbolStack ?: Symbol []) {
1476
1476
let globalFlagsToPass = globalFlags & TypeFormatFlags.WriteOwnNameForAnyLike;
1477
1477
return writeType(type, globalFlags);
1478
1478
@@ -1557,49 +1557,54 @@ module ts {
1557
1557
}
1558
1558
1559
1559
function writeAnonymousType(type: ObjectType, flags: TypeFormatFlags) {
1560
- // Always use 'typeof T' for type of class, enum, and module objects
1561
- if (type.symbol && type.symbol.flags & (SymbolFlags.Class | SymbolFlags.Enum | SymbolFlags.ValueModule)) {
1562
- writeTypeofSymbol(type, flags);
1563
- }
1564
- // Use 'typeof T' for types of functions and methods that circularly reference themselves
1565
- else if (shouldWriteTypeOfFunctionSymbol()) {
1566
- writeTypeofSymbol(type, flags);
1567
- }
1568
- else if (typeStack && contains(typeStack, type)) {
1569
- // If type is an anonymous type literal in a type alias declaration, use type alias name
1570
- let typeAlias = getTypeAliasForTypeLiteral(type);
1571
- if (typeAlias) {
1572
- // The specified symbol flags need to be reinterpreted as type flags
1573
- buildSymbolDisplay(typeAlias, writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, flags);
1560
+ let symbol = type.symbol;
1561
+ if (symbol) {
1562
+ // Always use 'typeof T' for type of class, enum, and module objects
1563
+ if (symbol.flags & (SymbolFlags.Class | SymbolFlags.Enum | SymbolFlags.ValueModule)) {
1564
+ writeTypeofSymbol(type, flags);
1565
+ }
1566
+ else if (shouldWriteTypeOfFunctionSymbol()) {
1567
+ writeTypeofSymbol(type, flags);
1568
+ }
1569
+ else if (contains(symbolStack, symbol)) {
1570
+ // If type is an anonymous type literal in a type alias declaration, use type alias name
1571
+ let typeAlias = getTypeAliasForTypeLiteral(type);
1572
+ if (typeAlias) {
1573
+ // The specified symbol flags need to be reinterpreted as type flags
1574
+ buildSymbolDisplay(typeAlias, writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, flags);
1575
+ }
1576
+ else {
1577
+ // Recursive usage, use any
1578
+ writeKeyword(writer, SyntaxKind.AnyKeyword);
1579
+ }
1574
1580
}
1575
1581
else {
1576
- // Recursive usage, use any
1577
- writeKeyword(writer, SyntaxKind.AnyKeyword);
1582
+ // Since instantiations of the same anonymous type have the same symbol, tracking symbols instead
1583
+ // of types allows us to catch circular references to instantiations of the same anonymous type
1584
+ if (!symbolStack) {
1585
+ symbolStack = [];
1586
+ }
1587
+ symbolStack.push(symbol);
1588
+ writeLiteralType(type, flags);
1589
+ symbolStack.pop();
1578
1590
}
1579
1591
}
1580
1592
else {
1581
- if (!typeStack) {
1582
- typeStack = [];
1583
- }
1584
- typeStack.push(type);
1593
+ // Anonymous types with no symbol are never circular
1585
1594
writeLiteralType(type, flags);
1586
- typeStack.pop();
1587
1595
}
1588
1596
1589
1597
function shouldWriteTypeOfFunctionSymbol() {
1590
- if (type.symbol) {
1591
- let isStaticMethodSymbol = !!(type.symbol.flags & SymbolFlags.Method && // typeof static method
1592
- ts.forEach(type.symbol.declarations, declaration => declaration.flags & NodeFlags.Static));
1593
- let isNonLocalFunctionSymbol = !!(type.symbol.flags & SymbolFlags.Function) &&
1594
- (type.symbol.parent || // is exported function symbol
1595
- ts.forEach(type.symbol.declarations, declaration =>
1596
- declaration.parent.kind === SyntaxKind.SourceFile || declaration.parent.kind === SyntaxKind.ModuleBlock));
1597
-
1598
- if (isStaticMethodSymbol || isNonLocalFunctionSymbol) {
1599
- // typeof is allowed only for static/non local functions
1600
- return !!(flags & TypeFormatFlags.UseTypeOfFunction) || // use typeof if format flags specify it
1601
- (typeStack && contains(typeStack, type)); // it is type of the symbol uses itself recursively
1602
- }
1598
+ let isStaticMethodSymbol = !!(symbol.flags & SymbolFlags.Method && // typeof static method
1599
+ forEach(symbol.declarations, declaration => declaration.flags & NodeFlags.Static));
1600
+ let isNonLocalFunctionSymbol = !!(symbol.flags & SymbolFlags.Function) &&
1601
+ (symbol.parent || // is exported function symbol
1602
+ forEach(symbol.declarations, declaration =>
1603
+ declaration.parent.kind === SyntaxKind.SourceFile || declaration.parent.kind === SyntaxKind.ModuleBlock));
1604
+ if (isStaticMethodSymbol || isNonLocalFunctionSymbol) {
1605
+ // typeof is allowed only for static/non local functions
1606
+ return !!(flags & TypeFormatFlags.UseTypeOfFunction) || // use typeof if format flags specify it
1607
+ (contains(symbolStack, symbol)); // it is type of the symbol uses itself recursively
1603
1608
}
1604
1609
}
1605
1610
}
@@ -1634,7 +1639,7 @@ module ts {
1634
1639
if (flags & TypeFormatFlags.InElementType) {
1635
1640
writePunctuation(writer, SyntaxKind.OpenParenToken);
1636
1641
}
1637
- buildSignatureDisplay(resolved.callSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | TypeFormatFlags.WriteArrowStyleSignature, typeStack );
1642
+ buildSignatureDisplay(resolved.callSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | TypeFormatFlags.WriteArrowStyleSignature, symbolStack );
1638
1643
if (flags & TypeFormatFlags.InElementType) {
1639
1644
writePunctuation(writer, SyntaxKind.CloseParenToken);
1640
1645
}
@@ -1646,7 +1651,7 @@ module ts {
1646
1651
}
1647
1652
writeKeyword(writer, SyntaxKind.NewKeyword);
1648
1653
writeSpace(writer);
1649
- buildSignatureDisplay(resolved.constructSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | TypeFormatFlags.WriteArrowStyleSignature, typeStack );
1654
+ buildSignatureDisplay(resolved.constructSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | TypeFormatFlags.WriteArrowStyleSignature, symbolStack );
1650
1655
if (flags & TypeFormatFlags.InElementType) {
1651
1656
writePunctuation(writer, SyntaxKind.CloseParenToken);
1652
1657
}
@@ -1658,15 +1663,15 @@ module ts {
1658
1663
writer.writeLine();
1659
1664
writer.increaseIndent();
1660
1665
for (let signature of resolved.callSignatures) {
1661
- buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, typeStack );
1666
+ buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, symbolStack );
1662
1667
writePunctuation(writer, SyntaxKind.SemicolonToken);
1663
1668
writer.writeLine();
1664
1669
}
1665
1670
for (let signature of resolved.constructSignatures) {
1666
1671
writeKeyword(writer, SyntaxKind.NewKeyword);
1667
1672
writeSpace(writer);
1668
1673
1669
- buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, typeStack );
1674
+ buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, symbolStack );
1670
1675
writePunctuation(writer, SyntaxKind.SemicolonToken);
1671
1676
writer.writeLine();
1672
1677
}
@@ -1707,7 +1712,7 @@ module ts {
1707
1712
if (p.flags & SymbolFlags.Optional) {
1708
1713
writePunctuation(writer, SyntaxKind.QuestionToken);
1709
1714
}
1710
- buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, typeStack );
1715
+ buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, symbolStack );
1711
1716
writePunctuation(writer, SyntaxKind.SemicolonToken);
1712
1717
writer.writeLine();
1713
1718
}
@@ -1736,18 +1741,18 @@ module ts {
1736
1741
}
1737
1742
}
1738
1743
1739
- function buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack ?: Type []) {
1744
+ function buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack ?: Symbol []) {
1740
1745
appendSymbolNameOnly(tp.symbol, writer);
1741
1746
let constraint = getConstraintOfTypeParameter(tp);
1742
1747
if (constraint) {
1743
1748
writeSpace(writer);
1744
1749
writeKeyword(writer, SyntaxKind.ExtendsKeyword);
1745
1750
writeSpace(writer);
1746
- buildTypeDisplay(constraint, writer, enclosingDeclaration, flags, typeStack );
1751
+ buildTypeDisplay(constraint, writer, enclosingDeclaration, flags, symbolStack );
1747
1752
}
1748
1753
}
1749
1754
1750
- function buildParameterDisplay(p: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack ?: Type []) {
1755
+ function buildParameterDisplay(p: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack ?: Symbol []) {
1751
1756
if (hasDotDotDotToken(p.valueDeclaration)) {
1752
1757
writePunctuation(writer, SyntaxKind.DotDotDotToken);
1753
1758
}
@@ -1758,24 +1763,24 @@ module ts {
1758
1763
writePunctuation(writer, SyntaxKind.ColonToken);
1759
1764
writeSpace(writer);
1760
1765
1761
- buildTypeDisplay(getTypeOfSymbol(p), writer, enclosingDeclaration, flags, typeStack );
1766
+ buildTypeDisplay(getTypeOfSymbol(p), writer, enclosingDeclaration, flags, symbolStack );
1762
1767
}
1763
1768
1764
- function buildDisplayForTypeParametersAndDelimiters(typeParameters: TypeParameter[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack ?: Type []) {
1769
+ function buildDisplayForTypeParametersAndDelimiters(typeParameters: TypeParameter[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack ?: Symbol []) {
1765
1770
if (typeParameters && typeParameters.length) {
1766
1771
writePunctuation(writer, SyntaxKind.LessThanToken);
1767
1772
for (let i = 0; i < typeParameters.length; i++) {
1768
1773
if (i > 0) {
1769
1774
writePunctuation(writer, SyntaxKind.CommaToken);
1770
1775
writeSpace(writer);
1771
1776
}
1772
- buildTypeParameterDisplay(typeParameters[i], writer, enclosingDeclaration, flags, typeStack );
1777
+ buildTypeParameterDisplay(typeParameters[i], writer, enclosingDeclaration, flags, symbolStack );
1773
1778
}
1774
1779
writePunctuation(writer, SyntaxKind.GreaterThanToken);
1775
1780
}
1776
1781
}
1777
1782
1778
- function buildDisplayForTypeArgumentsAndDelimiters(typeParameters: TypeParameter[], mapper: TypeMapper, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack ?: Type []) {
1783
+ function buildDisplayForTypeArgumentsAndDelimiters(typeParameters: TypeParameter[], mapper: TypeMapper, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack ?: Symbol []) {
1779
1784
if (typeParameters && typeParameters.length) {
1780
1785
writePunctuation(writer, SyntaxKind.LessThanToken);
1781
1786
for (let i = 0; i < typeParameters.length; i++) {
@@ -1789,19 +1794,19 @@ module ts {
1789
1794
}
1790
1795
}
1791
1796
1792
- function buildDisplayForParametersAndDelimiters(parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack ?: Type []) {
1797
+ function buildDisplayForParametersAndDelimiters(parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack ?: Symbol []) {
1793
1798
writePunctuation(writer, SyntaxKind.OpenParenToken);
1794
1799
for (let i = 0; i < parameters.length; i++) {
1795
1800
if (i > 0) {
1796
1801
writePunctuation(writer, SyntaxKind.CommaToken);
1797
1802
writeSpace(writer);
1798
1803
}
1799
- buildParameterDisplay(parameters[i], writer, enclosingDeclaration, flags, typeStack );
1804
+ buildParameterDisplay(parameters[i], writer, enclosingDeclaration, flags, symbolStack );
1800
1805
}
1801
1806
writePunctuation(writer, SyntaxKind.CloseParenToken);
1802
1807
}
1803
1808
1804
- function buildReturnTypeDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack ?: Type []) {
1809
+ function buildReturnTypeDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack ?: Symbol []) {
1805
1810
if (flags & TypeFormatFlags.WriteArrowStyleSignature) {
1806
1811
writeSpace(writer);
1807
1812
writePunctuation(writer, SyntaxKind.EqualsGreaterThanToken);
@@ -1810,21 +1815,21 @@ module ts {
1810
1815
writePunctuation(writer, SyntaxKind.ColonToken);
1811
1816
}
1812
1817
writeSpace(writer);
1813
- buildTypeDisplay(getReturnTypeOfSignature(signature), writer, enclosingDeclaration, flags, typeStack );
1818
+ buildTypeDisplay(getReturnTypeOfSignature(signature), writer, enclosingDeclaration, flags, symbolStack );
1814
1819
}
1815
1820
1816
- function buildSignatureDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack ?: Type []) {
1821
+ function buildSignatureDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack ?: Symbol []) {
1817
1822
if (signature.target && (flags & TypeFormatFlags.WriteTypeArgumentsOfSignature)) {
1818
1823
// Instantiated signature, write type arguments instead
1819
1824
// This is achieved by passing in the mapper separately
1820
1825
buildDisplayForTypeArgumentsAndDelimiters(signature.target.typeParameters, signature.mapper, writer, enclosingDeclaration);
1821
1826
}
1822
1827
else {
1823
- buildDisplayForTypeParametersAndDelimiters(signature.typeParameters, writer, enclosingDeclaration, flags, typeStack );
1828
+ buildDisplayForTypeParametersAndDelimiters(signature.typeParameters, writer, enclosingDeclaration, flags, symbolStack );
1824
1829
}
1825
1830
1826
- buildDisplayForParametersAndDelimiters(signature.parameters, writer, enclosingDeclaration, flags, typeStack );
1827
- buildReturnTypeDisplay(signature, writer, enclosingDeclaration, flags, typeStack );
1831
+ buildDisplayForParametersAndDelimiters(signature.parameters, writer, enclosingDeclaration, flags, symbolStack );
1832
+ buildReturnTypeDisplay(signature, writer, enclosingDeclaration, flags, symbolStack );
1828
1833
}
1829
1834
1830
1835
return _displayBuilder || (_displayBuilder = {
@@ -3889,7 +3894,7 @@ module ts {
3889
3894
mapper.mappings = {};
3890
3895
}
3891
3896
// Instantiate the given type using the given mapper and cache the result
3892
- let result = <ResolvedType>createObjectType(TypeFlags.Anonymous, type.symbol);
3897
+ let result = <ResolvedType>createObjectType(TypeFlags.Anonymous | TypeFlags.Instantiated , type.symbol);
3893
3898
result.properties = instantiateList(getPropertiesOfObjectType(type), mapper, instantiateSymbol);
3894
3899
result.members = createSymbolTable(result.properties);
3895
3900
result.callSignatures = instantiateList(getSignaturesOfType(type, SignatureKind.Call), mapper, instantiateSignature);
@@ -4313,12 +4318,12 @@ module ts {
4313
4318
// Effectively, we will generate a false positive when two types are structurally equal to at least 10 levels, but unequal at
4314
4319
// some level beyond that.
4315
4320
function isDeeplyNestedGeneric(type: ObjectType, stack: ObjectType[]): boolean {
4316
- if (type.flags & TypeFlags.Reference && depth >= 10) {
4317
- let target = (<TypeReference> type).target ;
4321
+ if (type.flags & ( TypeFlags.Reference | TypeFlags.Instantiated) && depth >= 10) {
4322
+ let symbol = type.symbol ;
4318
4323
let count = 0;
4319
4324
for (let i = 0; i < depth; i++) {
4320
4325
let t = stack[i];
4321
- if (t.flags & TypeFlags.Reference && (<TypeReference>t).target === target ) {
4326
+ if (t.flags & ( TypeFlags.Reference | TypeFlags.Instantiated) && t.symbol === symbol ) {
4322
4327
count++;
4323
4328
if (count >= 10) return true;
4324
4329
}
0 commit comments