-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Minor cleanup to symbolWalker #18549
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
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -994,11 +994,6 @@ namespace ts { | |
|
||
/** | ||
* Gets the owned, enumerable property keys of a map-like. | ||
* | ||
* NOTE: This is intended for use with MapLike<T> objects. For Map<T> objects, use | ||
* Object.keys instead as it offers better performance. | ||
* | ||
* @param map A map-like. | ||
*/ | ||
export function getOwnKeys<T>(map: MapLike<T>): string[] { | ||
const keys: string[] = []; | ||
|
@@ -1011,6 +1006,17 @@ namespace ts { | |
return keys; | ||
} | ||
|
||
export function getOwnValues<T>(sparseArray: T[]): T[] { | ||
const values: T[] = []; | ||
for (const key in sparseArray) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm sure I'm missing something, but how is this different from a for-of loop? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's also supposedly identical to |
||
if (hasOwnProperty.call(sparseArray, key)) { | ||
values.push(sparseArray[key]); | ||
} | ||
} | ||
|
||
return values; | ||
} | ||
|
||
/** Shims `Array.from`. */ | ||
export function arrayFrom<T, U>(iterator: Iterator<T>, map: (t: T) => U): U[]; | ||
export function arrayFrom<T>(iterator: Iterator<T>): T[]; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,21 +14,29 @@ namespace ts { | |
return getSymbolWalker; | ||
|
||
function getSymbolWalker(accept: (symbol: Symbol) => boolean = () => true): SymbolWalker { | ||
const visitedTypes = createMap<Type>(); // Key is id as string | ||
const visitedSymbols = createMap<Symbol>(); // Key is id as string | ||
const visitedTypes: Type[] = []; // Sparse array from id to type | ||
const visitedSymbols: Symbol[] = []; // Sparse array from id to symbol | ||
|
||
return { | ||
walkType: type => { | ||
visitedTypes.clear(); | ||
visitedSymbols.clear(); | ||
visitType(type); | ||
return { visitedTypes: arrayFrom(visitedTypes.values()), visitedSymbols: arrayFrom(visitedSymbols.values()) }; | ||
try { | ||
visitType(type); | ||
return { visitedTypes: getOwnValues(visitedTypes), visitedSymbols: getOwnValues(visitedSymbols) }; | ||
} | ||
finally { | ||
clear(visitedTypes); | ||
clear(visitedSymbols); | ||
} | ||
}, | ||
walkSymbol: symbol => { | ||
visitedTypes.clear(); | ||
visitedSymbols.clear(); | ||
visitSymbol(symbol); | ||
return { visitedTypes: arrayFrom(visitedTypes.values()), visitedSymbols: arrayFrom(visitedSymbols.values()) }; | ||
try { | ||
visitSymbol(symbol); | ||
return { visitedTypes: getOwnValues(visitedTypes), visitedSymbols: getOwnValues(visitedSymbols) }; | ||
} | ||
finally { | ||
clear(visitedTypes); | ||
clear(visitedSymbols); | ||
} | ||
}, | ||
}; | ||
|
||
|
@@ -37,11 +45,10 @@ namespace ts { | |
return; | ||
} | ||
|
||
const typeIdString = type.id.toString(); | ||
if (visitedTypes.has(typeIdString)) { | ||
if (visitedTypes[type.id]) { | ||
return; | ||
} | ||
visitedTypes.set(typeIdString, type); | ||
visitedTypes[type.id] = type; | ||
|
||
// Reuse visitSymbol to visit the type's symbol, | ||
// but be sure to bail on recuring into the type if accept declines the symbol. | ||
|
@@ -66,43 +73,22 @@ namespace ts { | |
} | ||
} | ||
if (type.flags & TypeFlags.TypeParameter) { | ||
visitTypeParameter(type as TypeParameter); | ||
visitType(getConstraintFromTypeParameter(type as TypeParameter)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I do not really like the inlining of these short functions - it removes the ability to grep for the symbol handling that case, and makes the block less uniform (and potentially makes the outer function more polymorphic). TBQH, if |
||
} | ||
if (type.flags & TypeFlags.UnionOrIntersection) { | ||
visitUnionOrIntersectionType(type as UnionOrIntersectionType); | ||
forEach((type as UnionOrIntersectionType).types, visitType); | ||
} | ||
if (type.flags & TypeFlags.Index) { | ||
visitIndexType(type as IndexType); | ||
visitType((type as IndexType).type); | ||
} | ||
if (type.flags & TypeFlags.IndexedAccess) { | ||
visitIndexedAccessType(type as IndexedAccessType); | ||
} | ||
} | ||
|
||
function visitTypeList(types: Type[]): void { | ||
if (!types) { | ||
return; | ||
} | ||
for (let i = 0; i < types.length; i++) { | ||
visitType(types[i]); | ||
} | ||
} | ||
|
||
function visitTypeReference(type: TypeReference): void { | ||
visitType(type.target); | ||
visitTypeList(type.typeArguments); | ||
} | ||
|
||
function visitTypeParameter(type: TypeParameter): void { | ||
visitType(getConstraintFromTypeParameter(type)); | ||
} | ||
|
||
function visitUnionOrIntersectionType(type: UnionOrIntersectionType): void { | ||
visitTypeList(type.types); | ||
} | ||
|
||
function visitIndexType(type: IndexType): void { | ||
visitType(type.type); | ||
forEach(type.typeArguments, visitType); | ||
} | ||
|
||
function visitIndexedAccessType(type: IndexedAccessType): void { | ||
|
@@ -122,7 +108,7 @@ namespace ts { | |
if (signature.typePredicate) { | ||
visitType(signature.typePredicate.type); | ||
} | ||
visitTypeList(signature.typeParameters); | ||
forEach(signature.typeParameters, visitType); | ||
|
||
for (const parameter of signature.parameters){ | ||
visitSymbol(parameter); | ||
|
@@ -133,8 +119,8 @@ namespace ts { | |
|
||
function visitInterfaceType(interfaceT: InterfaceType): void { | ||
visitObjectType(interfaceT); | ||
visitTypeList(interfaceT.typeParameters); | ||
visitTypeList(getBaseTypes(interfaceT)); | ||
forEach(interfaceT.typeParameters, visitType); | ||
forEach(getBaseTypes(interfaceT), visitType); | ||
visitType(interfaceT.thisType); | ||
} | ||
|
||
|
@@ -161,11 +147,11 @@ namespace ts { | |
if (!symbol) { | ||
return; | ||
} | ||
const symbolIdString = getSymbolId(symbol).toString(); | ||
if (visitedSymbols.has(symbolIdString)) { | ||
const symbolId = getSymbolId(symbol); | ||
if (visitedSymbols[symbolId]) { | ||
return; | ||
} | ||
visitedSymbols.set(symbolIdString, symbol); | ||
visitedSymbols[symbolId] = symbol; | ||
if (!accept(symbol)) { | ||
return true; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment outdated;
Map<T>
is now a real ES6 map, so we would use the.keys()
method.