From 58b549c6d508584a416c71c6ffe0bf09bc9fca3f Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Fri, 28 Oct 2016 23:18:04 -0700 Subject: [PATCH 1/3] cache type for empty type literal --- src/compiler/checker.ts | 31 ++++++++++++++++++++++--------- src/compiler/types.ts | 2 +- src/services/findAllReferences.ts | 2 +- src/services/symbolDisplay.ts | 2 +- 4 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9c4ed1128dcb4..dd94b7c093e61 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -138,6 +138,11 @@ namespace ts { const silentNeverType = createIntrinsicType(TypeFlags.Never, "never"); const emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); + + const emptyTypeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral | SymbolFlags.Transient | SymbolFlags.Synthesized, "empty"); + emptyTypeLiteralSymbol.members = createMap(); + const cachedEmptyTypeLiteralType = createAnonymousType(emptyTypeLiteralSymbol, emptySymbols, emptyArray, emptyArray, undefined, undefined); + const emptyGenericType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); emptyGenericType.instantiations = createMap(); @@ -4456,7 +4461,7 @@ namespace ts { for (const key in props) { const prop = props[key]; // We need to filter out partial properties in union types - if (!(prop.flags & SymbolFlags.SyntheticProperty && (prop).isPartial)) { + if (!(prop.flags & SymbolFlags.Synthesized && (prop).isPartial)) { result.push(prop); } } @@ -4560,7 +4565,7 @@ namespace ts { } propTypes.push(type); } - const result = createSymbol(SymbolFlags.Property | SymbolFlags.Transient | SymbolFlags.SyntheticProperty | commonFlags, name); + const result = createSymbol(SymbolFlags.Property | SymbolFlags.Transient | SymbolFlags.Synthesized | commonFlags, name); result.containingType = containingType; result.hasNonUniformType = hasNonUniformType; result.isPartial = isPartial; @@ -4590,7 +4595,7 @@ namespace ts { function getPropertyOfUnionOrIntersectionType(type: UnionOrIntersectionType, name: string): Symbol { const property = getUnionOrIntersectionProperty(type, name); // We need to filter out partial properties in union types - return property && !(property.flags & SymbolFlags.SyntheticProperty && (property).isPartial) ? property : undefined; + return property && !(property.flags & SymbolFlags.Synthesized && (property).isPartial) ? property : undefined; } /** @@ -5696,10 +5701,15 @@ namespace ts { const links = getNodeLinks(node); if (!links.resolvedType) { // Deferred resolution of members is handled by resolveObjectTypeMembers - const type = createObjectType(ObjectFlags.Anonymous, node.symbol); - type.aliasSymbol = aliasSymbol; - type.aliasTypeArguments = aliasTypeArguments; - links.resolvedType = type; + if (isEmpty(node.symbol.members) && !aliasSymbol && !aliasTypeArguments) { + links.resolvedType = cachedEmptyTypeLiteralType; + } + else { + const type = createObjectType(ObjectFlags.Anonymous, node.symbol); + type.aliasSymbol = aliasSymbol; + type.aliasTypeArguments = aliasTypeArguments; + links.resolvedType = type; + } } return links.resolvedType; } @@ -6036,6 +6046,9 @@ namespace ts { } function isSymbolInScopeOfMappedTypeParameter(symbol: Symbol, mapper: TypeMapper) { + if (symbol.flags & SymbolFlags.Synthesized) { + return false; + } const mappedTypes = mapper.mappedTypes; // Starting with the parent of the symbol's declaration, check if the mapper maps any of // the type parameters introduced by enclosing declarations. We just pick the first @@ -8216,7 +8229,7 @@ namespace ts { function isDiscriminantProperty(type: Type, name: string) { if (type && type.flags & TypeFlags.Union) { const prop = getUnionOrIntersectionProperty(type, name); - if (prop && prop.flags & SymbolFlags.SyntheticProperty) { + if (prop && prop.flags & SymbolFlags.Synthesized) { if ((prop).isDiscriminantProperty === undefined) { (prop).isDiscriminantProperty = (prop).hasNonUniformType && isLiteralType(getTypeOfSymbol(prop)); } @@ -19011,7 +19024,7 @@ namespace ts { } function getRootSymbols(symbol: Symbol): Symbol[] { - if (symbol.flags & SymbolFlags.SyntheticProperty) { + if (symbol.flags & SymbolFlags.Synthesized) { const symbols: Symbol[] = []; const name = symbol.name; forEach(getSymbolLinks(symbol).containingType.types, t => { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 3bbd78f3f686b..8c20043846d98 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2490,7 +2490,7 @@ namespace ts { Merged = 0x02000000, // Merged symbol (created during program binding) Transient = 0x04000000, // Transient symbol (created during type check) Prototype = 0x08000000, // Prototype property (no source representation) - SyntheticProperty = 0x10000000, // Property in union or intersection type + Synthesized = 0x10000000, // Property in union or intersection type Optional = 0x20000000, // Optional property ExportStar = 0x40000000, // Export * declaration diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 9765780ee7c8f..5b73ea915586a 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -228,7 +228,7 @@ namespace ts.FindAllReferences { // if this symbol is visible from its parent container, e.g. exported, then bail out // if symbol correspond to the union property - bail out - if (symbol.parent || (symbol.flags & SymbolFlags.SyntheticProperty)) { + if (symbol.parent || (symbol.flags & SymbolFlags.Synthesized)) { return undefined; } diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts index 516b5d7fbc5b1..e294777b6f3ec 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -51,7 +51,7 @@ namespace ts.SymbolDisplay { if (flags & SymbolFlags.Constructor) return ScriptElementKind.constructorImplementationElement; if (flags & SymbolFlags.Property) { - if (flags & SymbolFlags.SyntheticProperty) { + if (flags & SymbolFlags.Synthesized) { // If union property is result of union of non method (property/accessors/variables), it is labeled as property const unionPropertyKind = forEach(typeChecker.getRootSymbols(symbol), rootSymbol => { const rootSymbolFlags = rootSymbol.getFlags(); From bc2771ff9c409a03d2ce145f232062004167a24e Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Sat, 29 Oct 2016 08:24:27 -0700 Subject: [PATCH 2/3] addressed PR feedback --- src/compiler/checker.ts | 14 +++++++------- src/compiler/types.ts | 2 +- src/services/findAllReferences.ts | 2 +- src/services/symbolDisplay.ts | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index dd94b7c093e61..3a08ede9cc7fc 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -139,7 +139,7 @@ namespace ts { const emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); - const emptyTypeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral | SymbolFlags.Transient | SymbolFlags.Synthesized, "empty"); + const emptyTypeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral | SymbolFlags.Transient, "__type"); emptyTypeLiteralSymbol.members = createMap(); const cachedEmptyTypeLiteralType = createAnonymousType(emptyTypeLiteralSymbol, emptySymbols, emptyArray, emptyArray, undefined, undefined); @@ -4461,7 +4461,7 @@ namespace ts { for (const key in props) { const prop = props[key]; // We need to filter out partial properties in union types - if (!(prop.flags & SymbolFlags.Synthesized && (prop).isPartial)) { + if (!(prop.flags & SymbolFlags.SyntheticProperty && (prop).isPartial)) { result.push(prop); } } @@ -4565,7 +4565,7 @@ namespace ts { } propTypes.push(type); } - const result = createSymbol(SymbolFlags.Property | SymbolFlags.Transient | SymbolFlags.Synthesized | commonFlags, name); + const result = createSymbol(SymbolFlags.Property | SymbolFlags.Transient | SymbolFlags.SyntheticProperty | commonFlags, name); result.containingType = containingType; result.hasNonUniformType = hasNonUniformType; result.isPartial = isPartial; @@ -4595,7 +4595,7 @@ namespace ts { function getPropertyOfUnionOrIntersectionType(type: UnionOrIntersectionType, name: string): Symbol { const property = getUnionOrIntersectionProperty(type, name); // We need to filter out partial properties in union types - return property && !(property.flags & SymbolFlags.Synthesized && (property).isPartial) ? property : undefined; + return property && !(property.flags & SymbolFlags.SyntheticProperty && (property).isPartial) ? property : undefined; } /** @@ -6046,7 +6046,7 @@ namespace ts { } function isSymbolInScopeOfMappedTypeParameter(symbol: Symbol, mapper: TypeMapper) { - if (symbol.flags & SymbolFlags.Synthesized) { + if (!(symbol.declarations && symbol.declarations.length)) { return false; } const mappedTypes = mapper.mappedTypes; @@ -8229,7 +8229,7 @@ namespace ts { function isDiscriminantProperty(type: Type, name: string) { if (type && type.flags & TypeFlags.Union) { const prop = getUnionOrIntersectionProperty(type, name); - if (prop && prop.flags & SymbolFlags.Synthesized) { + if (prop && prop.flags & SymbolFlags.SyntheticProperty) { if ((prop).isDiscriminantProperty === undefined) { (prop).isDiscriminantProperty = (prop).hasNonUniformType && isLiteralType(getTypeOfSymbol(prop)); } @@ -19024,7 +19024,7 @@ namespace ts { } function getRootSymbols(symbol: Symbol): Symbol[] { - if (symbol.flags & SymbolFlags.Synthesized) { + if (symbol.flags & SymbolFlags.SyntheticProperty) { const symbols: Symbol[] = []; const name = symbol.name; forEach(getSymbolLinks(symbol).containingType.types, t => { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 8c20043846d98..3bbd78f3f686b 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2490,7 +2490,7 @@ namespace ts { Merged = 0x02000000, // Merged symbol (created during program binding) Transient = 0x04000000, // Transient symbol (created during type check) Prototype = 0x08000000, // Prototype property (no source representation) - Synthesized = 0x10000000, // Property in union or intersection type + SyntheticProperty = 0x10000000, // Property in union or intersection type Optional = 0x20000000, // Optional property ExportStar = 0x40000000, // Export * declaration diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 5b73ea915586a..9765780ee7c8f 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -228,7 +228,7 @@ namespace ts.FindAllReferences { // if this symbol is visible from its parent container, e.g. exported, then bail out // if symbol correspond to the union property - bail out - if (symbol.parent || (symbol.flags & SymbolFlags.Synthesized)) { + if (symbol.parent || (symbol.flags & SymbolFlags.SyntheticProperty)) { return undefined; } diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts index e294777b6f3ec..516b5d7fbc5b1 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -51,7 +51,7 @@ namespace ts.SymbolDisplay { if (flags & SymbolFlags.Constructor) return ScriptElementKind.constructorImplementationElement; if (flags & SymbolFlags.Property) { - if (flags & SymbolFlags.Synthesized) { + if (flags & SymbolFlags.SyntheticProperty) { // If union property is result of union of non method (property/accessors/variables), it is labeled as property const unionPropertyKind = forEach(typeChecker.getRootSymbols(symbol), rootSymbol => { const rootSymbolFlags = rootSymbol.getFlags(); From 51c59c3cf4c6a62c6221d15e3c6f3e34db2a77f9 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Sat, 29 Oct 2016 15:42:08 -0700 Subject: [PATCH 3/3] renamed cachedEmptyLiteralType to emptyLiteralType --- src/compiler/checker.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 3a08ede9cc7fc..704018627b24e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -141,7 +141,7 @@ namespace ts { const emptyTypeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral | SymbolFlags.Transient, "__type"); emptyTypeLiteralSymbol.members = createMap(); - const cachedEmptyTypeLiteralType = createAnonymousType(emptyTypeLiteralSymbol, emptySymbols, emptyArray, emptyArray, undefined, undefined); + const emptyTypeLiteralType = createAnonymousType(emptyTypeLiteralSymbol, emptySymbols, emptyArray, emptyArray, undefined, undefined); const emptyGenericType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); emptyGenericType.instantiations = createMap(); @@ -5702,7 +5702,7 @@ namespace ts { if (!links.resolvedType) { // Deferred resolution of members is handled by resolveObjectTypeMembers if (isEmpty(node.symbol.members) && !aliasSymbol && !aliasTypeArguments) { - links.resolvedType = cachedEmptyTypeLiteralType; + links.resolvedType = emptyTypeLiteralType; } else { const type = createObjectType(ObjectFlags.Anonymous, node.symbol);