diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 33aae7c8ea009..fe8e63676d7d5 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -2901,6 +2901,13 @@ namespace ts { return value; } + export function assertEachDefined>(value: A, message: string): A { + for (const v of value) { + assertDefined(v, message); + } + return value; + } + export function assertNever(member: never, message?: string, stackCrawlMark?: AnyFunction): never { return fail(message || `Illegal value: ${member}`, stackCrawlMark || assertNever); } diff --git a/src/services/completions.ts b/src/services/completions.ts index 2085e38292cf2..190f9bc9a3403 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -912,7 +912,7 @@ namespace ts.Completions { getTypeScriptMemberSymbols(); } else if (isRightOfOpenTag) { - const tagSymbols = typeChecker.getJsxIntrinsicTagNames(); + const tagSymbols = Debug.assertEachDefined(typeChecker.getJsxIntrinsicTagNames(), "getJsxIntrinsicTagNames() should all be defined"); if (tryGetGlobalSymbols()) { symbols = tagSymbols.concat(symbols.filter(s => !!(s.flags & (SymbolFlags.Value | SymbolFlags.Alias)))); } @@ -923,7 +923,7 @@ namespace ts.Completions { } else if (isStartingCloseTag) { const tagName = (contextToken.parent.parent).openingElement.tagName; - const tagSymbol = typeChecker.getSymbolAtLocation(tagName); + const tagSymbol = Debug.assertDefined(typeChecker.getSymbolAtLocation(tagName)); if (!typeChecker.isUnknownSymbol(tagSymbol)) { symbols = [tagSymbol]; @@ -971,7 +971,7 @@ namespace ts.Completions { if (symbol.flags & (SymbolFlags.Module | SymbolFlags.Enum)) { // Extract module or enum members - const exportedSymbols = typeChecker.getExportsOfModule(symbol); + const exportedSymbols = Debug.assertEachDefined(typeChecker.getExportsOfModule(symbol), "getExportsOfModule() should all be defined"); const isValidValueAccess = (symbol: Symbol) => typeChecker.isValidPropertyAccess((node.parent), symbol.name); const isValidTypeAccess = (symbol: Symbol) => symbolCanBeReferencedAtTypeLocation(symbol); const isValidAccess = isRhsOfImportDeclaration ? @@ -1111,7 +1111,7 @@ namespace ts.Completions { const symbolMeanings = SymbolFlags.Type | SymbolFlags.Value | SymbolFlags.Namespace | SymbolFlags.Alias; - symbols = typeChecker.getSymbolsInScope(scopeNode, symbolMeanings); + symbols = Debug.assertEachDefined(typeChecker.getSymbolsInScope(scopeNode, symbolMeanings), "getSymbolsInScope() should all be defined"); // Need to insert 'this.' before properties of `this` type, so only do that if `includeInsertTextCompletions` if (options.includeInsertTextCompletions && scopeNode.kind !== SyntaxKind.SourceFile) { @@ -1452,7 +1452,7 @@ namespace ts.Completions { if (typeMembers && typeMembers.length > 0) { // Add filtered items to the completion list - symbols = filterObjectMembersList(typeMembers, existingMembers); + symbols = filterObjectMembersList(typeMembers, Debug.assertDefined(existingMembers)); } return true; } @@ -1926,11 +1926,7 @@ namespace ts.Completions { existingImportsOrExports.set(name.escapedText, true); } - if (existingImportsOrExports.size === 0) { - return filter(exportsOfModule, e => e.escapedName !== InternalSymbolName.Default); - } - - return filter(exportsOfModule, e => e.escapedName !== InternalSymbolName.Default && !existingImportsOrExports.get(e.escapedName)); + return exportsOfModule.filter(e => e.escapedName !== InternalSymbolName.Default && !existingImportsOrExports.get(e.escapedName)); } /** @@ -1940,7 +1936,7 @@ namespace ts.Completions { * do not occur at the current position and have not otherwise been typed. */ function filterObjectMembersList(contextualMemberSymbols: Symbol[], existingMembers: ReadonlyArray): Symbol[] { - if (!existingMembers || existingMembers.length === 0) { + if (existingMembers.length === 0) { return contextualMemberSymbols; } @@ -1980,7 +1976,7 @@ namespace ts.Completions { existingMemberNames.set(existingName, true); } - return filter(contextualMemberSymbols, m => !existingMemberNames.get(m.escapedName)); + return contextualMemberSymbols.filter(m => !existingMemberNames.get(m.escapedName)); } /** @@ -2066,7 +2062,7 @@ namespace ts.Completions { } } - return filter(symbols, a => !seenNames.get(a.escapedName)); + return symbols.filter(a => !seenNames.get(a.escapedName)); } function isCurrentlyEditingNode(node: Node): boolean { @@ -2248,13 +2244,13 @@ namespace ts.Completions { */ function getPropertiesForCompletion(type: Type, checker: TypeChecker, isForAccess: boolean): Symbol[] { if (!(type.flags & TypeFlags.Union)) { - return type.getApparentProperties(); + return Debug.assertEachDefined(type.getApparentProperties(), "getApparentProperties() should all be defined"); } const { types } = type as UnionType; // If we're providing completions for an object literal, skip primitive, array-like, or callable types since those shouldn't be implemented by object literals. const filteredTypes = isForAccess ? types : types.filter(memberType => !(memberType.flags & TypeFlags.Primitive || checker.isArrayLikeType(memberType) || typeHasCallOrConstructSignatures(memberType, checker))); - return checker.getAllPossiblePropertiesOfTypes(filteredTypes); + return Debug.assertEachDefined(checker.getAllPossiblePropertiesOfTypes(filteredTypes), "getAllPossiblePropertiesOfTypes() should all be defined"); } }