Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cache type for empty type literal #11934

Merged
merged 3 commits into from
Oct 29, 2016
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 22 additions & 9 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you marking this as SymbolFlags.Synthesized? We use that flag for union and intersection properties. Also, I would use the name "__type", that's what we do in the binder.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the idea was to use this flag for marking anything what was not present in the original source code.
will change

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

emptyTypeLiteralSymbol.members = createMap<Symbol>();
const cachedEmptyTypeLiteralType = createAnonymousType(emptyTypeLiteralSymbol, emptySymbols, emptyArray, emptyArray, undefined, undefined);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For consistency with the other precanned types and symbols I would just name this emptyTypeLiteralType.


const emptyGenericType = <GenericType><ObjectType>createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
emptyGenericType.instantiations = createMap<TypeReference>();

Expand Down Expand Up @@ -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 && (<TransientSymbol>prop).isPartial)) {
if (!(prop.flags & SymbolFlags.Synthesized && (<TransientSymbol>prop).isPartial)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would just leave this flag alone, it doesn't have anything to do with the fix here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

result.push(prop);
}
}
Expand Down Expand Up @@ -4560,7 +4565,7 @@ namespace ts {
}
propTypes.push(type);
}
const result = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | SymbolFlags.SyntheticProperty | commonFlags, name);
const result = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | SymbolFlags.Synthesized | commonFlags, name);
result.containingType = containingType;
result.hasNonUniformType = hasNonUniformType;
result.isPartial = isPartial;
Expand Down Expand Up @@ -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 && (<TransientSymbol>property).isPartial) ? property : undefined;
return property && !(property.flags & SymbolFlags.Synthesized && (<TransientSymbol>property).isPartial) ? property : undefined;
}

/**
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -6036,6 +6046,9 @@ namespace ts {
}

function isSymbolInScopeOfMappedTypeParameter(symbol: Symbol, mapper: TypeMapper) {
if (symbol.flags & SymbolFlags.Synthesized) {
return false;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change this to:

if (!(symbol.declarations && symbol.declarations.length)) {
    return false;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Expand Down Expand Up @@ -8216,7 +8229,7 @@ namespace ts {
function isDiscriminantProperty(type: Type, name: string) {
if (type && type.flags & TypeFlags.Union) {
const prop = getUnionOrIntersectionProperty(<UnionType>type, name);
if (prop && prop.flags & SymbolFlags.SyntheticProperty) {
if (prop && prop.flags & SymbolFlags.Synthesized) {
if ((<TransientSymbol>prop).isDiscriminantProperty === undefined) {
(<TransientSymbol>prop).isDiscriminantProperty = (<TransientSymbol>prop).hasNonUniformType && isLiteralType(getTypeOfSymbol(prop));
}
Expand Down Expand Up @@ -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 => {
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion src/services/findAllReferences.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
2 changes: 1 addition & 1 deletion src/services/symbolDisplay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down