Skip to content

Commit 2fede09

Browse files
author
Andy
authored
Add helper functions for adding an item to an array only if it's not already contained (microsoft#17833)
* Add helper functions for adding an item to an array only if it's not already contained * One more use of appendIfUnique
1 parent cd2ea9a commit 2fede09

File tree

3 files changed

+42
-57
lines changed

3 files changed

+42
-57
lines changed

src/compiler/checker.ts

Lines changed: 14 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1881,10 +1881,9 @@ namespace ts {
18811881
// The ES6 spec permits export * declarations in a module to circularly reference the module itself. For example,
18821882
// module 'a' can 'export * from "b"' and 'b' can 'export * from "a"' without error.
18831883
function visit(symbol: Symbol): SymbolTable {
1884-
if (!(symbol && symbol.flags & SymbolFlags.HasExports && !contains(visitedSymbols, symbol))) {
1884+
if (!(symbol && symbol.flags & SymbolFlags.HasExports && pushIfUnique(visitedSymbols, symbol))) {
18851885
return;
18861886
}
1887-
visitedSymbols.push(symbol);
18881887
const symbols = cloneMap(symbol.exports);
18891888
// All export * declarations are collected in an __export symbol by the binder
18901889
const exportStars = symbol.exports.get(InternalSymbolName.ExportStar);
@@ -2060,10 +2059,10 @@ namespace ts {
20602059
}
20612060

20622061
function getAccessibleSymbolChainFromSymbolTableWorker(symbols: SymbolTable, visitedSymbolTables: SymbolTable[]): Symbol[] {
2063-
if (contains<SymbolTable>(visitedSymbolTables, symbols)) {
2062+
if (!pushIfUnique(visitedSymbolTables, symbols)) {
20642063
return undefined;
20652064
}
2066-
visitedSymbolTables.push(symbols);
2065+
20672066
const result = trySymbolTable(symbols);
20682067
visitedSymbolTables.pop();
20692068
return result;
@@ -2276,14 +2275,7 @@ namespace ts {
22762275
// since we will do the emitting later in trackSymbol.
22772276
if (shouldComputeAliasToMakeVisible) {
22782277
getNodeLinks(declaration).isVisible = true;
2279-
if (aliasesToMakeVisible) {
2280-
if (!contains(aliasesToMakeVisible, anyImportSyntax)) {
2281-
aliasesToMakeVisible.push(anyImportSyntax);
2282-
}
2283-
}
2284-
else {
2285-
aliasesToMakeVisible = [anyImportSyntax];
2286-
}
2278+
aliasesToMakeVisible = appendIfUnique(aliasesToMakeVisible, anyImportSyntax);
22872279
}
22882280
return true;
22892281
}
@@ -3981,9 +3973,7 @@ namespace ts {
39813973
forEach(declarations, declaration => {
39823974
getNodeLinks(declaration).isVisible = true;
39833975
const resultNode = getAnyImportSyntax(declaration) || declaration;
3984-
if (!contains(result, resultNode)) {
3985-
result.push(resultNode);
3986-
}
3976+
pushIfUnique(result, resultNode);
39873977

39883978
if (isInternalModuleImportEqualsDeclaration(declaration)) {
39893979
// Add the referenced top container visible
@@ -4793,12 +4783,7 @@ namespace ts {
47934783
function appendTypeParameters(typeParameters: TypeParameter[], declarations: ReadonlyArray<TypeParameterDeclaration>): TypeParameter[] {
47944784
for (const declaration of declarations) {
47954785
const tp = getDeclaredTypeOfTypeParameter(getSymbolOfNode(declaration));
4796-
if (!typeParameters) {
4797-
typeParameters = [tp];
4798-
}
4799-
else if (!contains(typeParameters, tp)) {
4800-
typeParameters.push(tp);
4801-
}
4786+
typeParameters = appendIfUnique(typeParameters, tp);
48024787
}
48034788
return typeParameters;
48044789
}
@@ -5521,9 +5506,7 @@ namespace ts {
55215506
if (!match) {
55225507
return undefined;
55235508
}
5524-
if (!contains(result, match)) {
5525-
(result || (result = [])).push(match);
5526-
}
5509+
result = appendIfUnique(result, match);
55275510
}
55285511
return result;
55295512
}
@@ -6073,12 +6056,7 @@ namespace ts {
60736056
const modifiers = prop ? getDeclarationModifierFlagsFromSymbol(prop) : 0;
60746057
if (prop && !(modifiers & excludeModifiers)) {
60756058
commonFlags &= prop.flags;
6076-
if (!props) {
6077-
props = [prop];
6078-
}
6079-
else if (!contains(props, prop)) {
6080-
props.push(prop);
6081-
}
6059+
props = appendIfUnique(props, prop);
60826060
checkFlags |= (isReadonlySymbol(prop) ? CheckFlags.Readonly : 0) |
60836061
(!(modifiers & ModifierFlags.NonPublicAccessibilityModifier) ? CheckFlags.ContainsPublic : 0) |
60846062
(modifiers & ModifierFlags.Protected ? CheckFlags.ContainsProtected : 0) |
@@ -6237,12 +6215,7 @@ namespace ts {
62376215
let result: TypeParameter[];
62386216
forEach(getEffectiveTypeParameterDeclarations(declaration), node => {
62396217
const tp = getDeclaredTypeOfTypeParameter(node.symbol);
6240-
if (!contains(result, tp)) {
6241-
if (!result) {
6242-
result = [];
6243-
}
6244-
result.push(tp);
6245-
}
6218+
result = appendIfUnique(result, tp);
62466219
});
62476220
return result;
62486221
}
@@ -11715,9 +11688,7 @@ namespace ts {
1171511688
if (type === declaredType && declaredType === initialType) {
1171611689
return type;
1171711690
}
11718-
if (!contains(antecedentTypes, type)) {
11719-
antecedentTypes.push(type);
11720-
}
11691+
pushIfUnique(antecedentTypes, type);
1172111692
// If an antecedent type is not a subset of the declared type, we need to perform
1172211693
// subtype reduction. This happens when a "foreign" type is injected into the control
1172311694
// flow using the instanceof operator or a user defined type predicate.
@@ -11783,9 +11754,7 @@ namespace ts {
1178311754
if (cached) {
1178411755
return cached;
1178511756
}
11786-
if (!contains(antecedentTypes, type)) {
11787-
antecedentTypes.push(type);
11788-
}
11757+
pushIfUnique(antecedentTypes, type);
1178911758
// If an antecedent type is not a subset of the declared type, we need to perform
1179011759
// subtype reduction. This happens when a "foreign" type is injected into the control
1179111760
// flow using the instanceof operator or a user defined type predicate.
@@ -16826,9 +16795,7 @@ namespace ts {
1682616795
? Diagnostics.Type_of_iterated_elements_of_a_yield_Asterisk_operand_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member
1682716796
: Diagnostics.Type_of_yield_operand_in_an_async_generator_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member);
1682816797
}
16829-
if (!contains(aggregatedTypes, type)) {
16830-
aggregatedTypes.push(type);
16831-
}
16798+
pushIfUnique(aggregatedTypes, type);
1683216799
}
1683316800
});
1683416801

@@ -16880,9 +16847,7 @@ namespace ts {
1688016847
if (type.flags & TypeFlags.Never) {
1688116848
hasReturnOfTypeNever = true;
1688216849
}
16883-
else if (!contains(aggregatedTypes, type)) {
16884-
aggregatedTypes.push(type);
16885-
}
16850+
pushIfUnique(aggregatedTypes, type);
1688616851
}
1688716852
else {
1688816853
hasReturnWithNoExpression = true;
@@ -16893,9 +16858,7 @@ namespace ts {
1689316858
return undefined;
1689416859
}
1689516860
if (strictNullChecks && aggregatedTypes.length && hasReturnWithNoExpression) {
16896-
if (!contains(aggregatedTypes, undefinedType)) {
16897-
aggregatedTypes.push(undefinedType);
16898-
}
16861+
pushIfUnique(aggregatedTypes, undefinedType);
1689916862
}
1690016863
return aggregatedTypes;
1690116864
}

src/compiler/core.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,32 @@ namespace ts {
771771
return to;
772772
}
773773

774+
/**
775+
* @return Whether the value was added.
776+
*/
777+
export function pushIfUnique<T>(array: T[], toAdd: T): boolean {
778+
if (contains(array, toAdd)) {
779+
return false;
780+
}
781+
else {
782+
array.push(toAdd);
783+
return true;
784+
}
785+
}
786+
787+
/**
788+
* Unlike `pushIfUnique`, this can take `undefined` as an input, and returns a new array.
789+
*/
790+
export function appendIfUnique<T>(array: T[] | undefined, toAdd: T): T[] {
791+
if (array) {
792+
pushIfUnique(array, toAdd);
793+
return array;
794+
}
795+
else {
796+
return [toAdd];
797+
}
798+
}
799+
774800
/**
775801
* Stable sort of an array. Elements equal to each other maintain their relative position in the array.
776802
*/

src/compiler/factory.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2636,9 +2636,7 @@ namespace ts {
26362636
if (some(helpers)) {
26372637
const emitNode = getOrCreateEmitNode(node);
26382638
for (const helper of helpers) {
2639-
if (!contains(emitNode.helpers, helper)) {
2640-
emitNode.helpers = append(emitNode.helpers, helper);
2641-
}
2639+
emitNode.helpers = appendIfUnique(emitNode.helpers, helper);
26422640
}
26432641
}
26442642
return node;
@@ -2680,9 +2678,7 @@ namespace ts {
26802678
const helper = sourceEmitHelpers[i];
26812679
if (predicate(helper)) {
26822680
helpersRemoved++;
2683-
if (!contains(targetEmitNode.helpers, helper)) {
2684-
targetEmitNode.helpers = append(targetEmitNode.helpers, helper);
2685-
}
2681+
targetEmitNode.helpers = appendIfUnique(targetEmitNode.helpers, helper);
26862682
}
26872683
else if (helpersRemoved > 0) {
26882684
sourceEmitHelpers[i - helpersRemoved] = helper;

0 commit comments

Comments
 (0)