diff --git a/Gulpfile.js b/Gulpfile.js index b6f1f0fcb0235..af7461ba7e61a 100644 --- a/Gulpfile.js +++ b/Gulpfile.js @@ -260,6 +260,7 @@ function getCompilerSettings(base, useBuiltCompiler) { for (const key in base) { copy[key] = base[key]; } + copy.strictNullChecks = true; if (!useDebugMode) { if (copy.removeComments === undefined) copy.removeComments = true; } diff --git a/Jakefile.js b/Jakefile.js index 5d85a4e74f3d7..2e18fe1fa71b3 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -251,7 +251,7 @@ function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, opts else { options += " --lib es5"; } - options += " --noUnusedLocals --noUnusedParameters"; + options += " --noUnusedLocals --noUnusedParameters --strictNullChecks"; var cmd = host + " " + compilerPath + " " + options + " "; cmd = cmd + sources.join(" "); diff --git a/scripts/buildProtocol.ts b/scripts/buildProtocol.ts index 3ea7d703cd374..65bb0f01083e2 100644 --- a/scripts/buildProtocol.ts +++ b/scripts/buildProtocol.ts @@ -8,7 +8,7 @@ function endsWith(s: string, suffix: string) { } function isStringEnum(declaration: ts.EnumDeclaration) { - return declaration.members.length && declaration.members.every(m => m.initializer && m.initializer.kind === ts.SyntaxKind.StringLiteral); + return declaration.members.length && declaration.members.every(m => !!m.initializer && m.initializer.kind === ts.SyntaxKind.StringLiteral); } class DeclarationsWalker { @@ -30,7 +30,7 @@ class DeclarationsWalker { text += "\ndeclare namespace ts {\n"; text += " // these types are empty stubs for types from services and should not be used directly\n" for (const type of walker.removedTypes) { - text += ` export type ${type.symbol.name} = never;\n`; + text += ` export type ${type.symbol!.name} = never;\n`; } text += "}" } @@ -130,7 +130,7 @@ function writeProtocolFile(outputFile: string, protocolTs: string, typeScriptSer function getInitialDtsFileForProtocol() { const program = ts.createProgram([protocolTs, typeScriptServicesDts], options); - let protocolDts: string; + let protocolDts: string | undefined; program.emit(program.getSourceFile(protocolTs), (file, content) => { if (endsWith(file, ".d.ts")) { protocolDts = content; @@ -162,7 +162,7 @@ function writeProtocolFile(outputFile: string, protocolTs: string, typeScriptSer let protocolDts = getInitialDtsFileForProtocol(); const program = getProgramWithProtocolText(protocolDts, /*includeTypeScriptServices*/ true); - const protocolFile = program.getSourceFile("protocol.d.ts"); + const protocolFile = program.getSourceFile("protocol.d.ts")!; const extraDeclarations = DeclarationsWalker.getExtraDeclarations(program.getTypeChecker(), protocolFile); if (extraDeclarations) { protocolDts += extraDeclarations; diff --git a/scripts/processDiagnosticMessages.ts b/scripts/processDiagnosticMessages.ts index 848a60cfb4fa5..6318b131309ab 100644 --- a/scripts/processDiagnosticMessages.ts +++ b/scripts/processDiagnosticMessages.ts @@ -22,7 +22,7 @@ function main(): void { } const inputFilePath = sys.args[0].replace(/\\/g, "/"); - const inputStr = sys.readFile(inputFilePath); + const inputStr = sys.readFile(inputFilePath)!; const diagnosticMessagesJson: { [key: string]: DiagnosticDetails } = JSON.parse(inputStr); diff --git a/scripts/tslint/rules/noInOperatorRule.ts b/scripts/tslint/rules/noInOperatorRule.ts index 95f052ccaa62e..448cf90cacdc8 100644 --- a/scripts/tslint/rules/noInOperatorRule.ts +++ b/scripts/tslint/rules/noInOperatorRule.ts @@ -12,7 +12,7 @@ export class Rule extends Lint.Rules.AbstractRule { function walk(ctx: Lint.WalkContext): void { ts.forEachChild(ctx.sourceFile, recur); function recur(node: ts.Node): void { - if (node.kind === ts.SyntaxKind.InKeyword && node.parent.kind === ts.SyntaxKind.BinaryExpression) { + if (node.kind === ts.SyntaxKind.InKeyword && node.parent!.kind === ts.SyntaxKind.BinaryExpression) { ctx.addFailureAtNode(node, Rule.FAILURE_STRING); } } diff --git a/scripts/tslint/rules/noUnnecessaryTypeAssertion2Rule.ts b/scripts/tslint/rules/noUnnecessaryTypeAssertion2Rule.ts deleted file mode 100644 index bcfb91b739fb4..0000000000000 --- a/scripts/tslint/rules/noUnnecessaryTypeAssertion2Rule.ts +++ /dev/null @@ -1,98 +0,0 @@ -/** - * @license - * Copyright 2016 Palantir Technologies, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import * as ts from "typescript"; -import * as Lint from "tslint"; - -export class Rule extends Lint.Rules.TypedRule { - /* tslint:disable:object-literal-sort-keys */ - public static metadata: Lint.IRuleMetadata = { - ruleName: "no-unnecessary-type-assertion", - description: "Warns if a type assertion does not change the type of an expression.", - options: { - type: "list", - listType: { - type: "array", - items: { type: "string" }, - }, - }, - optionsDescription: "A list of whitelisted assertion types to ignore", - type: "typescript", - hasFix: true, - typescriptOnly: true, - requiresTypeInfo: true, - }; - /* tslint:enable:object-literal-sort-keys */ - - public static FAILURE_STRING = "This assertion is unnecessary since it does not change the type of the expression."; - - public applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): Lint.RuleFailure[] { - return this.applyWithWalker(new Walker(sourceFile, this.ruleName, this.ruleArguments, program.getTypeChecker())); - } -} - -class Walker extends Lint.AbstractWalker { - constructor(sourceFile: ts.SourceFile, ruleName: string, options: string[], private readonly checker: ts.TypeChecker) { - super(sourceFile, ruleName, options); - } - - public walk(sourceFile: ts.SourceFile) { - const cb = (node: ts.Node): void => { - switch (node.kind) { - case ts.SyntaxKind.TypeAssertionExpression: - case ts.SyntaxKind.AsExpression: - this.verifyCast(node as ts.TypeAssertion | ts.AsExpression); - } - - return ts.forEachChild(node, cb); - }; - - return ts.forEachChild(sourceFile, cb); - } - - private verifyCast(node: ts.TypeAssertion | ts.NonNullExpression | ts.AsExpression) { - if (ts.isAssertionExpression(node) && this.options.indexOf(node.type.getText(this.sourceFile)) !== -1) { - return; - } - const castType = this.checker.getTypeAtLocation(node); - if (castType === undefined) { - return; - } - - if (node.kind !== ts.SyntaxKind.NonNullExpression && - (castType.flags & ts.TypeFlags.Literal || - castType.flags & ts.TypeFlags.Object && - (castType as ts.ObjectType).objectFlags & ts.ObjectFlags.Tuple) || - // Sometimes tuple types don't have ObjectFlags.Tuple set, like when - // they're being matched against an inferred type. So, in addition, - // check if any properties are numbers, which implies that this is - // likely a tuple type. - (castType.getProperties().some((symbol) => !isNaN(Number(symbol.name))))) { - - // It's not always safe to remove a cast to a literal type or tuple - // type, as those types are sometimes widened without the cast. - return; - } - - const uncastType = this.checker.getTypeAtLocation(node.expression); - if (uncastType === castType) { - this.addFailureAtNode(node, Rule.FAILURE_STRING, node.kind === ts.SyntaxKind.TypeAssertionExpression - ? Lint.Replacement.deleteFromTo(node.getStart(), node.expression.getStart()) - : Lint.Replacement.deleteFromTo(node.expression.getEnd(), node.getEnd())); - } - } -} diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 36fbbeb2ec74b..7dd4ed1a39a2b 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -123,13 +123,13 @@ namespace ts { // state used by control flow analysis let currentFlow: FlowNode; - let currentBreakTarget: FlowLabel; - let currentContinueTarget: FlowLabel; - let currentReturnTarget: FlowLabel; - let currentTrueTarget: FlowLabel; - let currentFalseTarget: FlowLabel; - let preSwitchCaseFlow: FlowNode; - let activeLabels: ActiveLabel[]; + let currentBreakTarget: FlowLabel | undefined; + let currentContinueTarget: FlowLabel | undefined; + let currentReturnTarget: FlowLabel | undefined; + let currentTrueTarget: FlowLabel | undefined; + let currentFalseTarget: FlowLabel | undefined; + let preSwitchCaseFlow: FlowNode | undefined; + let activeLabels: ActiveLabel[] | undefined; let hasExplicitReturn: boolean; // state used for emit helpers @@ -180,23 +180,23 @@ namespace ts { delayedBindJSDocTypedefTag(); } - file = undefined; - options = undefined; - languageVersion = undefined; - parent = undefined; - container = undefined; - thisParentContainer = undefined; - blockScopeContainer = undefined; - lastContainer = undefined; - delayedTypeAliases = undefined; + file = undefined!; + options = undefined!; + languageVersion = undefined!; + parent = undefined!; + container = undefined!; + thisParentContainer = undefined!; + blockScopeContainer = undefined!; + lastContainer = undefined!; + delayedTypeAliases = undefined!; seenThisKeyword = false; - currentFlow = undefined; + currentFlow = undefined!; currentBreakTarget = undefined; currentContinueTarget = undefined; currentReturnTarget = undefined; currentTrueTarget = undefined; currentFalseTarget = undefined; - activeLabels = undefined; + activeLabels = undefined!; hasExplicitReturn = false; emitFlags = NodeFlags.None; subtreeTransformFlags = TransformFlags.None; @@ -234,7 +234,7 @@ namespace ts { } if (symbolFlags & SymbolFlags.Value) { - const valueDeclaration = symbol.valueDeclaration; + const { valueDeclaration } = symbol; if (!valueDeclaration || (valueDeclaration.kind !== node.kind && valueDeclaration.kind === SyntaxKind.ModuleDeclaration)) { // other kinds of value declarations take precedence over modules @@ -245,7 +245,7 @@ namespace ts { // Should not be called on a declaration with a computed property name, // unless it is a well known Symbol. - function getDeclarationName(node: Declaration): __String { + function getDeclarationName(node: Declaration): __String | undefined { if (node.kind === SyntaxKind.ExportAssignment) { return (node).isExportEquals ? InternalSymbolName.ExportEquals : InternalSymbolName.Default; } @@ -306,7 +306,7 @@ namespace ts { } function getDisplayName(node: Declaration): string { - return isNamedDeclaration(node) ? declarationNameToString(node.name) : unescapeLeadingUnderscores(getDeclarationName(node)); + return isNamedDeclaration(node) ? declarationNameToString(node.name) : unescapeLeadingUnderscores(getDeclarationName(node)!); // TODO: GH#18217 } /** @@ -317,7 +317,7 @@ namespace ts { * @param includes - The SymbolFlags that node has in addition to its declaration type (eg: export, ambient, etc.) * @param excludes - The flags which node cannot be declared alongside in a symbol table. Used to report forbidden declarations. */ - function declareSymbol(symbolTable: SymbolTable, parent: Symbol, node: Declaration, includes: SymbolFlags, excludes: SymbolFlags, isReplaceableByMethod?: boolean): Symbol { + function declareSymbol(symbolTable: SymbolTable, parent: Symbol | undefined, node: Declaration, includes: SymbolFlags, excludes: SymbolFlags, isReplaceableByMethod?: boolean): Symbol { Debug.assert(!hasDynamicName(node)); const isDefaultExport = hasModifier(node, ModifierFlags.Default); @@ -325,7 +325,7 @@ namespace ts { // The exported symbol for an export default function/class node is always named "default" const name = isDefaultExport && parent ? InternalSymbolName.Default : getDeclarationName(node); - let symbol: Symbol; + let symbol: Symbol | undefined; if (name === undefined) { symbol = createSymbol(SymbolFlags.None, InternalSymbolName.Missing); } @@ -432,10 +432,10 @@ namespace ts { const hasExportModifier = getCombinedModifierFlags(node) & ModifierFlags.Export; if (symbolFlags & SymbolFlags.Alias) { if (node.kind === SyntaxKind.ExportSpecifier || (node.kind === SyntaxKind.ImportEqualsDeclaration && hasExportModifier)) { - return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); + return declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes); } else { - return declareSymbol(container.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes); + return declareSymbol(container.locals!, /*parent*/ undefined, node, symbolFlags, symbolExcludes); } } else { @@ -457,16 +457,16 @@ namespace ts { if (isJSDocTypeAlias(node)) Debug.assert(isInJavaScriptFile(node)); // We shouldn't add symbols for JSDoc nodes if not in a JS file. if ((!isAmbientModule(node) && (hasExportModifier || container.flags & NodeFlags.ExportContext)) || isJSDocTypeAlias(node)) { if (hasModifier(node, ModifierFlags.Default) && !getDeclarationName(node)) { - return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); // No local symbol for an unnamed default! + return declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes); // No local symbol for an unnamed default! } const exportKind = symbolFlags & SymbolFlags.Value ? SymbolFlags.ExportValue : 0; - const local = declareSymbol(container.locals, /*parent*/ undefined, node, exportKind, symbolExcludes); - local.exportSymbol = declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); + const local = declareSymbol(container.locals!, /*parent*/ undefined, node, exportKind, symbolExcludes); + local.exportSymbol = declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes); node.localSymbol = local; return local; } else { - return declareSymbol(container.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes); + return declareSymbol(container.locals!, /*parent*/ undefined, node, symbolFlags, symbolExcludes); } } } @@ -547,6 +547,7 @@ namespace ts { if (node.kind === SyntaxKind.SourceFile) { node.flags |= emitFlags; } + if (currentReturnTarget) { addAntecedent(currentReturnTarget, currentFlow); currentFlow = finishFlowLabel(currentReturnTarget); @@ -595,12 +596,12 @@ namespace ts { } } - function bindEachFunctionsFirst(nodes: NodeArray) { + function bindEachFunctionsFirst(nodes: NodeArray | undefined): void { bindEach(nodes, n => n.kind === SyntaxKind.FunctionDeclaration ? bind(n) : undefined); bindEach(nodes, n => n.kind !== SyntaxKind.FunctionDeclaration ? bind(n) : undefined); } - function bindEach(nodes: NodeArray, bindFunction = bind) { + function bindEach(nodes: NodeArray | undefined, bindFunction: (node: Node) => void = bind): void { if (nodes === undefined) { return; } @@ -820,7 +821,7 @@ namespace ts { } } - function createFlowCondition(flags: FlowFlags, antecedent: FlowNode, expression: Expression): FlowNode { + function createFlowCondition(flags: FlowFlags, antecedent: FlowNode, expression: Expression | undefined): FlowNode { if (antecedent.flags & FlowFlags.Unreachable) { return antecedent; } @@ -907,7 +908,7 @@ namespace ts { return !isStatementCondition(node) && !isLogicalExpression(node.parent); } - function bindCondition(node: Expression, trueTarget: FlowLabel, falseTarget: FlowLabel) { + function bindCondition(node: Expression | undefined, trueTarget: FlowLabel, falseTarget: FlowLabel) { const saveTrueTarget = currentTrueTarget; const saveFalseTarget = currentFalseTarget; currentTrueTarget = trueTarget; @@ -947,7 +948,7 @@ namespace ts { function bindDoStatement(node: DoStatement): void { const preDoLabel = createLoopLabel(); const enclosingLabeledStatement = node.parent.kind === SyntaxKind.LabeledStatement - ? lastOrUndefined(activeLabels) + ? lastOrUndefined(activeLabels!) : undefined; // if do statement is wrapped in labeled statement then target labels for break/continue with or without // label should be the same @@ -1032,7 +1033,7 @@ namespace ts { return undefined; } - function bindBreakOrContinueFlow(node: BreakOrContinueStatement, breakTarget: FlowLabel, continueTarget: FlowLabel) { + function bindBreakOrContinueFlow(node: BreakOrContinueStatement, breakTarget: FlowLabel | undefined, continueTarget: FlowLabel | undefined) { const flowLabel = node.kind === SyntaxKind.BreakStatement ? breakTarget : continueTarget; if (flowLabel) { addAntecedent(flowLabel, currentFlow); @@ -1162,7 +1163,8 @@ namespace ts { i++; } const preCaseLabel = createBranchLabel(); - addAntecedent(preCaseLabel, createFlowSwitchClause(preSwitchCaseFlow, node.parent, clauseStart, i + 1)); + addAntecedent(preCaseLabel, createFlowSwitchClause(preSwitchCaseFlow!, node.parent, clauseStart, i + 1)); + addAntecedent(preCaseLabel, createFlowSwitchClause(preSwitchCaseFlow!, node.parent, clauseStart, i + 1)); addAntecedent(preCaseLabel, fallthroughFlow); currentFlow = finishFlowLabel(preCaseLabel); const clause = clauses[i]; @@ -1178,7 +1180,7 @@ namespace ts { function bindCaseClause(node: CaseClause): void { const saveCurrentFlow = currentFlow; - currentFlow = preSwitchCaseFlow; + currentFlow = preSwitchCaseFlow!; bind(node.expression); currentFlow = saveCurrentFlow; bindEach(node.statements); @@ -1196,7 +1198,7 @@ namespace ts { } function popActiveLabel() { - activeLabels.pop(); + activeLabels!.pop(); } function bindLabeledStatement(node: LabeledStatement): void { @@ -1301,7 +1303,7 @@ namespace ts { currentFlow = finishFlowLabel(postExpressionLabel); } else { - bindLogicalExpression(node, currentTrueTarget, currentFalseTarget); + bindLogicalExpression(node, currentTrueTarget!, currentFalseTarget!); } } else { @@ -1478,7 +1480,7 @@ namespace ts { lastContainer = next; } - function declareSymbolAndAddToSymbolTable(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags): Symbol { + function declareSymbolAndAddToSymbolTable(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags): Symbol | undefined { switch (container.kind) { // Modules, source files, and classes need specialized handling for how their // members are declared (for example, a member of a class will go into a specific @@ -1495,7 +1497,7 @@ namespace ts { return declareClassMember(node, symbolFlags, symbolExcludes); case SyntaxKind.EnumDeclaration: - return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); + return declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes); case SyntaxKind.TypeLiteral: case SyntaxKind.JSDocTypeLiteral: @@ -1507,7 +1509,7 @@ namespace ts { // container, and are never in scope otherwise (even inside the body of the // object / type / interface declaring them). An exception is type parameters, // which are in scope without qualification (similar to 'locals'). - return declareSymbol(container.symbol.members, container.symbol, node, symbolFlags, symbolExcludes); + return declareSymbol(container.symbol.members!, container.symbol, node, symbolFlags, symbolExcludes); case SyntaxKind.FunctionType: case SyntaxKind.ConstructorType: @@ -1534,20 +1536,20 @@ namespace ts { // their container in the tree). To accomplish this, we simply add their declared // symbol to the 'locals' of the container. These symbols can then be found as // the type checker walks up the containers, checking them for matching names. - return declareSymbol(container.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes); + return declareSymbol(container.locals!, /*parent*/ undefined, node, symbolFlags, symbolExcludes); } } function declareClassMember(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags) { return hasModifier(node, ModifierFlags.Static) - ? declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes) - : declareSymbol(container.symbol.members, container.symbol, node, symbolFlags, symbolExcludes); + ? declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes) + : declareSymbol(container.symbol.members!, container.symbol, node, symbolFlags, symbolExcludes); } function declareSourceFileMember(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags) { return isExternalModule(file) ? declareModuleMember(node, symbolFlags, symbolExcludes) - : declareSymbol(file.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes); + : declareSymbol(file.locals!, /*parent*/ undefined, node, symbolFlags, symbolExcludes); } function hasExportDeclarations(node: ModuleDeclaration | SourceFile): boolean { @@ -1594,8 +1596,8 @@ namespace ts { } } - const symbol = declareSymbolAndAddToSymbolTable(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes); - file.patternAmbientModules = append(file.patternAmbientModules, pattern && { pattern, symbol }); + const symbol = declareSymbolAndAddToSymbolTable(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes)!; + file.patternAmbientModules = append(file.patternAmbientModules, pattern && { pattern, symbol }); } } else { @@ -1628,7 +1630,7 @@ namespace ts { // We do that by making an anonymous type literal symbol, and then setting the function // symbol as its sole member. To the rest of the system, this symbol will be indistinguishable // from an actual type literal symbol you would have gotten had you used the long form. - const symbol = createSymbol(SymbolFlags.Signature, getDeclarationName(node)); + const symbol = createSymbol(SymbolFlags.Signature, getDeclarationName(node)!); // TODO: GH#18217 addDeclarationToSymbol(symbol, node, SymbolFlags.Signature); const typeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, InternalSymbolName.Type); @@ -1757,8 +1759,8 @@ namespace ts { // check for reserved words used as identifiers in strict mode code. function checkStrictModeIdentifier(node: Identifier) { if (inStrictMode && - node.originalKeywordKind >= SyntaxKind.FirstFutureReservedWord && - node.originalKeywordKind <= SyntaxKind.LastFutureReservedWord && + node.originalKeywordKind! >= SyntaxKind.FirstFutureReservedWord && + node.originalKeywordKind! <= SyntaxKind.LastFutureReservedWord && !isIdentifierName(node) && !(node.flags & NodeFlags.Ambient)) { @@ -1814,7 +1816,7 @@ namespace ts { return isIdentifier(node) && (node.escapedText === "eval" || node.escapedText === "arguments"); } - function checkStrictModeEvalOrArguments(contextNode: Node, name: Node) { + function checkStrictModeEvalOrArguments(contextNode: Node, name: Node | undefined) { if (name && name.kind === SyntaxKind.Identifier) { const identifier = name; if (isEvalOrArgumentsIdentifier(identifier)) { @@ -1925,7 +1927,7 @@ namespace ts { } } - function bind(node: Node): void { + function bind(node: Node | undefined): void { if (!node) { return; } @@ -1980,12 +1982,12 @@ namespace ts { function bindJSDoc(node: Node) { if (hasJSDocNodes(node)) { if (isInJavaScriptFile(node)) { - for (const j of node.jsDoc) { + for (const j of node.jsDoc!) { bind(j); } } else { - for (const j of node.jsDoc) { + for (const j of node.jsDoc!) { setParentPointers(node, j); } } @@ -2231,7 +2233,7 @@ namespace ts { bindSourceFileAsExternalModule(); // Create symbol equivalent for the module.exports = {} const originalSymbol = file.symbol; - declareSymbol(file.symbol.exports, file.symbol, file, SymbolFlags.Property, SymbolFlags.All); + declareSymbol(file.symbol.exports!, file.symbol, file, SymbolFlags.Property, SymbolFlags.All); file.symbol = originalSymbol; } } @@ -2243,7 +2245,7 @@ namespace ts { function bindExportAssignment(node: ExportAssignment) { if (!container.symbol || !container.symbol.exports) { // Export assignment in some sort of block construct - bindAnonymousDeclaration(node, SymbolFlags.Alias, getDeclarationName(node)); + bindAnonymousDeclaration(node, SymbolFlags.Alias, getDeclarationName(node)!); } else { const flags = node.kind === SyntaxKind.ExportAssignment && exportAssignmentIsAlias(node) @@ -2287,7 +2289,7 @@ namespace ts { function bindExportDeclaration(node: ExportDeclaration) { if (!container.symbol || !container.symbol.exports) { // Export * in some sort of block construct - bindAnonymousDeclaration(node, SymbolFlags.ExportStar, getDeclarationName(node)); + bindAnonymousDeclaration(node, SymbolFlags.ExportStar, getDeclarationName(node)!); } else if (!node.exportClause) { // All export * declarations are collected in an __export symbol @@ -2319,7 +2321,7 @@ namespace ts { if (!original) { return undefined; } - const s = getJSInitializerSymbol(original); + const s = getJSInitializerSymbol(original)!; addDeclarationToSymbol(s, id, SymbolFlags.Module | SymbolFlags.JSContainer); return s; }); @@ -2327,7 +2329,7 @@ namespace ts { const flags = isClassExpression(node.right) ? SymbolFlags.Property | SymbolFlags.ExportValue | SymbolFlags.Class : SymbolFlags.Property | SymbolFlags.ExportValue; - declareSymbol(symbol.exports, symbol, lhs, flags, SymbolFlags.None); + declareSymbol(symbol.exports!, symbol, lhs, flags, SymbolFlags.None); } } @@ -2348,7 +2350,7 @@ namespace ts { const flags = exportAssignmentIsAlias(node) ? SymbolFlags.Alias // An export= with an EntityNameExpression or a ClassExpression exports all meanings of that identifier or class : SymbolFlags.Property | SymbolFlags.ExportValue | SymbolFlags.ValueModule; - declareSymbol(file.symbol.exports, file.symbol, node, flags, SymbolFlags.None); + declareSymbol(file.symbol.exports!, file.symbol, node, flags, SymbolFlags.None); } function bindThisPropertyAssignment(node: BinaryExpression | PropertyAccessExpression) { @@ -2362,7 +2364,7 @@ namespace ts { if (isBinaryExpression(thisContainer.parent) && thisContainer.parent.operatorToken.kind === SyntaxKind.EqualsToken) { const l = thisContainer.parent.left; if (isPropertyAccessEntityNameExpression(l) && isPrototypeAccess(l.expression)) { - constructorSymbol = getJSInitializerSymbolFromName(l.expression.expression, thisParentContainer); + constructorSymbol = getJSInitializerSymbolFromName(l.expression.expression, thisParentContainer)!; } } @@ -2382,7 +2384,7 @@ namespace ts { // this.foo assignment in a JavaScript class // Bind this property to the containing class const containingClass = thisContainer.parent; - const symbolTable = hasModifier(thisContainer, ModifierFlags.Static) ? containingClass.symbol.exports : containingClass.symbol.members; + const symbolTable = hasModifier(thisContainer, ModifierFlags.Static) ? containingClass.symbol.exports! : containingClass.symbol.members!; declareSymbol(symbolTable, containingClass.symbol, node, SymbolFlags.Property, SymbolFlags.None, /*isReplaceableByMethod*/ true); break; case SyntaxKind.SourceFile: @@ -2461,7 +2463,7 @@ namespace ts { bindPropertyAssignment(node.expression, node, /*isPrototypeProperty*/ false); } - function getJSInitializerSymbolFromName(name: EntityNameExpression, lookupContainer?: Node): Symbol { + function getJSInitializerSymbolFromName(name: EntityNameExpression, lookupContainer?: Node): Symbol | undefined { return getJSInitializerSymbol(lookupSymbolForPropertyAccess(name, lookupContainer)); } @@ -2482,7 +2484,7 @@ namespace ts { return original; } else { - return symbol = declareSymbol(symbol ? symbol.exports : container.locals, symbol, id, flags, excludeFlags); + return symbol = declareSymbol(symbol ? symbol.exports! : container.locals!, symbol, id, flags, excludeFlags); } }); } @@ -2497,7 +2499,7 @@ namespace ts { // Declare the method/property const jsContainerFlag = isToplevelNamespaceableInitializer ? SymbolFlags.JSContainer : 0; - const isMethod = isFunctionLikeDeclaration(getAssignedJavascriptInitializer(propertyAccess)); + const isMethod = isFunctionLikeDeclaration(getAssignedJavascriptInitializer(propertyAccess)!); // TODO: GH#18217 const symbolFlags = (isMethod ? SymbolFlags.Method : SymbolFlags.Property) | jsContainerFlag; const symbolExcludes = (isMethod ? SymbolFlags.MethodExcludes : SymbolFlags.PropertyExcludes) & ~jsContainerFlag; declareSymbol(symbolTable, symbol, propertyAccess, symbolFlags, symbolExcludes); @@ -2520,7 +2522,7 @@ namespace ts { } } - function forEachIdentifierInEntityName(e: EntityNameExpression, action: (e: Identifier, symbol: Symbol) => Symbol): Symbol { + function forEachIdentifierInEntityName(e: EntityNameExpression, action: (e: Identifier, symbol: Symbol | undefined) => Symbol | undefined): Symbol | undefined { if (isExportsOrModuleExportsOrAlias(file, e)) { return file.symbol; } @@ -2529,7 +2531,7 @@ namespace ts { } else { const s = getJSInitializerSymbol(forEachIdentifierInEntityName(e.expression, action)); - Debug.assert(!!s && !!s.exports); + if (!s || !s.exports) return Debug.fail(); return action(e.name, s.exports.get(e.name.escapedText)); } } @@ -2555,7 +2557,7 @@ namespace ts { } } - const symbol = node.symbol; + const { symbol } = node; // TypeScript 1.0 spec (April 2014): 8.4 // Every class automatically contains a static property member named 'prototype', the @@ -2567,14 +2569,14 @@ namespace ts { // module might have an exported variable called 'prototype'. We can't allow that as // that would clash with the built-in 'prototype' for the class. const prototypeSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Prototype, "prototype" as __String); - const symbolExport = symbol.exports.get(prototypeSymbol.escapedName); + const symbolExport = symbol.exports!.get(prototypeSymbol.escapedName); if (symbolExport) { if (node.name) { node.name.parent = node; } file.bindDiagnostics.push(createDiagnosticForNode(symbolExport.declarations[0], Diagnostics.Duplicate_identifier_0, symbolName(prototypeSymbol))); } - symbol.exports.set(prototypeSymbol.escapedName, prototypeSymbol); + symbol.exports!.set(prototypeSymbol.escapedName, prototypeSymbol); prototypeSymbol.parent = symbol; } @@ -2632,7 +2634,7 @@ namespace ts { // containing class. if (isParameterPropertyDeclaration(node)) { const classDeclaration = node.parent.parent; - declareSymbol(classDeclaration.symbol.members, classDeclaration.symbol, node, SymbolFlags.Property | (node.questionToken ? SymbolFlags.Optional : SymbolFlags.None), SymbolFlags.PropertyExcludes); + declareSymbol(classDeclaration.symbol.members!, classDeclaration.symbol, node, SymbolFlags.Property | (node.questionToken ? SymbolFlags.Optional : SymbolFlags.None), SymbolFlags.PropertyExcludes); } } @@ -2681,14 +2683,14 @@ namespace ts { : declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes); } - function getInferTypeContainer(node: Node): ConditionalTypeNode { + function getInferTypeContainer(node: Node): ConditionalTypeNode | undefined { const extendsType = findAncestor(node, n => n.parent && isConditionalTypeNode(n.parent) && n.parent.extendsType === n); return extendsType && extendsType.parent as ConditionalTypeNode; } function bindTypeParameter(node: TypeParameterDeclaration) { if (isJSDocTemplateTag(node.parent)) { - const container = find((node.parent.parent as JSDoc).tags, isJSDocTypeAlias) || getHostSignatureFromJSDoc(node.parent); + const container = find((node.parent.parent as JSDoc).tags!, isJSDocTypeAlias) || getHostSignatureFromJSDoc(node.parent); // TODO: GH#18217 if (container) { if (!container.locals) { container.locals = createSymbolTable(); @@ -2708,7 +2710,7 @@ namespace ts { declareSymbol(container.locals, /*parent*/ undefined, node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes); } else { - bindAnonymousDeclaration(node, SymbolFlags.TypeParameter, getDeclarationName(node)); + bindAnonymousDeclaration(node, SymbolFlags.TypeParameter, getDeclarationName(node)!); // TODO: GH#18217 } } else { @@ -2720,7 +2722,7 @@ namespace ts { function shouldReportErrorOnModuleDeclaration(node: ModuleDeclaration): boolean { const instanceState = getModuleInstanceState(node); - return instanceState === ModuleInstanceState.Instantiated || (instanceState === ModuleInstanceState.ConstEnumOnly && options.preserveConstEnums); + return instanceState === ModuleInstanceState.Instantiated || (instanceState === ModuleInstanceState.ConstEnumOnly && !!options.preserveConstEnums); } function checkUnreachable(node: Node): boolean { @@ -2777,8 +2779,8 @@ namespace ts { function isNameOfExportsOrModuleExportsAliasDeclaration(sourceFile: SourceFile, node: Identifier): boolean { const symbol = lookupSymbolForNameWorker(sourceFile, node.escapedText); - return symbol && symbol.valueDeclaration && isVariableDeclaration(symbol.valueDeclaration) && - symbol.valueDeclaration.initializer && isExportsOrModuleExportsOrAliasOrAssignment(sourceFile, symbol.valueDeclaration.initializer); + return !!symbol && !!symbol.valueDeclaration && isVariableDeclaration(symbol.valueDeclaration) && + !!symbol.valueDeclaration.initializer && isExportsOrModuleExportsOrAliasOrAssignment(sourceFile, symbol.valueDeclaration.initializer); } function isExportsOrModuleExportsOrAliasOrAssignment(sourceFile: SourceFile, node: Expression): boolean { diff --git a/src/compiler/builder.ts b/src/compiler/builder.ts index 6dd3226e550ee..a4f3bbefac20a 100644 --- a/src/compiler/builder.ts +++ b/src/compiler/builder.ts @@ -3,6 +3,7 @@ namespace ts { /** * State to store the changed files, affected files and cache semantic diagnostics */ + // TODO: GH#18217 Properties of this interface are frequently asserted to be defined. export interface BuilderProgramState extends BuilderState { /** * Cache of semantic diagnostics for files with their Path being the key @@ -41,7 +42,7 @@ namespace ts { function hasSameKeys(map1: ReadonlyMap | undefined, map2: ReadonlyMap | undefined): boolean { // Has same size and every key is present in both maps - return map1 as ReadonlyMap === map2 || map1 && map2 && map1.size === map2.size && !forEachKey(map1, key => !map2.has(key)); + return map1 as ReadonlyMap === map2 || map1 !== undefined && map2 !== undefined && map1.size === map2.size && !forEachKey(map1, key => !map2.has(key)); } /** @@ -56,45 +57,45 @@ namespace ts { } state.changedFilesSet = createMap(); const useOldState = BuilderState.canReuseOldState(state.referencedMap, oldState); - const canCopySemanticDiagnostics = useOldState && oldState.semanticDiagnosticsPerFile && !!state.semanticDiagnosticsPerFile; + const canCopySemanticDiagnostics = useOldState && oldState!.semanticDiagnosticsPerFile && !!state.semanticDiagnosticsPerFile; if (useOldState) { // Verify the sanity of old state - if (!oldState.currentChangedFilePath) { - Debug.assert(!oldState.affectedFiles && (!oldState.currentAffectedFilesSignatures || !oldState.currentAffectedFilesSignatures.size), "Cannot reuse if only few affected files of currentChangedFile were iterated"); + if (!oldState!.currentChangedFilePath) { + Debug.assert(!oldState!.affectedFiles && (!oldState!.currentAffectedFilesSignatures || !oldState!.currentAffectedFilesSignatures!.size), "Cannot reuse if only few affected files of currentChangedFile were iterated"); } if (canCopySemanticDiagnostics) { - Debug.assert(!forEachKey(oldState.changedFilesSet, path => oldState.semanticDiagnosticsPerFile.has(path)), "Semantic diagnostics shouldnt be available for changed files"); + Debug.assert(!forEachKey(oldState!.changedFilesSet, path => oldState!.semanticDiagnosticsPerFile!.has(path)), "Semantic diagnostics shouldnt be available for changed files"); } // Copy old state's changed files set - copyEntries(oldState.changedFilesSet, state.changedFilesSet); + copyEntries(oldState!.changedFilesSet, state.changedFilesSet); } // Update changed files and copy semantic diagnostics if we can const referencedMap = state.referencedMap; - const oldReferencedMap = useOldState && oldState.referencedMap; + const oldReferencedMap = useOldState ? oldState!.referencedMap : undefined; state.fileInfos.forEach((info, sourceFilePath) => { - let oldInfo: Readonly; - let newReferences: BuilderState.ReferencedSet; + let oldInfo: Readonly | undefined; + let newReferences: BuilderState.ReferencedSet | undefined; // if not using old state, every file is changed if (!useOldState || // File wasnt present in old state - !(oldInfo = oldState.fileInfos.get(sourceFilePath)) || + !(oldInfo = oldState!.fileInfos.get(sourceFilePath)) || // versions dont match oldInfo.version !== info.version || // Referenced files changed !hasSameKeys(newReferences = referencedMap && referencedMap.get(sourceFilePath), oldReferencedMap && oldReferencedMap.get(sourceFilePath)) || // Referenced file was deleted in the new program - newReferences && forEachKey(newReferences, path => !state.fileInfos.has(path) && oldState.fileInfos.has(path))) { + newReferences && forEachKey(newReferences, path => !state.fileInfos.has(path) && oldState!.fileInfos.has(path))) { // Register file as changed file and do not copy semantic diagnostics, since all changed files need to be re-evaluated state.changedFilesSet.set(sourceFilePath, true); } else if (canCopySemanticDiagnostics) { // Unchanged file copy diagnostics - const diagnostics = oldState.semanticDiagnosticsPerFile.get(sourceFilePath); + const diagnostics = oldState!.semanticDiagnosticsPerFile!.get(sourceFilePath); if (diagnostics) { - state.semanticDiagnosticsPerFile.set(sourceFilePath, diagnostics); + state.semanticDiagnosticsPerFile!.set(sourceFilePath, diagnostics); } } }); @@ -106,7 +107,7 @@ namespace ts { * Verifies that source file is ok to be used in calls that arent handled by next */ function assertSourceFileOkWithoutNextAffectedCall(state: BuilderProgramState, sourceFile: SourceFile | undefined) { - Debug.assert(!sourceFile || !state.affectedFiles || state.affectedFiles[state.affectedFilesIndex - 1] !== sourceFile || !state.semanticDiagnosticsPerFile.has(sourceFile.path)); + Debug.assert(!sourceFile || !state.affectedFiles || state.affectedFiles[state.affectedFilesIndex! - 1] !== sourceFile || !state.semanticDiagnosticsPerFile!.has(sourceFile.path)); } /** @@ -120,25 +121,25 @@ namespace ts { const { affectedFiles } = state; if (affectedFiles) { const { seenAffectedFiles, semanticDiagnosticsPerFile } = state; - let { affectedFilesIndex } = state; + let affectedFilesIndex = state.affectedFilesIndex!; // TODO: GH#18217 while (affectedFilesIndex < affectedFiles.length) { const affectedFile = affectedFiles[affectedFilesIndex]; - if (!seenAffectedFiles.has(affectedFile.path)) { + if (!seenAffectedFiles!.has(affectedFile.path)) { // Set the next affected file as seen and remove the cached semantic diagnostics state.affectedFilesIndex = affectedFilesIndex; - semanticDiagnosticsPerFile.delete(affectedFile.path); + semanticDiagnosticsPerFile!.delete(affectedFile.path); return affectedFile; } - seenAffectedFiles.set(affectedFile.path, true); + seenAffectedFiles!.set(affectedFile.path, true); affectedFilesIndex++; } // Remove the changed file from the change set - state.changedFilesSet.delete(state.currentChangedFilePath); + state.changedFilesSet.delete(state.currentChangedFilePath!); state.currentChangedFilePath = undefined; // Commit the changes in file signature - BuilderState.updateSignaturesFromCache(state, state.currentAffectedFilesSignatures); - state.currentAffectedFilesSignatures.clear(); + BuilderState.updateSignaturesFromCache(state, state.currentAffectedFilesSignatures!); + state.currentAffectedFilesSignatures!.clear(); state.affectedFiles = undefined; } @@ -161,7 +162,7 @@ namespace ts { state.currentAffectedFilesSignatures = state.currentAffectedFilesSignatures || createMap(); state.affectedFiles = BuilderState.getFilesAffectedBy(state, state.program, nextKey.value as Path, cancellationToken, computeHash, state.currentAffectedFilesSignatures); state.currentChangedFilePath = nextKey.value as Path; - state.semanticDiagnosticsPerFile.delete(nextKey.value as Path); + state.semanticDiagnosticsPerFile!.delete(nextKey.value as Path); state.affectedFilesIndex = 0; state.seenAffectedFiles = state.seenAffectedFiles || createMap(); } @@ -176,8 +177,8 @@ namespace ts { state.changedFilesSet.clear(); } else { - state.seenAffectedFiles.set((affected as SourceFile).path, true); - state.affectedFilesIndex++; + state.seenAffectedFiles!.set((affected as SourceFile).path, true); + state.affectedFilesIndex!++; } } @@ -195,7 +196,7 @@ namespace ts { */ function getSemanticDiagnosticsOfFile(state: BuilderProgramState, sourceFile: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray { const path = sourceFile.path; - const cachedDiagnostics = state.semanticDiagnosticsPerFile.get(path); + const cachedDiagnostics = state.semanticDiagnosticsPerFile!.get(path); // Report the semantic diagnostics from the cache if we already have those diagnostics present if (cachedDiagnostics) { return cachedDiagnostics; @@ -203,7 +204,7 @@ namespace ts { // Diagnostics werent cached, get them from program, and cache the result const diagnostics = state.program.getSemanticDiagnostics(sourceFile, cancellationToken); - state.semanticDiagnosticsPerFile.set(path, diagnostics); + state.semanticDiagnosticsPerFile!.set(path, diagnostics); return diagnostics; } @@ -250,7 +251,7 @@ namespace ts { // Return same program if underlying program doesnt change let oldState = oldProgram && oldProgram.getState(); if (oldState && newProgram === oldState.program && configFileParsingDiagnostics === newProgram.getConfigFileParsingDiagnostics()) { - newProgram = undefined; + newProgram = undefined!; // TODO: GH#18217 oldState = undefined; return oldProgram; } @@ -266,7 +267,7 @@ namespace ts { const state = createBuilderProgramState(newProgram, getCanonicalFileName, oldState); // To ensure that we arent storing any references to old program or new program without state - newProgram = undefined; + newProgram = undefined!; // TODO: GH#18217 oldProgram = undefined; oldState = undefined; @@ -336,8 +337,8 @@ namespace ts { if (!targetSourceFile) { // Emit and report any errors we ran into. let sourceMaps: SourceMapData[] = []; - let emitSkipped: boolean; - let diagnostics: Diagnostic[]; + let emitSkipped = false; + let diagnostics: Diagnostic[] | undefined; let emittedFiles: string[] = []; let affectedEmitResult: AffectedFileResult; @@ -423,7 +424,7 @@ namespace ts { } } - let diagnostics: Diagnostic[]; + let diagnostics: Diagnostic[] | undefined; for (const sourceFile of state.program.getSourceFiles()) { diagnostics = addRange(diagnostics, getSemanticDiagnosticsOfFile(state, sourceFile, cancellationToken)); } diff --git a/src/compiler/builderState.ts b/src/compiler/builderState.ts index ac9f36b1258df..ed41ef4a8d3fa 100644 --- a/src/compiler/builderState.ts +++ b/src/compiler/builderState.ts @@ -108,7 +108,7 @@ namespace ts.BuilderState { return; } - const fileName = resolvedTypeReferenceDirective.resolvedFileName; + const fileName = resolvedTypeReferenceDirective.resolvedFileName!; // TODO: GH#18217 const typeFilePath = toPath(fileName, sourceFileDirectory, getCanonicalFileName); addReferencedFile(typeFilePath); }); @@ -127,7 +127,7 @@ namespace ts.BuilderState { /** * Returns true if oldState is reusable, that is the emitKind = module/non module has not changed */ - export function canReuseOldState(newReferencedMap: ReadonlyMap, oldState: Readonly | undefined) { + export function canReuseOldState(newReferencedMap: ReadonlyMap | undefined, oldState: Readonly | undefined) { return oldState && !oldState.referencedMap === !newReferencedMap; } @@ -143,7 +143,7 @@ namespace ts.BuilderState { // Create the reference map, and set the file infos for (const sourceFile of newProgram.getSourceFiles()) { const version = sourceFile.version; - const oldInfo = useOldState && oldState.fileInfos.get(sourceFile.path); + const oldInfo = useOldState ? oldState!.fileInfos.get(sourceFile.path) : undefined; if (referencedMap) { const newReferences = getReferencedFiles(newProgram, sourceFile, getCanonicalFileName); if (newReferences) { @@ -194,7 +194,7 @@ namespace ts.BuilderState { */ export function updateSignaturesFromCache(state: BuilderState, signatureCache: Map) { signatureCache.forEach((signature, path) => { - state.fileInfos.get(path).signature = signature; + state.fileInfos.get(path)!.signature = signature; state.hasCalledUpdateShapeSignature.set(path, true); }); } @@ -211,7 +211,7 @@ namespace ts.BuilderState { } const info = state.fileInfos.get(sourceFile.path); - Debug.assert(!!info); + if (!info) return Debug.fail(); const prevSignature = info.signature; let latestSignature: string; @@ -224,7 +224,7 @@ namespace ts.BuilderState { latestSignature = computeHash(emitOutput.outputFiles[0].text); } else { - latestSignature = prevSignature; + latestSignature = prevSignature!; // TODO: GH#18217 } } cacheToUpdateSignature.set(sourceFile.path, latestSignature); @@ -251,7 +251,7 @@ namespace ts.BuilderState { const seenMap = createMap(); const queue = [sourceFile.path]; while (queue.length) { - const path = queue.pop(); + const path = queue.pop()!; if (!seenMap.has(path)) { seenMap.set(path, true); const references = state.referencedMap.get(path); @@ -285,7 +285,7 @@ namespace ts.BuilderState { * Gets the files referenced by the the file path */ function getReferencedByPaths(state: Readonly, referencedFilePath: Path) { - return arrayFrom(mapDefinedIterator(state.referencedMap.entries(), ([filePath, referencesInFile]) => + return arrayFrom(mapDefinedIterator(state.referencedMap!.entries(), ([filePath, referencesInFile]) => referencesInFile.has(referencedFilePath) ? filePath as Path : undefined )); } @@ -314,7 +314,7 @@ namespace ts.BuilderState { return state.allFilesExcludingDefaultLibraryFile; } - let result: SourceFile[]; + let result: SourceFile[] | undefined; addSourceFile(firstSourceFile); for (const sourceFile of programOfThisState.getSourceFiles()) { if (sourceFile !== firstSourceFile) { @@ -366,11 +366,11 @@ namespace ts.BuilderState { seenFileNamesMap.set(sourceFileWithUpdatedShape.path, sourceFileWithUpdatedShape); const queue = getReferencedByPaths(state, sourceFileWithUpdatedShape.path); while (queue.length > 0) { - const currentPath = queue.pop(); + const currentPath = queue.pop()!; if (!seenFileNamesMap.has(currentPath)) { - const currentSourceFile = programOfThisState.getSourceFileByPath(currentPath); + const currentSourceFile = programOfThisState.getSourceFileByPath(currentPath)!; seenFileNamesMap.set(currentPath, currentSourceFile); - if (currentSourceFile && updateShapeSignature(state, programOfThisState, currentSourceFile, cacheToUpdateSignature, cancellationToken, computeHash)) { + if (currentSourceFile && updateShapeSignature(state, programOfThisState, currentSourceFile, cacheToUpdateSignature, cancellationToken, computeHash!)) { // TODO: GH#18217 queue.push(...getReferencedByPaths(state, currentPath)); } } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index faa6cb9cb76e8..d2ee958752eea 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -40,7 +40,7 @@ namespace ts { // Currently we only support setting the cancellation token when getting diagnostics. This // is because diagnostics can be quite expensive, and we want to allow hosts to bail out if // they no longer need the information (for example, if the user started editing again). - let cancellationToken: CancellationToken; + let cancellationToken: CancellationToken | undefined; let requestedExternalEmitHelpers: ExternalEmitHelpers; let externalHelpersModule: Symbol; @@ -101,9 +101,9 @@ namespace ts { location = getParseTreeNode(location); return location ? getTypeOfSymbolAtLocation(symbol, location) : unknownType; }, - getSymbolsOfParameterPropertyDeclaration: (parameter, parameterName) => { - parameter = getParseTreeNode(parameter, isParameter); - Debug.assert(parameter !== undefined, "Cannot get symbols of a synthetic parameter that cannot be resolved to a parse-tree node."); + getSymbolsOfParameterPropertyDeclaration: (parameterIn, parameterName) => { + const parameter = getParseTreeNode(parameterIn, isParameter); + if (parameter === undefined) return Debug.fail("Cannot get symbols of a synthetic parameter that cannot be resolved to a parse-tree node."); return getSymbolsOfParameterPropertyDeclaration(parameter, escapeLeadingUnderscores(parameterName)); }, getDeclaredTypeOfSymbol, @@ -115,8 +115,8 @@ namespace ts { getBaseTypes, getBaseTypeOfLiteralType, getWidenedType, - getTypeFromTypeNode: node => { - node = getParseTreeNode(node, isTypeNode); + getTypeFromTypeNode: nodeIn => { + const node = getParseTreeNode(nodeIn, isTypeNode); return node ? getTypeFromTypeNode(node) : unknownType; }, getParameterType: getTypeAtPosition, @@ -126,11 +126,11 @@ namespace ts { typeToTypeNode: nodeBuilder.typeToTypeNode, indexInfoToIndexSignatureDeclaration: nodeBuilder.indexInfoToIndexSignatureDeclaration, signatureToSignatureDeclaration: nodeBuilder.signatureToSignatureDeclaration, - symbolToEntityName: nodeBuilder.symbolToEntityName, - symbolToExpression: nodeBuilder.symbolToExpression, + symbolToEntityName: nodeBuilder.symbolToEntityName as (symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration?: Node, flags?: NodeBuilderFlags) => EntityName, // TODO: GH#18217 + symbolToExpression: nodeBuilder.symbolToExpression as (symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration?: Node, flags?: NodeBuilderFlags) => Expression, // TODO: GH#18217 symbolToTypeParameterDeclarations: nodeBuilder.symbolToTypeParameterDeclarations, - symbolToParameterDeclaration: nodeBuilder.symbolToParameterDeclaration, - typeParameterToDeclaration: nodeBuilder.typeParameterToDeclaration, + symbolToParameterDeclaration: nodeBuilder.symbolToParameterDeclaration as (symbol: Symbol, enclosingDeclaration?: Node, flags?: NodeBuilderFlags) => ParameterDeclaration, // TODO: GH#18217 + typeParameterToDeclaration: nodeBuilder.typeParameterToDeclaration as (parameter: TypeParameter, enclosingDeclaration?: Node, flags?: NodeBuilderFlags) => TypeParameterDeclaration, // TODO: GH#18217 getSymbolsInScope: (location, meaning) => { location = getParseTreeNode(location); return location ? getSymbolsInScope(location, meaning) : []; @@ -143,8 +143,8 @@ namespace ts { node = getParseTreeNode(node); return node ? getShorthandAssignmentValueSymbol(node) : undefined; }, - getExportSpecifierLocalTargetSymbol: node => { - node = getParseTreeNode(node, isExportSpecifier); + getExportSpecifierLocalTargetSymbol: nodeIn => { + const node = getParseTreeNode(nodeIn, isExportSpecifier); return node ? getExportSpecifierLocalTargetSymbol(node) : undefined; }, getExportSymbolOfSymbol(symbol) { @@ -154,8 +154,8 @@ namespace ts { node = getParseTreeNode(node); return node ? getTypeOfNode(node) : unknownType; }, - getPropertySymbolOfDestructuringAssignment: location => { - location = getParseTreeNode(location, isIdentifier); + getPropertySymbolOfDestructuringAssignment: locationIn => { + const location = getParseTreeNode(locationIn, isIdentifier); return location ? getPropertySymbolOfDestructuringAssignment(location) : undefined; }, signatureToString: (signature, enclosingDeclaration, flags, kind) => { @@ -185,41 +185,41 @@ namespace ts { getSymbolDisplayBuilder, // TODO (weswigham): Remove once deprecation process is complete getAugmentedPropertiesOfType, getRootSymbols, - getContextualType: node => { - node = getParseTreeNode(node, isExpression); + getContextualType: nodeIn => { + const node = getParseTreeNode(nodeIn, isExpression); return node ? getContextualType(node) : undefined; }, - getContextualTypeForArgumentAtIndex: (node, argIndex) => { - node = getParseTreeNode(node, isCallLikeExpression); + getContextualTypeForArgumentAtIndex: (nodeIn, argIndex) => { + const node = getParseTreeNode(nodeIn, isCallLikeExpression); return node && getContextualTypeForArgumentAtIndex(node, argIndex); }, - getContextualTypeForJsxAttribute: (node) => { - node = getParseTreeNode(node, isJsxAttributeLike); + getContextualTypeForJsxAttribute: (nodeIn) => { + const node = getParseTreeNode(nodeIn, isJsxAttributeLike); return node && getContextualTypeForJsxAttribute(node); }, isContextSensitive, getFullyQualifiedName, - getResolvedSignature: (node, candidatesOutArray, theArgumentCount) => { - node = getParseTreeNode(node, isCallLikeExpression); + getResolvedSignature: (nodeIn, candidatesOutArray, theArgumentCount) => { + const node = getParseTreeNode(nodeIn, isCallLikeExpression); apparentArgumentCount = theArgumentCount; const res = node ? getResolvedSignature(node, candidatesOutArray) : undefined; apparentArgumentCount = undefined; return res; }, - getConstantValue: node => { - node = getParseTreeNode(node, canHaveConstantValue); + getConstantValue: nodeIn => { + const node = getParseTreeNode(nodeIn, canHaveConstantValue); return node ? getConstantValue(node) : undefined; }, - isValidPropertyAccess: (node, propertyName) => { - node = getParseTreeNode(node, isPropertyAccessOrQualifiedNameOrImportTypeNode); + isValidPropertyAccess: (nodeIn, propertyName) => { + const node = getParseTreeNode(nodeIn, isPropertyAccessOrQualifiedNameOrImportTypeNode); return !!node && isValidPropertyAccess(node, escapeLeadingUnderscores(propertyName)); }, - isValidPropertyAccessForCompletions: (node, type, property) => { - node = getParseTreeNode(node, isPropertyAccessExpression); + isValidPropertyAccessForCompletions: (nodeIn, type, property) => { + const node = getParseTreeNode(nodeIn, isPropertyAccessExpression); return !!node && isValidPropertyAccessForCompletions(node, type, property); }, - getSignatureFromDeclaration: declaration => { - declaration = getParseTreeNode(declaration, isFunctionLike); + getSignatureFromDeclaration: declarationIn => { + const declaration = getParseTreeNode(declarationIn, isFunctionLike); return declaration ? getSignatureFromDeclaration(declaration) : undefined; }, isImplementationOfOverload: node => { @@ -231,7 +231,7 @@ namespace ts { const links = getSymbolLinks(symbol); if (!links.immediateTarget) { const node = getDeclarationOfAliasSymbol(symbol); - Debug.assert(!!node); + if (!node) return Debug.fail(); links.immediateTarget = getTargetOfAliasDeclaration(node, /*dontRecursivelyResolve*/ true); } @@ -254,13 +254,13 @@ namespace ts { getFirstIdentifier, ), getAmbientModules, - getAllAttributesTypeFromJsxOpeningLikeElement: node => { - node = getParseTreeNode(node, isJsxOpeningLikeElement); + getAllAttributesTypeFromJsxOpeningLikeElement: nodeIn => { + const node = getParseTreeNode(nodeIn, isJsxOpeningLikeElement); return node ? getAllAttributesTypeFromJsxOpeningLikeElement(node) : undefined; }, getJsxIntrinsicTagNamesAt, - isOptionalParameter: node => { - node = getParseTreeNode(node, isParameter); + isOptionalParameter: nodeIn => { + const node = getParseTreeNode(nodeIn, isParameter); return node ? isOptionalParameter(node) : false; }, tryGetMemberInModuleExports: (name, symbol) => tryGetMemberInModuleExports(escapeLeadingUnderscores(name), symbol), @@ -300,14 +300,14 @@ namespace ts { }, getJsxNamespace: n => unescapeLeadingUnderscores(getJsxNamespace(n)), getAccessibleSymbolChain, - getTypePredicateOfSignature, + getTypePredicateOfSignature: getTypePredicateOfSignature as (signature: Signature) => TypePredicate, // TODO: GH#18217 resolveExternalModuleSymbol, tryGetThisTypeAt: node => { node = getParseTreeNode(node); return node && tryGetThisTypeAt(node); }, - getTypeArgumentConstraint: node => { - node = getParseTreeNode(node, isTypeNode); + getTypeArgumentConstraint: nodeIn => { + const node = getParseTreeNode(nodeIn, isTypeNode); return node && getTypeArgumentConstraint(node); }, @@ -433,11 +433,11 @@ namespace ts { // The library files are only loaded when the feature is used. // This allows users to just specify library files they want to used through --lib // and they will not get an error from not having unrelated library files - let deferredGlobalESSymbolConstructorSymbol: Symbol; + let deferredGlobalESSymbolConstructorSymbol: Symbol | undefined; let deferredGlobalESSymbolType: ObjectType; let deferredGlobalTypedPropertyDescriptorType: GenericType; let deferredGlobalPromiseType: GenericType; - let deferredGlobalPromiseConstructorSymbol: Symbol; + let deferredGlobalPromiseConstructorSymbol: Symbol | undefined; let deferredGlobalPromiseConstructorLikeType: ObjectType; let deferredGlobalIterableType: GenericType; let deferredGlobalIteratorType: GenericType; @@ -449,7 +449,7 @@ namespace ts { let deferredGlobalImportMetaType: ObjectType; let deferredGlobalExtractSymbol: Symbol; - let deferredNodes: Node[]; + let deferredNodes: Node[] | undefined; const allPotentiallyUnusedIdentifiers = createMap(); // key is file name let flowLoopStart = 0; @@ -573,7 +573,7 @@ namespace ts { const typeofType = createTypeofType(); let _jsxNamespace: __String; - let _jsxFactoryEntity: EntityName; + let _jsxFactoryEntity: EntityName | undefined; const subtypeRelation = createMap(); const assignableRelation = createMap(); @@ -647,7 +647,7 @@ namespace ts { buildTypeDisplay(type, writer, enclosingDeclaration?, flags?) { typeToString(type, enclosingDeclaration, flags, emitTextWriterWrapper(writer)); }, - buildSymbolDisplay(symbol, writer, enclosingDeclaration?, meaning?, flags?) { + buildSymbolDisplay(symbol, writer, enclosingDeclaration?, meaning?, flags = SymbolFormatFlags.None) { symbolToString(symbol, enclosingDeclaration, meaning, flags | SymbolFormatFlags.AllowAnyNodeKind, emitTextWriterWrapper(writer)); }, buildSignatureDisplay(signature, writer, enclosing?, flags?, kind?) { @@ -661,12 +661,12 @@ namespace ts { buildParameterDisplay(symbol, writer, enclosing?, flags?) { const node = nodeBuilder.symbolToParameterDeclaration(symbol, enclosing, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors, writer); const printer = createPrinter({ removeComments: true }); - printer.writeNode(EmitHint.Unspecified, node, getSourceFileOfNode(getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); + printer.writeNode(EmitHint.Unspecified, node!, getSourceFileOfNode(getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); // TODO: GH#18217 }, buildTypeParameterDisplay(tp, writer, enclosing?, flags?) { const node = nodeBuilder.typeParameterToDeclaration(tp, enclosing, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors | NodeBuilderFlags.OmitParameterModifiers, writer); const printer = createPrinter({ removeComments: true }); - printer.writeNode(EmitHint.Unspecified, node, getSourceFileOfNode(getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); + printer.writeNode(EmitHint.Unspecified, node!, getSourceFileOfNode(getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); // TODO: GH#18217 }, buildTypePredicateDisplay(predicate, writer, enclosing?, flags?) { typePredicateToString(predicate, enclosing, flags, emitTextWriterWrapper(writer)); @@ -679,13 +679,13 @@ namespace ts { buildDisplayForParametersAndDelimiters(thisParameter, parameters, writer, enclosing?, originalFlags?) { const printer = createPrinter({ removeComments: true }); const flags = NodeBuilderFlags.OmitParameterModifiers | NodeBuilderFlags.IgnoreErrors | toNodeBuilderFlags(originalFlags); - const thisParameterArray = thisParameter ? [nodeBuilder.symbolToParameterDeclaration(thisParameter, enclosing, flags)] : []; - const params = createNodeArray([...thisParameterArray, ...map(parameters, param => nodeBuilder.symbolToParameterDeclaration(param, enclosing, flags))]); + const thisParameterArray = thisParameter ? [nodeBuilder.symbolToParameterDeclaration(thisParameter, enclosing, flags)!] : []; // TODO: GH#18217 + const params = createNodeArray([...thisParameterArray, ...map(parameters, param => nodeBuilder.symbolToParameterDeclaration(param, enclosing, flags)!)]); // TODO: GH#18217 printer.writeList(ListFormat.CallExpressionArguments, params, getSourceFileOfNode(getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); }, buildDisplayForTypeParametersAndDelimiters(typeParameters, writer, enclosing?, flags?) { const printer = createPrinter({ removeComments: true }); - const args = createNodeArray(map(typeParameters, p => nodeBuilder.typeParameterToDeclaration(p, enclosing, toNodeBuilderFlags(flags)))); + const args = createNodeArray(map(typeParameters, p => nodeBuilder.typeParameterToDeclaration(p, enclosing, toNodeBuilderFlags(flags))!)); // TODO: GH#18217 printer.writeList(ListFormat.TypeParameters, args, getSourceFileOfNode(getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); }, buildReturnTypeDisplay(signature, writer, enclosing?, flags?) { @@ -697,7 +697,7 @@ namespace ts { } const node = nodeBuilder.typeToTypeNode(getReturnTypeOfSignature(signature), enclosing, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors, writer); const printer = createPrinter({ removeComments: true }); - printer.writeNode(EmitHint.Unspecified, node, getSourceFileOfNode(getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); + printer.writeNode(EmitHint.Unspecified, node!, getSourceFileOfNode(getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); // TODO: GH#18217 } }; @@ -787,7 +787,7 @@ namespace ts { } const jsxPragma = file.pragmas.get("jsx"); if (jsxPragma) { - const chosenpragma = isArray(jsxPragma) ? jsxPragma[0] : jsxPragma; + const chosenpragma: any = isArray(jsxPragma) ? jsxPragma[0] : jsxPragma; // TODO: GH#18217 file.localJsxFactory = parseIsolatedEntityName(chosenpragma.arguments.factory, languageVersion); if (file.localJsxFactory) { return file.localJsxNamespace = getFirstIdentifier(file.localJsxFactory).escapedText; @@ -817,7 +817,7 @@ namespace ts { return emitResolver; } - function error(location: Node, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number): void { + function error(location: Node | undefined, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number): void { const diagnostic = location ? createDiagnosticForNode(location, message, arg0, arg1, arg2, arg3) : createCompilerDiagnostic(message, arg0, arg1, arg2, arg3); @@ -915,7 +915,7 @@ namespace ts { mergeSymbolTable(target.exports, source.exports); } if ((source.flags | target.flags) & SymbolFlags.JSContainer) { - const sourceInitializer = getJSInitializerSymbol(source); + const sourceInitializer = getJSInitializerSymbol(source)!; const init = getDeclaredJavascriptInitializer(targetValueDeclaration) || getAssignedJavascriptInitializer(targetValueDeclaration); let targetInitializer = init && init.symbol ? init.symbol : target; if (!(targetInitializer.flags & SymbolFlags.Transient)) { @@ -984,7 +984,7 @@ namespace ts { } if (isGlobalScopeAugmentation(moduleAugmentation)) { - mergeSymbolTable(globals, moduleAugmentation.symbol.exports); + mergeSymbolTable(globals, moduleAugmentation.symbol.exports!); } else { // find a module that about to be augmented @@ -1036,14 +1036,14 @@ namespace ts { function getNodeLinks(node: Node): NodeLinks { const nodeId = getNodeId(node); - return nodeLinks[nodeId] || (nodeLinks[nodeId] = { flags: 0 }); + return nodeLinks[nodeId] || (nodeLinks[nodeId] = { flags: 0 } as NodeLinks); } function isGlobalSourceFile(node: Node) { return node.kind === SyntaxKind.SourceFile && !isExternalOrCommonJsModule(node); } - function getSymbol(symbols: SymbolTable, name: __String, meaning: SymbolFlags): Symbol { + function getSymbol(symbols: SymbolTable, name: __String, meaning: SymbolFlags): Symbol | undefined { if (meaning) { const symbol = symbols.get(name); if (symbol) { @@ -1073,14 +1073,14 @@ namespace ts { const constructorDeclaration = parameter.parent; const classDeclaration = parameter.parent.parent; - const parameterSymbol = getSymbol(constructorDeclaration.locals, parameterName, SymbolFlags.Value); + const parameterSymbol = getSymbol(constructorDeclaration.locals!, parameterName, SymbolFlags.Value); const propertySymbol = getSymbol(getMembersOfSymbol(classDeclaration.symbol), parameterName, SymbolFlags.Value); if (parameterSymbol && propertySymbol) { return [parameterSymbol, propertySymbol]; } - Debug.fail("There should exist two symbols, one as property declaration and one as parameter declaration"); + return Debug.fail("There should exist two symbols, one as property declaration and one as parameter declaration"); } function isBlockScopedNameDeclaredBeforeUse(declaration: Declaration, usage: Node): boolean { @@ -1163,7 +1163,8 @@ namespace ts { } // ForIn/ForOf case - use site should not be used in expression part - return isForInOrOfStatement(declaration.parent.parent) && isSameScopeDescendentOf(usage, declaration.parent.parent.expression, container); + const grandparent = declaration.parent.parent; + return isForInOrOfStatement(grandparent) && isSameScopeDescendentOf(usage, grandparent.expression, container); } function isUsedInFunctionOrInstanceProperty(usage: Node, declaration: Node, container?: Node): boolean { @@ -1192,6 +1193,7 @@ namespace ts { } } } + return false; }); } } @@ -1208,10 +1210,10 @@ namespace ts { name: __String, meaning: SymbolFlags, nameNotFoundMessage: DiagnosticMessage | undefined, - nameArg: __String | Identifier, + nameArg: __String | Identifier | undefined, isUse: boolean, excludeGlobals = false, - suggestedNameNotFoundMessage?: DiagnosticMessage): Symbol { + suggestedNameNotFoundMessage?: DiagnosticMessage): Symbol | undefined { return resolveNameHelper(location, name, meaning, nameNotFoundMessage, nameArg, isUse, excludeGlobals, getSymbol, suggestedNameNotFoundMessage); } @@ -1219,17 +1221,17 @@ namespace ts { location: Node | undefined, name: __String, meaning: SymbolFlags, - nameNotFoundMessage: DiagnosticMessage, - nameArg: __String | Identifier, + nameNotFoundMessage: DiagnosticMessage | undefined, + nameArg: __String | Identifier | undefined, isUse: boolean, excludeGlobals: boolean, lookup: typeof getSymbol, - suggestedNameNotFoundMessage?: DiagnosticMessage): Symbol { + suggestedNameNotFoundMessage?: DiagnosticMessage): Symbol | undefined { const originalLocation = location; // needed for did-you-mean error reporting, which gathers candidates starting from the original location - let result: Symbol; - let lastLocation: Node; - let lastSelfReferenceLocation: Node; - let propertyWithInvalidInitializer: Node; + let result: Symbol | undefined; + let lastLocation: Node | undefined; + let lastSelfReferenceLocation: Node | undefined; + let propertyWithInvalidInitializer: Node | undefined; const errorLocation = location; let grandparent: Node; let isInExternalModule = false; @@ -1288,7 +1290,7 @@ namespace ts { isInExternalModule = true; // falls through case SyntaxKind.ModuleDeclaration: - const moduleExports = getSymbolOfNode(location).exports; + const moduleExports = getSymbolOfNode(location as ModuleDeclaration).exports!; if (location.kind === SyntaxKind.SourceFile || isAmbientModule(location)) { // It's an external module. First see if the module has an export default and if the local @@ -1325,7 +1327,7 @@ namespace ts { } break; case SyntaxKind.EnumDeclaration: - if (result = lookup(getSymbolOfNode(location).exports, name, meaning & SymbolFlags.EnumMember)) { + if (result = lookup(getSymbolOfNode(location)!.exports!, name, meaning & SymbolFlags.EnumMember)) { break loop; } break; @@ -1350,7 +1352,7 @@ namespace ts { case SyntaxKind.ClassDeclaration: case SyntaxKind.ClassExpression: case SyntaxKind.InterfaceDeclaration: - if (result = lookup(getMembersOfSymbol(getSymbolOfNode(location)), name, meaning & SymbolFlags.Type)) { + if (result = lookup(getMembersOfSymbol(getSymbolOfNode(location as ClassLikeDeclaration | InterfaceDeclaration)), name, meaning & SymbolFlags.Type)) { if (!isTypeParameterSymbolDeclaredInContainer(result, location)) { // ignore type parameters not declared in this container result = undefined; @@ -1377,7 +1379,7 @@ namespace ts { // The type parameters of a class are not in scope in the base class expression. if (lastLocation === (location).expression && (location.parent).token === SyntaxKind.ExtendsKeyword) { const container = location.parent.parent; - if (isClassLike(container) && (result = lookup(getSymbolOfNode(container).members, name, meaning & SymbolFlags.Type))) { + if (isClassLike(container) && (result = lookup(getSymbolOfNode(container).members!, name, meaning & SymbolFlags.Type))) { if (nameNotFoundMessage) { error(errorLocation, Diagnostics.Base_class_expressions_cannot_reference_class_type_parameters); } @@ -1397,7 +1399,7 @@ namespace ts { grandparent = location.parent.parent; if (isClassLike(grandparent) || grandparent.kind === SyntaxKind.InterfaceDeclaration) { // A reference to this grandparent's type parameters would be an error - if (result = lookup(getSymbolOfNode(grandparent).members, name, meaning & SymbolFlags.Type)) { + if (result = lookup(getSymbolOfNode(grandparent as ClassLikeDeclaration | InterfaceDeclaration).members!, name, meaning & SymbolFlags.Type)) { error(errorLocation, Diagnostics.A_computed_property_name_cannot_reference_a_type_parameter_from_its_containing_type); return undefined; } @@ -1469,7 +1471,7 @@ namespace ts { // If `result === lastSelfReferenceLocation.symbol`, that means that we are somewhere inside `lastSelfReferenceLocation` looking up a name, and resolving to `lastLocation` itself. // That means that this is a self-reference of `lastLocation`, and shouldn't count this when considering whether `lastLocation` is used. if (isUse && result && (!lastSelfReferenceLocation || result !== lastSelfReferenceLocation.symbol)) { - result.isReferenced |= meaning; + result.isReferenced! |= meaning; } if (!result) { @@ -1498,7 +1500,7 @@ namespace ts { if (!result) { if (nameNotFoundMessage) { if (!errorLocation || - !checkAndReportErrorForMissingPrefix(errorLocation, name, nameArg) && + !checkAndReportErrorForMissingPrefix(errorLocation, name, nameArg!) && // TODO: GH#18217 !checkAndReportErrorForExtendingInterface(errorLocation) && !checkAndReportErrorForUsingTypeAsNamespace(errorLocation, name, meaning) && !checkAndReportErrorForUsingTypeAsValue(errorLocation, name, meaning) && @@ -1507,11 +1509,11 @@ namespace ts { if (suggestedNameNotFoundMessage && suggestionCount < maximumSuggestionCount) { suggestion = getSuggestionForNonexistentSymbol(originalLocation, name, meaning); if (suggestion) { - error(errorLocation, suggestedNameNotFoundMessage, diagnosticName(nameArg), suggestion); + error(errorLocation, suggestedNameNotFoundMessage, diagnosticName(nameArg!), suggestion); } } if (!suggestion) { - error(errorLocation, nameNotFoundMessage, diagnosticName(nameArg)); + error(errorLocation, nameNotFoundMessage, diagnosticName(nameArg!)); } suggestionCount++; } @@ -1526,7 +1528,7 @@ namespace ts { // to a local variable in the constructor where the code will be emitted. const propertyName = (propertyWithInvalidInitializer).name; error(errorLocation, Diagnostics.Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor, - declarationNameToString(propertyName), diagnosticName(nameArg)); + declarationNameToString(propertyName), diagnosticName(nameArg!)); return undefined; } @@ -1551,10 +1553,10 @@ namespace ts { } // If we're in an external module, we can't reference value symbols created from UMD export declarations - if (result && isInExternalModule && (meaning & SymbolFlags.Value) === SymbolFlags.Value && !(originalLocation.flags & NodeFlags.JSDoc)) { + if (result && isInExternalModule && (meaning & SymbolFlags.Value) === SymbolFlags.Value && !(originalLocation!.flags & NodeFlags.JSDoc)) { const decls = result.declarations; if (decls && decls.length === 1 && decls[0].kind === SyntaxKind.NamespaceExportDeclaration) { - error(errorLocation, Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead, unescapeLeadingUnderscores(name)); + error(errorLocation!, Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead, unescapeLeadingUnderscores(name)); // TODO: GH#18217 } } } @@ -1584,7 +1586,7 @@ namespace ts { if (decl.kind === SyntaxKind.TypeParameter) { const parent = isJSDocTemplateTag(decl.parent) ? getJSDocHost(decl.parent) : decl.parent; if (parent === container) { - return !(isJSDocTemplateTag(decl.parent) && find((decl.parent.parent as JSDoc).tags, isJSDocTypeAlias)); + return !(isJSDocTemplateTag(decl.parent) && find((decl.parent.parent as JSDoc).tags!, isJSDocTypeAlias)); // TODO: GH#18217 } } } @@ -1616,7 +1618,7 @@ namespace ts { // No static member is present. // Check if we're in an instance method and look for a relevant instance member. if (location === container && !hasModifier(location, ModifierFlags.Static)) { - const instanceType = (getDeclaredTypeOfSymbol(classSymbol)).thisType; + const instanceType = (getDeclaredTypeOfSymbol(classSymbol)).thisType!; // TODO: GH#18217 if (getPropertyOfType(instanceType, name)) { error(errorLocation, Diagnostics.Cannot_find_name_0_Did_you_mean_the_instance_member_this_0, diagnosticName(nameArg)); return true; @@ -1632,11 +1634,11 @@ namespace ts { function checkAndReportErrorForExtendingInterface(errorLocation: Node): boolean { const expression = getEntityNameForExtendingInterface(errorLocation); - const isError = !!(expression && resolveEntityName(expression, SymbolFlags.Interface, /*ignoreErrors*/ true)); - if (isError) { + if (expression && resolveEntityName(expression, SymbolFlags.Interface, /*ignoreErrors*/ true)) { error(errorLocation, Diagnostics.Cannot_extend_an_interface_0_Did_you_mean_implements, getTextOfNode(expression)); + return true; } - return isError; + return false; } /** * Climbs up parents to an ExpressionWithTypeArguments, and returns its expression, @@ -1723,7 +1725,7 @@ namespace ts { // Block-scoped variables cannot be used before their definition const declaration = forEach(result.declarations, d => isBlockOrCatchScoped(d) || isClassLike(d) || (d.kind === SyntaxKind.EnumDeclaration) ? d : undefined); - Debug.assert(declaration !== undefined, "Declaration to checkResolvedBlockScopedVariable is undefined"); + if (declaration === undefined) return Debug.fail("Declaration to checkResolvedBlockScopedVariable is undefined"); if (!(declaration.flags & NodeFlags.Ambient) && !isBlockScopedNameDeclaredBeforeUse(declaration, errorLocation)) { if (result.flags & SymbolFlags.BlockScopedVariable) { @@ -1742,8 +1744,8 @@ namespace ts { * If at any point current node is equal to 'parent' node - return true. * Return false if 'stopAt' node is reached or isFunctionLike(current) === true. */ - function isSameScopeDescendentOf(initial: Node, parent: Node, stopAt: Node): boolean { - return parent && !!findAncestor(initial, n => n === stopAt || isFunctionLike(n) ? "quit" : n === parent); + function isSameScopeDescendentOf(initial: Node, parent: Node | undefined, stopAt: Node): boolean { + return !!parent && !!findAncestor(initial, n => n === stopAt || isFunctionLike(n) ? "quit" : n === parent); } function getAnyImportSyntax(node: Node): AnyImportSyntax | undefined { @@ -1765,7 +1767,7 @@ namespace ts { return find(symbol.declarations, isAliasSymbolDeclaration); } - function getTargetOfImportEqualsDeclaration(node: ImportEqualsDeclaration, dontResolveAlias: boolean): Symbol { + function getTargetOfImportEqualsDeclaration(node: ImportEqualsDeclaration, dontResolveAlias: boolean): Symbol | undefined { if (node.moduleReference.kind === SyntaxKind.ExternalModuleReference) { return resolveExternalModuleSymbol(resolveExternalModuleName(node, getExternalModuleImportEqualsDeclarationExpression(node))); } @@ -1773,10 +1775,10 @@ namespace ts { } function resolveExportByName(moduleSymbol: Symbol, name: __String, dontResolveAlias: boolean) { - const exportValue = moduleSymbol.exports.get(InternalSymbolName.ExportEquals); + const exportValue = moduleSymbol.exports!.get(InternalSymbolName.ExportEquals); return exportValue ? getPropertyOfType(getTypeOfSymbol(exportValue), name) - : resolveSymbol(moduleSymbol.exports.get(name), dontResolveAlias); + : resolveSymbol(moduleSymbol.exports!.get(name), dontResolveAlias); } function isSyntacticDefault(node: Node) { @@ -1814,11 +1816,11 @@ namespace ts { return !file.externalModuleIndicator && !resolveExportByName(moduleSymbol, escapeLeadingUnderscores("__esModule"), dontResolveAlias); } - function getTargetOfImportClause(node: ImportClause, dontResolveAlias: boolean): Symbol { + function getTargetOfImportClause(node: ImportClause, dontResolveAlias: boolean): Symbol | undefined { const moduleSymbol = resolveExternalModuleName(node, node.parent.moduleSpecifier); if (moduleSymbol) { - let exportDefaultSymbol: Symbol; + let exportDefaultSymbol: Symbol | undefined; if (isShorthandAmbientModuleSymbol(moduleSymbol)) { exportDefaultSymbol = moduleSymbol; } @@ -1839,7 +1841,7 @@ namespace ts { } } - function getTargetOfNamespaceImport(node: NamespaceImport, dontResolveAlias: boolean): Symbol { + function getTargetOfNamespaceImport(node: NamespaceImport, dontResolveAlias: boolean): Symbol | undefined { const moduleSpecifier = node.parent.parent.moduleSpecifier; return resolveESModuleSymbol(resolveExternalModuleName(node, moduleSpecifier), moduleSpecifier, dontResolveAlias); } @@ -1878,24 +1880,24 @@ namespace ts { return result; } - function getExportOfModule(symbol: Symbol, name: __String, dontResolveAlias: boolean): Symbol { + function getExportOfModule(symbol: Symbol, name: __String, dontResolveAlias: boolean): Symbol | undefined { if (symbol.flags & SymbolFlags.Module) { - return resolveSymbol(getExportsOfSymbol(symbol).get(name), dontResolveAlias); + return resolveSymbol(getExportsOfSymbol(symbol).get(name)!, dontResolveAlias); } } - function getPropertyOfVariable(symbol: Symbol, name: __String): Symbol { + function getPropertyOfVariable(symbol: Symbol, name: __String): Symbol | undefined { if (symbol.flags & SymbolFlags.Variable) { const typeAnnotation = (symbol.valueDeclaration).type; if (typeAnnotation) { - return resolveSymbol(getPropertyOfType(getTypeFromTypeNode(typeAnnotation), name)); + return resolveSymbol(getPropertyOfType(getTypeFromTypeNode(typeAnnotation), name)); // TODO: GH#18217 } } } - function getExternalModuleMember(node: ImportDeclaration | ExportDeclaration, specifier: ImportOrExportSpecifier, dontResolveAlias?: boolean): Symbol { - const moduleSymbol = resolveExternalModuleName(node, node.moduleSpecifier); - const targetSymbol = resolveESModuleSymbol(moduleSymbol, node.moduleSpecifier, dontResolveAlias); + function getExternalModuleMember(node: ImportDeclaration | ExportDeclaration, specifier: ImportOrExportSpecifier, dontResolveAlias = false): Symbol | undefined { + const moduleSymbol = resolveExternalModuleName(node, node.moduleSpecifier!)!; // TODO: GH#18217 + const targetSymbol = resolveESModuleSymbol(moduleSymbol, node.moduleSpecifier!, dontResolveAlias); if (targetSymbol) { const name = specifier.propertyName || specifier.name; if (name.escapedText) { @@ -1903,7 +1905,7 @@ namespace ts { return moduleSymbol; } - let symbolFromVariable: Symbol; + let symbolFromVariable: Symbol | undefined; // First check if module was specified with "export=". If so, get the member from the resolved type if (moduleSymbol && moduleSymbol.exports && moduleSymbol.exports.get(InternalSymbolName.ExportEquals)) { symbolFromVariable = getPropertyOfType(getTypeOfSymbol(targetSymbol), name.escapedText); @@ -1937,7 +1939,7 @@ namespace ts { } } - function getTargetOfImportSpecifier(node: ImportSpecifier, dontResolveAlias: boolean): Symbol { + function getTargetOfImportSpecifier(node: ImportSpecifier, dontResolveAlias: boolean): Symbol | undefined { return getExternalModuleMember(node.parent.parent.parent, node, dontResolveAlias); } @@ -1964,7 +1966,7 @@ namespace ts { return getNodeLinks(expression).resolvedSymbol; } - function getTargetOfAliasDeclaration(node: Declaration, dontRecursivelyResolve?: boolean): Symbol | undefined { + function getTargetOfAliasDeclaration(node: Declaration, dontRecursivelyResolve = false): Symbol | undefined { switch (node.kind) { case SyntaxKind.ImportEqualsDeclaration: return getTargetOfImportEqualsDeclaration(node, dontRecursivelyResolve); @@ -1981,6 +1983,8 @@ namespace ts { return getTargetOfExportAssignment((node), dontRecursivelyResolve); case SyntaxKind.NamespaceExportDeclaration: return getTargetOfNamespaceExportDeclaration(node, dontRecursivelyResolve); + default: + return Debug.fail(); } } @@ -1988,14 +1992,15 @@ namespace ts { * Indicates that a symbol is an alias that does not merge with a local declaration. * OR Is a JSContainer which may merge an alias with a local declaration */ - function isNonLocalAlias(symbol: Symbol, excludes = SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace) { + function isNonLocalAlias(symbol: Symbol | undefined, excludes = SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace): symbol is Symbol { if (!symbol) return false; - return (symbol.flags & (SymbolFlags.Alias | excludes)) === SymbolFlags.Alias || (symbol.flags & SymbolFlags.Alias && symbol.flags & SymbolFlags.JSContainer); + return (symbol.flags & (SymbolFlags.Alias | excludes)) === SymbolFlags.Alias || !!(symbol.flags & SymbolFlags.Alias && symbol.flags & SymbolFlags.JSContainer); } - function resolveSymbol(symbol: Symbol, dontResolveAlias?: boolean): Symbol { - const shouldResolve = !dontResolveAlias && isNonLocalAlias(symbol); - return shouldResolve ? resolveAlias(symbol) : symbol; + function resolveSymbol(symbol: Symbol, dontResolveAlias?: boolean): Symbol; + function resolveSymbol(symbol: Symbol | undefined, dontResolveAlias?: boolean): Symbol | undefined; + function resolveSymbol(symbol: Symbol | undefined, dontResolveAlias?: boolean): Symbol | undefined { + return !dontResolveAlias && isNonLocalAlias(symbol) ? resolveAlias(symbol) : symbol; } function resolveAlias(symbol: Symbol): Symbol { @@ -2004,7 +2009,7 @@ namespace ts { if (!links.target) { links.target = resolvingSymbol; const node = getDeclarationOfAliasSymbol(symbol); - Debug.assert(!!node); + if (!node) return Debug.fail(); const target = getTargetOfAliasDeclaration(node); if (links.target === resolvingSymbol) { links.target = target || unknownSymbol; @@ -2040,7 +2045,7 @@ namespace ts { if (!links.referenced) { links.referenced = true; const node = getDeclarationOfAliasSymbol(symbol); - Debug.assert(!!node); + if (!node) return Debug.fail(); if (node.kind === SyntaxKind.ExportAssignment) { // export default checkExpressionCached((node).expression); @@ -2057,7 +2062,7 @@ namespace ts { } // This function is only for imports with entity names - function getSymbolOfPartOfRightHandSideOfImportEquals(entityName: EntityName, dontResolveAlias?: boolean): Symbol { + function getSymbolOfPartOfRightHandSideOfImportEquals(entityName: EntityName, dontResolveAlias?: boolean): Symbol | undefined { // There are three things we might try to look for. In the following examples, // the search term is enclosed in |...|: // @@ -2092,7 +2097,7 @@ namespace ts { } const namespaceMeaning = SymbolFlags.Namespace | (isInJavaScriptFile(name) ? meaning & SymbolFlags.Value : 0); - let symbol: Symbol; + let symbol: Symbol | undefined; if (name.kind === SyntaxKind.Identifier) { const message = meaning === namespaceMeaning ? Diagnostics.Cannot_find_namespace_0 : Diagnostics.Cannot_find_name_0; const symbolFromJSPrototype = isInJavaScriptFile(name) ? resolveEntityNameFromJSSpecialAssignment(name, meaning) : undefined; @@ -2114,7 +2119,7 @@ namespace ts { if (isInJavaScriptFile(name)) { const initializer = getDeclaredJavascriptInitializer(namespace.valueDeclaration) || getAssignedJavascriptInitializer(namespace.valueDeclaration); if (initializer) { - namespace = getSymbolOfNode(initializer); + namespace = getSymbolOfNode(initializer)!; } // Currently, IIFEs may not have a symbol and we don't know about their contents. Give up in this case. if (!namespace) { @@ -2143,7 +2148,7 @@ namespace ts { } } else { - Debug.assertNever(name, "Unknown entity name kind."); + throw Debug.assertNever(name, "Unknown entity name kind."); } Debug.assert((getCheckFlags(symbol) & CheckFlags.Instantiated) === 0, "Should never get an instantiated symbol here."); return (symbol.flags & meaning) || dontResolveAlias ? symbol : resolveAlias(symbol); @@ -2174,7 +2179,7 @@ namespace ts { isBinaryExpression(host.expression) && getSpecialPropertyAssignmentKind(host.expression) === SpecialPropertyAssignmentKind.PrototypeProperty) { const symbol = getSymbolOfNode(host.expression.left); - return symbol && symbol.parent.valueDeclaration; + return symbol && symbol.parent!.valueDeclaration; } const sig = getHostSignatureFromJSDocHost(host); if (sig) { @@ -2183,17 +2188,17 @@ namespace ts { } } - function resolveExternalModuleName(location: Node, moduleReferenceExpression: Expression): Symbol { + function resolveExternalModuleName(location: Node, moduleReferenceExpression: Expression): Symbol | undefined { return resolveExternalModuleNameWorker(location, moduleReferenceExpression, Diagnostics.Cannot_find_module_0); } - function resolveExternalModuleNameWorker(location: Node, moduleReferenceExpression: Expression, moduleNotFoundError: DiagnosticMessage, isForAugmentation = false): Symbol { + function resolveExternalModuleNameWorker(location: Node, moduleReferenceExpression: Expression, moduleNotFoundError: DiagnosticMessage | undefined, isForAugmentation = false): Symbol | undefined { return isStringLiteralLike(moduleReferenceExpression) ? resolveExternalModule(location, moduleReferenceExpression.text, moduleNotFoundError, moduleReferenceExpression, isForAugmentation) : undefined; } - function resolveExternalModule(location: Node, moduleReference: string, moduleNotFoundError: DiagnosticMessage, errorNode: Node, isForAugmentation = false): Symbol { + function resolveExternalModule(location: Node, moduleReference: string, moduleNotFoundError: DiagnosticMessage | undefined, errorNode: Node, isForAugmentation = false): Symbol | undefined { if (moduleReference === undefined) { return; } @@ -2209,7 +2214,7 @@ namespace ts { return ambientModule; } const currentSourceFile = getSourceFileOfNode(location); - const resolvedModule = getResolvedModule(currentSourceFile, moduleReference); + const resolvedModule = getResolvedModule(currentSourceFile, moduleReference)!; // TODO: GH#18217 const resolutionDiagnostic = resolvedModule && getResolutionDiagnostic(compilerOptions, resolvedModule); const sourceFile = resolvedModule && !resolutionDiagnostic && host.getSourceFile(resolvedModule.resolvedFileName); if (sourceFile) { @@ -2295,12 +2300,14 @@ namespace ts { // An external module with an 'export =' declaration resolves to the target of the 'export =' declaration, // and an external module with no 'export =' declaration resolves to the module itself. + function resolveExternalModuleSymbol(moduleSymbol: Symbol, dontResolveAlias?: boolean): Symbol; + function resolveExternalModuleSymbol(moduleSymbol: Symbol | undefined, dontResolveAlias?: boolean): Symbol | undefined; function resolveExternalModuleSymbol(moduleSymbol: Symbol, dontResolveAlias?: boolean): Symbol { - return moduleSymbol && getMergedSymbol(getCommonJsExportEquals(resolveSymbol(moduleSymbol.exports.get(InternalSymbolName.ExportEquals), dontResolveAlias), moduleSymbol)) || moduleSymbol; + return moduleSymbol && getMergedSymbol(getCommonJsExportEquals(resolveSymbol(moduleSymbol.exports!.get(InternalSymbolName.ExportEquals), dontResolveAlias), moduleSymbol)) || moduleSymbol; } - function getCommonJsExportEquals(exported: Symbol, moduleSymbol: Symbol): Symbol { - if (!exported || moduleSymbol.exports.size === 1) { + function getCommonJsExportEquals(exported: Symbol | undefined, moduleSymbol: Symbol): Symbol | undefined { + if (!exported || moduleSymbol.exports!.size === 1) { return exported; } const merged = cloneSymbol(exported); @@ -2308,15 +2315,15 @@ namespace ts { merged.flags = merged.flags | SymbolFlags.ValueModule; merged.exports = createSymbolTable(); } - moduleSymbol.exports.forEach((s, name) => { + moduleSymbol.exports!.forEach((s, name) => { if (name === InternalSymbolName.ExportEquals) return; - if (!merged.exports.has(name)) { - merged.exports.set(name, s); + if (!merged.exports!.has(name)) { + merged.exports!.set(name, s); } else { - const ms = cloneSymbol(merged.exports.get(name)); + const ms = cloneSymbol(merged.exports!.get(name)!); mergeSymbol(ms, s); - merged.exports.set(name, ms); + merged.exports!.set(name, ms); } }); return merged; @@ -2325,11 +2332,11 @@ namespace ts { // An external module with an 'export =' declaration may be referenced as an ES6 module provided the 'export =' // references a symbol that is at least declared as a module or a variable. The target of the 'export =' may // combine other declarations with the module or variable (e.g. a class/module, function/module, interface/variable). - function resolveESModuleSymbol(moduleSymbol: Symbol, referencingLocation: Node, dontResolveAlias: boolean): Symbol { + function resolveESModuleSymbol(moduleSymbol: Symbol | undefined, referencingLocation: Node, dontResolveAlias: boolean): Symbol | undefined { const symbol = resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias); if (!dontResolveAlias && symbol) { if (!(symbol.flags & (SymbolFlags.Module | SymbolFlags.Variable))) { - error(referencingLocation, Diagnostics.Module_0_resolves_to_a_non_module_entity_and_cannot_be_imported_using_this_construct, symbolToString(moduleSymbol)); + error(referencingLocation, Diagnostics.Module_0_resolves_to_a_non_module_entity_and_cannot_be_imported_using_this_construct, symbolToString(moduleSymbol!)); return symbol; } if (compilerOptions.esModuleInterop) { @@ -2344,7 +2351,7 @@ namespace ts { sigs = getSignaturesOfStructuredType(type, SignatureKind.Construct); } if (sigs && sigs.length) { - const moduleType = getTypeWithSyntheticDefaultImportType(type, symbol, moduleSymbol); + const moduleType = getTypeWithSyntheticDefaultImportType(type, symbol, moduleSymbol!); // Create a new symbol which has the module's type less the call and construct signatures const result = createSymbol(symbol.flags, symbol.escapedName); result.declarations = symbol.declarations ? symbol.declarations.slice() : []; @@ -2366,7 +2373,7 @@ namespace ts { } function hasExportAssignmentSymbol(moduleSymbol: Symbol): boolean { - return moduleSymbol.exports.get(InternalSymbolName.ExportEquals) !== undefined; + return moduleSymbol.exports!.get(InternalSymbolName.ExportEquals) !== undefined; } function getExportsOfModuleAsArray(moduleSymbol: Symbol): Symbol[] { @@ -2436,12 +2443,12 @@ namespace ts { target.set(id, sourceSymbol); if (lookupTable && exportNode) { lookupTable.set(id, { - specifierText: getTextOfNode(exportNode.moduleSpecifier) + specifierText: getTextOfNode(exportNode.moduleSpecifier!) } as ExportCollisionTracker); } } else if (lookupTable && exportNode && targetSymbol && resolveSymbol(targetSymbol) !== resolveSymbol(sourceSymbol)) { - const collisionTracker = lookupTable.get(id); + const collisionTracker = lookupTable.get(id)!; if (!collisionTracker.exportsWithDuplicate) { collisionTracker.exportsWithDuplicate = [exportNode]; } @@ -2462,18 +2469,18 @@ namespace ts { // The ES6 spec permits export * declarations in a module to circularly reference the module itself. For example, // module 'a' can 'export * from "b"' and 'b' can 'export * from "a"' without error. - function visit(symbol: Symbol): SymbolTable { + function visit(symbol: Symbol | undefined): SymbolTable | undefined { if (!(symbol && symbol.flags & SymbolFlags.HasExports && pushIfUnique(visitedSymbols, symbol))) { return; } - const symbols = cloneMap(symbol.exports); + const symbols = cloneMap(symbol.exports!); // All export * declarations are collected in an __export symbol by the binder - const exportStars = symbol.exports.get(InternalSymbolName.ExportStar); + const exportStars = symbol.exports!.get(InternalSymbolName.ExportStar); if (exportStars) { const nestedSymbols = createSymbolTable(); const lookupTable = createMap() as ExportCollisionTrackerTable; for (const node of exportStars.declarations) { - const resolvedModule = resolveExternalModuleName(node, (node as ExportDeclaration).moduleSpecifier); + const resolvedModule = resolveExternalModuleName(node, (node as ExportDeclaration).moduleSpecifier!); const exportedSymbols = visit(resolvedModule); extendExportSymbols( nestedSymbols, @@ -2491,7 +2498,7 @@ namespace ts { diagnostics.add(createDiagnosticForNode( node, Diagnostics.Module_0_has_already_exported_a_member_named_1_Consider_explicitly_re_exporting_to_resolve_the_ambiguity, - lookupTable.get(id).specifierText, + lookupTable.get(id)!.specifierText, unescapeLeadingUnderscores(id) )); } @@ -2502,20 +2509,26 @@ namespace ts { } } - function getMergedSymbol(symbol: Symbol): Symbol { + function getMergedSymbol(symbol: Symbol): Symbol; + function getMergedSymbol(symbol: Symbol | undefined): Symbol | undefined; + function getMergedSymbol(symbol: Symbol | undefined): Symbol | undefined { let merged: Symbol; return symbol && symbol.mergeId && (merged = mergedSymbols[symbol.mergeId]) ? merged : symbol; } - function getSymbolOfNode(node: Node): Symbol { + function getSymbolOfNode(node: Declaration): Symbol; + function getSymbolOfNode(node: Node): Symbol | undefined; + function getSymbolOfNode(node: Node): Symbol | undefined { return getMergedSymbol(node.symbol && getLateBoundSymbol(node.symbol)); } - function getParentOfSymbol(symbol: Symbol): Symbol { + function getParentOfSymbol(symbol: Symbol): Symbol | undefined { return getMergedSymbol(symbol.parent && getLateBoundSymbol(symbol.parent)); } - function getExportSymbolOfValueSymbolIfExported(symbol: Symbol): Symbol { + function getExportSymbolOfValueSymbolIfExported(symbol: Symbol): Symbol; + function getExportSymbolOfValueSymbolIfExported(symbol: Symbol | undefined): Symbol | undefined; + function getExportSymbolOfValueSymbolIfExported(symbol: Symbol | undefined): Symbol | undefined { return symbol && (symbol.flags & SymbolFlags.ExportValue) !== 0 ? getMergedSymbol(symbol.exportSymbol) : symbol; @@ -2525,7 +2538,7 @@ namespace ts { return !!(symbol.flags & SymbolFlags.Value || symbol.flags & SymbolFlags.Alias && resolveAlias(symbol).flags & SymbolFlags.Value); } - function findConstructorDeclaration(node: ClassLikeDeclaration): ConstructorDeclaration { + function findConstructorDeclaration(node: ClassLikeDeclaration): ConstructorDeclaration | undefined { const members = node.members; for (const member of members) { if (member.kind === SyntaxKind.Constructor && nodeIsPresent((member).body)) { @@ -2557,7 +2570,7 @@ namespace ts { function createObjectType(objectFlags: ObjectFlags, symbol?: Symbol): ObjectType { const type = createType(TypeFlags.Object); type.objectFlags = objectFlags; - type.symbol = symbol; + type.symbol = symbol!; return type; } @@ -2577,7 +2590,7 @@ namespace ts { } function getNamedMembers(members: SymbolTable): Symbol[] { - let result: Symbol[]; + let result: Symbol[] | undefined; members.forEach((symbol, id) => { if (!isReservedMemberName(id)) { if (!result) result = []; @@ -2589,7 +2602,7 @@ namespace ts { return result || emptyArray; } - function setStructuredTypeMembers(type: StructuredType, members: SymbolTable, callSignatures: Signature[], constructSignatures: Signature[], stringIndexInfo: IndexInfo, numberIndexInfo: IndexInfo): ResolvedType { + function setStructuredTypeMembers(type: StructuredType, members: SymbolTable, callSignatures: Signature[], constructSignatures: Signature[], stringIndexInfo: IndexInfo | undefined, numberIndexInfo: IndexInfo | undefined): ResolvedType { (type).members = members; (type).properties = getNamedMembers(members); (type).callSignatures = callSignatures; @@ -2599,12 +2612,12 @@ namespace ts { return type; } - function createAnonymousType(symbol: Symbol, members: SymbolTable, callSignatures: Signature[], constructSignatures: Signature[], stringIndexInfo: IndexInfo, numberIndexInfo: IndexInfo): ResolvedType { + function createAnonymousType(symbol: Symbol | undefined, members: SymbolTable, callSignatures: Signature[], constructSignatures: Signature[], stringIndexInfo: IndexInfo | undefined, numberIndexInfo: IndexInfo | undefined): ResolvedType { return setStructuredTypeMembers(createObjectType(ObjectFlags.Anonymous, symbol), members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); } - function forEachSymbolTableInScope(enclosingDeclaration: Node, callback: (symbolTable: SymbolTable) => T): T { + function forEachSymbolTableInScope(enclosingDeclaration: Node | undefined, callback: (symbolTable: SymbolTable) => T): T { let result: T; for (let location = enclosingDeclaration; location; location = location.parent) { // Locals of a source file are not in scope (because they get merged into the global symbol table) @@ -2620,7 +2633,7 @@ namespace ts { } // falls through case SyntaxKind.ModuleDeclaration: - if (result = callback(getSymbolOfNode(location).exports)) { + if (result = callback(getSymbolOfNode(location as ModuleDeclaration).exports!)) { return result; } break; @@ -2635,7 +2648,7 @@ namespace ts { return rightMeaning === SymbolFlags.Value ? SymbolFlags.Value : SymbolFlags.Namespace; } - function getAccessibleSymbolChain(symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags, useOnlyExternalAliasing: boolean, visitedSymbolTablesMap: Map = createMap()): Symbol[] | undefined { + function getAccessibleSymbolChain(symbol: Symbol | undefined, enclosingDeclaration: Node | undefined, meaning: SymbolFlags, useOnlyExternalAliasing: boolean, visitedSymbolTablesMap: Map = createMap()): Symbol[] | undefined { if (!(symbol && !isPropertyOrMethodDeclarationSymbol(symbol))) { return undefined; } @@ -2651,12 +2664,12 @@ namespace ts { * @param {ignoreQualification} boolean Set when a symbol is being looked for through the exports of another symbol (meaning we have a route to qualify it already) */ function getAccessibleSymbolChainFromSymbolTable(symbols: SymbolTable, ignoreQualification?: boolean): Symbol[] | undefined { - if (!pushIfUnique(visitedSymbolTables, symbols)) { + if (!pushIfUnique(visitedSymbolTables!, symbols)) { return undefined; } const result = trySymbolTable(symbols, ignoreQualification); - visitedSymbolTables.pop(); + visitedSymbolTables!.pop(); return result; } @@ -2676,10 +2689,10 @@ namespace ts { (ignoreQualification || canQualifySymbol(symbolFromSymbolTable, meaning)); } - function trySymbolTable(symbols: SymbolTable, ignoreQualification: boolean | undefined) { + function trySymbolTable(symbols: SymbolTable, ignoreQualification: boolean | undefined): Symbol[] | undefined { // If symbol is directly available by its name in the symbol table - if (isAccessible(symbols.get(symbol.escapedName), /*resolvedAliasSymbol*/ undefined, ignoreQualification)) { - return [symbol]; + if (isAccessible(symbols.get(symbol!.escapedName)!, /*resolvedAliasSymbol*/ undefined, ignoreQualification)) { + return [symbol!]; } // Check if symbol is any of the alias @@ -2704,9 +2717,9 @@ namespace ts { return [symbolFromSymbolTable].concat(accessibleSymbolsFromExports); } } - if (symbolFromSymbolTable.escapedName === symbol.escapedName && symbolFromSymbolTable.exportSymbol) { + if (symbolFromSymbolTable.escapedName === symbol!.escapedName && symbolFromSymbolTable.exportSymbol) { if (isAccessible(getMergedSymbol(symbolFromSymbolTable.exportSymbol), /*aliasSymbol*/ undefined, ignoreQualification)) { - return [symbol]; + return [symbol!]; } } }); @@ -2760,7 +2773,7 @@ namespace ts { return false; } - function isTypeSymbolAccessible(typeSymbol: Symbol, enclosingDeclaration: Node): boolean { + function isTypeSymbolAccessible(typeSymbol: Symbol, enclosingDeclaration: Node | undefined): boolean { const access = isSymbolAccessible(typeSymbol, enclosingDeclaration, SymbolFlags.Type, /*shouldComputeAliasesToMakeVisible*/ false); return access.accessibility === SymbolAccessibility.Accessible; } @@ -2778,7 +2791,7 @@ namespace ts { * @param meaning a SymbolFlags to check if such meaning of the symbol is accessible * @param shouldComputeAliasToMakeVisible a boolean value to indicate whether to return aliases to be mark visible in case the symbol is accessible */ - function isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags, shouldComputeAliasesToMakeVisible: boolean): SymbolAccessibilityResult { + function isSymbolAccessible(symbol: Symbol | undefined, enclosingDeclaration: Node | undefined, meaning: SymbolFlags, shouldComputeAliasesToMakeVisible: boolean): SymbolAccessibilityResult { if (symbol && enclosingDeclaration) { const initialSymbol = symbol; let meaningToLook = meaning; @@ -2859,8 +2872,8 @@ namespace ts { return isModuleWithStringLiteralName(declaration) || (declaration.kind === SyntaxKind.SourceFile && isExternalOrCommonJsModule(declaration)); } - function hasVisibleDeclarations(symbol: Symbol, shouldComputeAliasToMakeVisible: boolean): SymbolVisibilityResult { - let aliasesToMakeVisible: LateVisibilityPaintedStatement[]; + function hasVisibleDeclarations(symbol: Symbol, shouldComputeAliasToMakeVisible: boolean): SymbolVisibilityResult | undefined { + let aliasesToMakeVisible: LateVisibilityPaintedStatement[] | undefined; if (forEach(symbol.declarations, declaration => !getIsDeclarationVisible(declaration))) { return undefined; } @@ -2953,7 +2966,7 @@ namespace ts { return writer ? symbolToStringWorker(writer).getText() : usingSingleLineStringWriter(symbolToStringWorker); function symbolToStringWorker(writer: EmitTextWriter) { - const entity = builder(symbol, meaning, enclosingDeclaration, nodeFlags); + const entity = builder(symbol, meaning!, enclosingDeclaration, nodeFlags)!; // TODO: GH#18217 const printer = createPrinter({ removeComments: true }); const sourceFile = enclosingDeclaration && getSourceFileOfNode(enclosingDeclaration); printer.writeNode(EmitHint.Unspecified, entity, /*sourceFile*/ sourceFile, writer); @@ -2961,7 +2974,7 @@ namespace ts { } } - function signatureToString(signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind, writer?: EmitTextWriter): string { + function signatureToString(signature: Signature, enclosingDeclaration?: Node, flags = TypeFormatFlags.None, kind?: SignatureKind, writer?: EmitTextWriter): string { return writer ? signatureToStringWorker(writer).getText() : usingSingleLineStringWriter(signatureToStringWorker); function signatureToStringWorker(writer: EmitTextWriter) { @@ -2975,14 +2988,14 @@ namespace ts { const sig = nodeBuilder.signatureToSignatureDeclaration(signature, sigOutput, enclosingDeclaration, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors | NodeBuilderFlags.WriteTypeParametersInQualifiedName); const printer = createPrinter({ removeComments: true, omitTrailingSemicolon: true }); const sourceFile = enclosingDeclaration && getSourceFileOfNode(enclosingDeclaration); - printer.writeNode(EmitHint.Unspecified, sig, /*sourceFile*/ sourceFile, writer); + printer.writeNode(EmitHint.Unspecified, sig!, /*sourceFile*/ sourceFile, writer); // TODO: GH#18217 return writer; } } function typeToString(type: Type, enclosingDeclaration?: Node, flags: TypeFormatFlags = TypeFormatFlags.AllowUniqueESSymbolType, writer: EmitTextWriter = createTextWriter("")): string { const typeNode = nodeBuilder.typeToTypeNode(type, enclosingDeclaration, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors, writer); - Debug.assert(typeNode !== undefined, "should always get typenode"); + if (typeNode === undefined) return Debug.fail("should always get typenode"); const options = { removeComments: true }; const printer = createPrinter(options); const sourceFile = enclosingDeclaration && getSourceFileOfNode(enclosingDeclaration); @@ -2996,7 +3009,7 @@ namespace ts { return result; } - function toNodeBuilderFlags(flags?: TypeFormatFlags): NodeBuilderFlags { + function toNodeBuilderFlags(flags = TypeFormatFlags.None): NodeBuilderFlags { return flags & TypeFormatFlags.NodeBuilderFlagsMask; } @@ -3014,7 +3027,7 @@ namespace ts { const context = createNodeBuilderContext(enclosingDeclaration, flags, tracker); const resultingNode = indexInfoToIndexSignatureDeclarationHelper(indexInfo, kind, context); const result = context.encounteredError ? undefined : resultingNode; - return result; + return result!; // TODO: GH#18217 }, signatureToSignatureDeclaration: (signature: Signature, kind: SyntaxKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => { Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & NodeFlags.Synthesized) === 0); @@ -3063,7 +3076,7 @@ namespace ts { function createNodeBuilderContext(enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined, tracker: SymbolTracker | undefined): NodeBuilderContext { return { enclosingDeclaration, - flags, + flags: flags || NodeBuilderFlags.None, tracker: tracker && tracker.trackSymbol ? tracker : { trackSymbol: noop }, encounteredError: false, visitedSymbols: undefined, @@ -3080,7 +3093,7 @@ namespace ts { if (!type) { context.encounteredError = true; - return undefined; + return undefined!; // TODO: GH#18217 } if (type.flags & TypeFlags.Any) { @@ -3096,7 +3109,7 @@ namespace ts { return createKeywordTypeNode(SyntaxKind.BooleanKeyword); } if (type.flags & TypeFlags.EnumLiteral && !(type.flags & TypeFlags.Union)) { - const parentSymbol = getParentOfSymbol(type.symbol); + const parentSymbol = getParentOfSymbol(type.symbol)!; const parentName = symbolToName(parentSymbol, context, SymbolFlags.Type, /*expectsIdentifier*/ false); const enumLiteralName = getDeclaredTypeOfSymbol(parentSymbol) === type ? parentName : createQualifiedName(parentName, symbolName(type.symbol)); return createTypeReferenceNode(enumLiteralName, /*typeArguments*/ undefined); @@ -3116,7 +3129,7 @@ namespace ts { } if (type.flags & TypeFlags.UniqueESSymbol) { if (!(context.flags & NodeBuilderFlags.AllowUniqueESSymbolType)) { - if (isValueSymbolAccessible(type.symbol, context.enclosingDeclaration)) { + if (isValueSymbolAccessible(type.symbol, context.enclosingDeclaration!)) { return symbolToTypeNode(type.symbol, context, SymbolFlags.Value); } if (context.tracker.reportInaccessibleUniqueSymbolError) { @@ -3194,7 +3207,7 @@ namespace ts { if (!context.encounteredError && !(context.flags & NodeBuilderFlags.AllowEmptyUnionOrIntersection)) { context.encounteredError = true; } - return undefined; + return undefined!; // TODO: GH#18217 } } if (objectFlags & (ObjectFlags.Anonymous | ObjectFlags.Mapped)) { @@ -3226,7 +3239,7 @@ namespace ts { return typeToTypeNodeHelper((type).typeVariable, context); } - Debug.fail("Should be unreachable."); + return Debug.fail("Should be unreachable."); function createMappedTypeNodeFromType(type: MappedType) { Debug.assert(!!(type.flags & TypeFlags.Object)); @@ -3303,7 +3316,7 @@ namespace ts { if (isStaticMethodSymbol || isNonLocalFunctionSymbol) { // typeof is allowed only for static/non local functions return (!!(context.flags & NodeBuilderFlags.UseTypeOfFunction) || (context.visitedSymbols && context.visitedSymbols.has(id))) && // it is type of the symbol uses itself recursively - (!(context.flags & NodeBuilderFlags.UseStructuralFallback) || isValueSymbolAccessible(symbol, context.enclosingDeclaration)); // And the build is going to succeed without visibility error or there is no structural fallback allowed + (!(context.flags & NodeBuilderFlags.UseStructuralFallback) || isValueSymbolAccessible(symbol, context.enclosingDeclaration!)); // TODO: GH#18217 // And the build is going to succeed without visibility error or there is no structural fallback allowed } } } @@ -3363,25 +3376,25 @@ namespace ts { return createTupleTypeNode([]); } context.encounteredError = true; - return undefined; + return undefined!; // TODO: GH#18217 } else if (context.flags & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral && type.symbol.valueDeclaration && isClassLike(type.symbol.valueDeclaration) && - !isValueSymbolAccessible(type.symbol, context.enclosingDeclaration) + !isValueSymbolAccessible(type.symbol, context.enclosingDeclaration!) ) { return createAnonymousTypeNode(type); } else { const outerTypeParameters = type.target.outerTypeParameters; let i = 0; - let resultType: TypeReferenceNode | ImportTypeNode; + let resultType: TypeReferenceNode | ImportTypeNode | undefined; if (outerTypeParameters) { const length = outerTypeParameters.length; while (i < length) { // Find group of type arguments for type parameters with the same declaring container. const start = i; - const parent = getParentSymbolOfTypeParameter(outerTypeParameters[i]); + const parent = getParentSymbolOfTypeParameter(outerTypeParameters[i])!; do { i++; } while (i < length && getParentSymbolOfTypeParameter(outerTypeParameters[i]) === parent); @@ -3451,7 +3464,7 @@ namespace ts { return ids; } - function createTypeNodesFromResolvedType(resolvedType: ResolvedType): TypeElement[] { + function createTypeNodesFromResolvedType(resolvedType: ResolvedType): TypeElement[] | undefined { const typeElements: TypeElement[] = []; for (const signature of resolvedType.callSignatures) { typeElements.push(signatureToSignatureDeclarationHelper(signature, SyntaxKind.CallSignature, context)); @@ -3488,7 +3501,7 @@ namespace ts { const saveEnclosingDeclaration = context.enclosingDeclaration; context.enclosingDeclaration = undefined; if (getCheckFlags(propertySymbol) & CheckFlags.Late) { - const decl = firstOrUndefined(propertySymbol.declarations); + const decl = first(propertySymbol.declarations); const name = hasLateBindableName(decl) && resolveEntityName(decl.name.expression, SymbolFlags.Value); if (name && context.tracker.trackSymbol) { context.tracker.trackSymbol(name, saveEnclosingDeclaration, SymbolFlags.Value); @@ -3534,7 +3547,7 @@ namespace ts { } } - function mapToTypeNodes(types: Type[], context: NodeBuilderContext): TypeNode[] { + function mapToTypeNodes(types: Type[] | undefined, context: NodeBuilderContext): TypeNode[] | undefined { if (some(types)) { const result = []; for (const type of types) { @@ -3560,7 +3573,7 @@ namespace ts { /*questionToken*/ undefined, indexerTypeNode, /*initializer*/ undefined); - const typeNode = indexInfo.type ? typeToTypeNodeHelper(indexInfo.type, context) : typeToTypeNodeHelper(anyType, context); + const typeNode = typeToTypeNodeHelper(indexInfo.type || anyType, context); if (!indexInfo.type && !(context.flags & NodeBuilderFlags.AllowEmptyIndexInfoType)) { context.encounteredError = true; } @@ -3572,10 +3585,10 @@ namespace ts { } function signatureToSignatureDeclarationHelper(signature: Signature, kind: SyntaxKind, context: NodeBuilderContext): SignatureDeclaration { - let typeParameters: TypeParameterDeclaration[]; - let typeArguments: TypeNode[]; + let typeParameters: TypeParameterDeclaration[] | undefined; + let typeArguments: TypeNode[] | undefined; if (context.flags & NodeBuilderFlags.WriteTypeArgumentsOfSignature && signature.target && signature.mapper && signature.target.typeParameters) { - typeArguments = signature.target.typeParameters.map(parameter => typeToTypeNodeHelper(instantiateType(parameter, signature.mapper), context)); + typeArguments = signature.target.typeParameters.map(parameter => typeToTypeNodeHelper(instantiateType(parameter, signature.mapper!), context)); } else { typeParameters = signature.typeParameters && signature.typeParameters.map(parameter => typeParameterToDeclaration(parameter, context)); @@ -3586,7 +3599,8 @@ namespace ts { const thisParameter = symbolToParameterDeclaration(signature.thisParameter, context); parameters.unshift(thisParameter); } - let returnTypeNode: TypeNode; + + let returnTypeNode: TypeNode | undefined; const typePredicate = getTypePredicateOfSignature(signature); if (typePredicate) { const parameterName = typePredicate.kind === TypePredicateKind.Identifier ? @@ -3637,7 +3651,7 @@ namespace ts { } function symbolToParameterDeclaration(parameterSymbol: Symbol, context: NodeBuilderContext, preserveModifierFlags?: boolean): ParameterDeclaration { - let parameterDeclaration: ParameterDeclaration | JSDocParameterTag = getDeclarationOfKind(parameterSymbol, SyntaxKind.Parameter); + let parameterDeclaration: ParameterDeclaration | JSDocParameterTag | undefined = getDeclarationOfKind(parameterSymbol, SyntaxKind.Parameter); if (!parameterDeclaration && !isTransientSymbol(parameterSymbol)) { parameterDeclaration = getDeclarationOfKind(parameterSymbol, SyntaxKind.JSDocParameterTag); } @@ -3648,7 +3662,7 @@ namespace ts { } const parameterTypeNode = typeToTypeNodeHelper(parameterType, context); - const modifiers = !(context.flags & NodeBuilderFlags.OmitParameterModifiers) && preserveModifierFlags && parameterDeclaration && parameterDeclaration.modifiers && parameterDeclaration.modifiers.map(getSynthesizedClone); + const modifiers = !(context.flags & NodeBuilderFlags.OmitParameterModifiers) && preserveModifierFlags && parameterDeclaration && parameterDeclaration.modifiers ? parameterDeclaration.modifiers.map(getSynthesizedClone) : undefined; const isRest = parameterDeclaration ? isRestParameter(parameterDeclaration) : (parameterSymbol as TransientSymbol).isRestParameter; const dotDotDotToken = isRest ? createToken(SyntaxKind.DotDotDotToken) : undefined; const name = parameterDeclaration @@ -3672,7 +3686,7 @@ namespace ts { function cloneBindingName(node: BindingName): BindingName { return elideInitializerAndSetEmitFlags(node); function elideInitializerAndSetEmitFlags(node: Node): Node { - const visited = visitEachChild(node, elideInitializerAndSetEmitFlags, nullTransformationContext, /*nodesVisitor*/ undefined, elideInitializerAndSetEmitFlags); + const visited = visitEachChild(node, elideInitializerAndSetEmitFlags, nullTransformationContext, /*nodesVisitor*/ undefined, elideInitializerAndSetEmitFlags)!; const clone = nodeIsSynthesized(visited) ? visited : getSynthesizedClone(visited); if (clone.kind === SyntaxKind.BindingElement) { (clone).initializer = undefined; @@ -3683,12 +3697,12 @@ namespace ts { } function lookupSymbolChain(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags, yieldModuleSymbol?: boolean) { - context.tracker.trackSymbol(symbol, context.enclosingDeclaration, meaning); + context.tracker.trackSymbol!(symbol, context.enclosingDeclaration, meaning); // TODO: GH#18217 // Try to get qualified name if the symbol is not a type parameter and there is an enclosing declaration. let chain: Symbol[]; const isTypeParameter = symbol.flags & SymbolFlags.TypeParameter; if (!isTypeParameter && (context.enclosingDeclaration || context.flags & NodeBuilderFlags.UseFullyQualifiedType)) { - chain = getSymbolChain(symbol, meaning, /*endOfChain*/ true); + chain = Debug.assertDefined(getSymbolChain(symbol, meaning, /*endOfChain*/ true)); Debug.assert(chain && chain.length > 0); } else { @@ -3699,7 +3713,7 @@ namespace ts { /** @param endOfChain Set to false for recursive calls; non-recursive calls should always output something. */ function getSymbolChain(symbol: Symbol, meaning: SymbolFlags, endOfChain: boolean): Symbol[] | undefined { let accessibleSymbolChain = getAccessibleSymbolChain(symbol, context.enclosingDeclaration, meaning, !!(context.flags & NodeBuilderFlags.UseOnlyExternalAliasing)); - let parentSymbol: Symbol; + let parentSymbol: Symbol | undefined; if (!accessibleSymbolChain || needsQualification(accessibleSymbolChain[0], context.enclosingDeclaration, accessibleSymbolChain.length === 1 ? meaning : getQualifiedLeftMeaning(meaning))) { @@ -3751,7 +3765,7 @@ namespace ts { const params = getTypeParametersOfClassOrInterface( parentSymbol.flags & SymbolFlags.Alias ? resolveAlias(parentSymbol) : parentSymbol ); - typeParameterNodes = mapToTypeNodes(map(params, (nextSymbol as TransientSymbol).mapper), context); + typeParameterNodes = mapToTypeNodes(map(params, (nextSymbol as TransientSymbol).mapper!), context); } else { typeParameterNodes = typeParametersToTypeParameterDeclarations(symbol, context); @@ -3785,7 +3799,7 @@ namespace ts { const lit = createLiteralTypeNode(createLiteral(rootName.substring(1, rootName.length - 1))); if (!nonRootParts || isEntityName(nonRootParts)) { if (nonRootParts) { - const lastId = isIdentifier(nonRootParts) ? nonRootParts : (nonRootParts as QualifiedName).right; + const lastId = isIdentifier(nonRootParts) ? nonRootParts : nonRootParts.right; lastId.typeArguments = undefined; } return createImportTypeNode(lit, nonRootParts as EntityName, typeParameterNodes as ReadonlyArray, isTypeOf); @@ -3909,7 +3923,7 @@ namespace ts { symbolName = symbolName.substring(1, symbolName.length - 1); firstChar = symbolName.charCodeAt(0); } - let expression: Expression; + let expression: Expression | undefined; if (isSingleOrDoubleQuote(firstChar)) { expression = createLiteral(symbolName.substring(1, symbolName.length - 1).replace(/\\./g, s => s.substring(1))); (expression as StringLiteral).singleQuote = firstChar === CharacterCodes.singleQuote; @@ -3933,7 +3947,7 @@ namespace ts { function typePredicateToStringWorker(writer: EmitTextWriter) { const predicate = createTypePredicateNode( typePredicate.kind === TypePredicateKind.Identifier ? createIdentifier(typePredicate.parameterName) : createThisTypeNode(), - nodeBuilder.typeToTypeNode(typePredicate.type, enclosingDeclaration, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors | NodeBuilderFlags.WriteTypeParametersInQualifiedName) + nodeBuilder.typeToTypeNode(typePredicate.type, enclosingDeclaration, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors | NodeBuilderFlags.WriteTypeParametersInQualifiedName)!, // TODO: GH#18217 ); const printer = createPrinter({ removeComments: true }); const sourceFile = enclosingDeclaration && getSourceFileOfNode(enclosingDeclaration); @@ -3978,9 +3992,9 @@ namespace ts { return "public"; } - function getTypeAliasForTypeLiteral(type: Type): Symbol { + function getTypeAliasForTypeLiteral(type: Type): Symbol | undefined { if (type.symbol && type.symbol.flags & SymbolFlags.TypeLiteral) { - const node = findAncestor(type.symbol.declarations[0].parent, n => n.kind !== SyntaxKind.ParenthesizedType); + const node = findAncestor(type.symbol.declarations[0].parent, n => n.kind !== SyntaxKind.ParenthesizedType)!; if (node.kind === SyntaxKind.TypeAliasDeclaration) { return getSymbolOfNode(node); } @@ -3996,8 +4010,8 @@ namespace ts { interface NodeBuilderContext { enclosingDeclaration: Node | undefined; - flags: NodeBuilderFlags | undefined; - tracker: SymbolTracker | undefined; + flags: NodeBuilderFlags; + tracker: SymbolTracker; // State encounteredError: boolean; @@ -4027,21 +4041,21 @@ namespace ts { return "default"; } if (symbol.declarations && symbol.declarations.length) { - if (some(symbol.declarations, hasExternalModuleSymbol) && context.enclosingDeclaration) { + if (some(symbol.declarations, hasExternalModuleSymbol) && context!.enclosingDeclaration) { // TODO: GH#18217 const file = getDeclarationOfKind(symbol, SyntaxKind.SourceFile); - if (!file || !context.tracker.moduleResolverHost) { - if (context.tracker.trackReferencedAmbientModule) { + if (!file || !context!.tracker.moduleResolverHost) { + if (context!.tracker.trackReferencedAmbientModule) { const ambientDecls = filter(symbol.declarations, isAmbientModule); if (length(ambientDecls)) { for (const decl of ambientDecls) { - context.tracker.trackReferencedAmbientModule(decl); + context!.tracker.trackReferencedAmbientModule!(decl); // TODO: GH#18217 } } } // ambient module, just use declaration/symbol name (fallthrough) } else { - return `"${getResolvedExternalModuleName(context.tracker.moduleResolverHost, file, getSourceFileOfNode(getOriginalNode(context.enclosingDeclaration)))}"`; + return `"${getResolvedExternalModuleName(context!.tracker.moduleResolverHost!, file, getSourceFileOfNode(getOriginalNode(context!.enclosingDeclaration)))}"`; } } const declaration = symbol.declarations[0]; @@ -4177,14 +4191,14 @@ namespace ts { } function collectLinkedAliases(node: Identifier, setVisibility?: boolean): Node[] | undefined { - let exportSymbol: Symbol; + let exportSymbol: Symbol | undefined; if (node.parent && node.parent.kind === SyntaxKind.ExportAssignment) { exportSymbol = resolveName(node, node.escapedText, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias, /*nameNotFoundMessage*/ undefined, node, /*isUse*/ false); } else if (node.parent.kind === SyntaxKind.ExportSpecifier) { exportSymbol = getTargetOfExportSpecifier(node.parent, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias); } - let result: Node[]; + let result: Node[] | undefined; if (exportSymbol) { buildVisibleNodeList(exportSymbol.declarations); } @@ -4255,25 +4269,25 @@ namespace ts { return -1; } - function hasType(target: TypeSystemEntity, propertyName: TypeSystemPropertyName): Type | boolean { + function hasType(target: TypeSystemEntity, propertyName: TypeSystemPropertyName): boolean { if (propertyName === TypeSystemPropertyName.Type) { - return getSymbolLinks(target).type; + return !!getSymbolLinks(target).type; } if (propertyName === TypeSystemPropertyName.DeclaredType) { - return getSymbolLinks(target).declaredType; + return !!getSymbolLinks(target).declaredType; } if (propertyName === TypeSystemPropertyName.ResolvedBaseConstructorType) { - return (target).resolvedBaseConstructorType; + return !!(target).resolvedBaseConstructorType; } if (propertyName === TypeSystemPropertyName.ResolvedReturnType) { - return (target).resolvedReturnType; + return !!(target).resolvedReturnType; } if (propertyName === TypeSystemPropertyName.ResolvedBaseConstraint) { const bc = (target).resolvedBaseConstraint; - return bc && bc !== circularConstraintType; + return !!bc && bc !== circularConstraintType; } - Debug.fail("Unhandled TypeSystemPropertyName " + propertyName); + return Debug.fail("Unhandled TypeSystemPropertyName " + propertyName); } // Pop an entry from the type resolution stack and return its associated result value. The result value will @@ -4281,11 +4295,11 @@ namespace ts { function popTypeResolution(): boolean { resolutionTargets.pop(); resolutionPropertyNames.pop(); - return resolutionResults.pop(); + return resolutionResults.pop()!; } function getDeclarationContainer(node: Node): Node { - node = findAncestor(getRootDeclaration(node), node => { + return findAncestor(getRootDeclaration(node), node => { switch (node.kind) { case SyntaxKind.VariableDeclaration: case SyntaxKind.VariableDeclarationList: @@ -4297,8 +4311,7 @@ namespace ts { default: return true; } - }); - return node && node.parent; + })!.parent; } function getTypeOfPrototypeProperty(prototype: Symbol): Type { @@ -4306,17 +4319,17 @@ namespace ts { // Every class automatically contains a static property member named 'prototype', // the type of which is an instantiation of the class type with type Any supplied as a type argument for each type parameter. // It is an error to explicitly declare a static property member with the name 'prototype'. - const classType = getDeclaredTypeOfSymbol(getParentOfSymbol(prototype)); + const classType = getDeclaredTypeOfSymbol(getParentOfSymbol(prototype)!); return classType.typeParameters ? createTypeReference(classType, map(classType.typeParameters, _ => anyType)) : classType; } // Return the type of the given property in the given type, or undefined if no such property exists - function getTypeOfPropertyOfType(type: Type, name: __String): Type { + function getTypeOfPropertyOfType(type: Type, name: __String): Type | undefined { const prop = getPropertyOfType(type, name); return prop ? getTypeOfSymbol(prop) : undefined; } - function isTypeAny(type: Type) { + function isTypeAny(type: Type | undefined) { return type && (type.flags & TypeFlags.Any) !== 0; } @@ -4331,7 +4344,7 @@ namespace ts { return name.kind === SyntaxKind.ComputedPropertyName && !isStringOrNumericLiteral(name.expression); } - function getRestType(source: Type, properties: PropertyName[], symbol: Symbol): Type { + function getRestType(source: Type, properties: PropertyName[], symbol: Symbol | undefined): Type { source = filterType(source, t => !(t.flags & TypeFlags.Nullable)); if (source.flags & TypeFlags.Never) { return emptyObjectType; @@ -4360,7 +4373,7 @@ namespace ts { } /** Return the inferred type for a binding element */ - function getTypeForBindingElement(declaration: BindingElement): Type { + function getTypeForBindingElement(declaration: BindingElement): Type | undefined { const pattern = declaration.parent; let parentType = getTypeForBindingElementParent(pattern.parent); // If parent has the unknown (error) type, then so does this binding element @@ -4377,7 +4390,7 @@ namespace ts { return parentType; } - let type: Type; + let type: Type | undefined; if (pattern.kind === SyntaxKind.ObjectBindingPattern) { if (declaration.dotDotDotToken) { if (!isValidSpreadType(parentType)) { @@ -4419,8 +4432,8 @@ namespace ts { // Use type of the specified property, or otherwise, for a numeric name, the type of the numeric index signature, // or otherwise the type of the string index signature. - const nameType = isLate && checkComputedPropertyName(name as ComputedPropertyName) as LiteralType | UniqueESSymbolType; - const text = isLate ? getLateBoundNameFromType(nameType) : + const nameType = isLate ? checkComputedPropertyName(name as ComputedPropertyName) as LiteralType | UniqueESSymbolType : undefined; + const text = isLate ? getLateBoundNameFromType(nameType!) : isWellKnown ? getPropertyNameForKnownSymbolName(idText(((name as ComputedPropertyName).expression as PropertyAccessExpression).name)) : getTextOfPropertyName(name); @@ -4503,7 +4516,7 @@ namespace ts { } // Return the inferred type for a variable, parameter, or property declaration - function getTypeForVariableLikeDeclaration(declaration: ParameterDeclaration | PropertyDeclaration | PropertySignature | VariableDeclaration | BindingElement, includeOptionality: boolean): Type { + function getTypeForVariableLikeDeclaration(declaration: ParameterDeclaration | PropertyDeclaration | PropertySignature | VariableDeclaration | BindingElement, includeOptionality: boolean): Type | undefined { // A variable declared in a for..in statement is of type string, or of type keyof T when the // right hand expression is of a type parameter type. if (isVariableDeclaration(declaration) && declaration.parent.parent.kind === SyntaxKind.ForInStatement) { @@ -4561,13 +4574,13 @@ namespace ts { if (thisParameter && declaration === thisParameter) { // Use the type from the *getter* Debug.assert(!thisParameter.type); - return getTypeOfSymbol(getterSignature.thisParameter); + return getTypeOfSymbol(getterSignature.thisParameter!); } return getReturnTypeOfSignature(getterSignature); } } // Use contextual parameter type if one is available - let type: Type; + let type: Type | undefined; if (declaration.symbol.escapedName === "this") { type = getContextualThisParameterType(func); } @@ -4607,10 +4620,10 @@ namespace ts { return getWidenedLiteralType(checkExpressionCached(specialDeclaration)); } const types: Type[] = []; - let constructorTypes: Type[]; + let constructorTypes: Type[] | undefined; let definedInConstructor = false; let definedInMethod = false; - let jsDocType: Type; + let jsDocType: Type | undefined; for (const declaration of symbol.declarations) { let declarationInConstructor = false; const expression = declaration.kind === SyntaxKind.BinaryExpression ? declaration : @@ -4660,9 +4673,9 @@ namespace ts { const exportedType = resolveStructuredTypeMembers(type as AnonymousType); const members = createSymbolTable(); copyEntries(exportedType.members, members); - symbol.exports.forEach((s, name) => { + symbol.exports!.forEach((s, name) => { if (members.has(name)) { - const exportedMember = exportedType.members.get(name); + const exportedMember = exportedType.members.get(name)!; const union = createSymbol(s.flags | exportedMember.flags, name); union.type = getUnionType([getTypeOfSymbol(s), getTypeOfSymbol(exportedMember)]); members.set(name, union); @@ -4702,7 +4715,7 @@ namespace ts { definedInConstructor = true; } } - const sourceTypes = some(constructorTypes, t => !!(t.flags & ~(TypeFlags.Nullable | TypeFlags.ContainsWideningType))) ? constructorTypes : types; + const sourceTypes = some(constructorTypes, t => !!(t.flags & ~(TypeFlags.Nullable | TypeFlags.ContainsWideningType))) ? constructorTypes! : types; // TODO: GH#18217 type = getUnionType(sourceTypes, UnionReduction.Subtype); } const widened = getWidenedType(addOptionality(type, definedInMethod && !definedInConstructor)); @@ -4749,7 +4762,7 @@ namespace ts { // Return the type implied by an object binding pattern function getTypeFromObjectBindingPattern(pattern: ObjectBindingPattern, includePatternInType: boolean, reportErrors: boolean): Type { const members = createSymbolTable(); - let stringIndexInfo: IndexInfo; + let stringIndexInfo: IndexInfo | undefined; let objectFlags = ObjectFlags.ObjectLiteral; forEach(pattern.elements, e => { const name = e.propertyName || e.name; @@ -4783,7 +4796,7 @@ namespace ts { function getTypeFromArrayBindingPattern(pattern: BindingPattern, includePatternInType: boolean, reportErrors: boolean): Type { const elements = pattern.elements; const lastElement = lastOrUndefined(elements); - if (elements.length === 0 || (!isOmittedExpression(lastElement) && lastElement.dotDotDotToken)) { + if (!lastElement || (!isOmittedExpression(lastElement) && lastElement.dotDotDotToken)) { return languageVersion >= ScriptTarget.ES2015 ? createIterableType(anyType) : anyArrayType; } // If the pattern has at least one element, and no rest element, then it should imply a tuple type. @@ -4803,7 +4816,7 @@ namespace ts { // used as the contextual type of an initializer associated with the binding pattern. Also, for a destructuring // parameter with no type annotation or initializer, the type implied by the binding pattern becomes the type of // the parameter. - function getTypeFromBindingPattern(pattern: BindingPattern, includePatternInType?: boolean, reportErrors?: boolean): Type { + function getTypeFromBindingPattern(pattern: BindingPattern, includePatternInType = false, reportErrors = false): Type { return pattern.kind === SyntaxKind.ObjectBindingPattern ? getTypeFromObjectBindingPattern(pattern, includePatternInType, reportErrors) : getTypeFromArrayBindingPattern(pattern, includePatternInType, reportErrors); @@ -4932,7 +4945,7 @@ namespace ts { type = getWidenedTypeForVariableLikeDeclaration(declaration, /*reportErrors*/ true); } else { - Debug.fail("Unhandled declaration kind! " + Debug.showSyntaxKind(declaration)); + return Debug.fail("Unhandled declaration kind! " + Debug.showSyntaxKind(declaration)); } if (!popTypeResolution()) { @@ -4943,7 +4956,7 @@ namespace ts { return links.type; } - function getAnnotatedAccessorType(accessor: AccessorDeclaration): Type { + function getAnnotatedAccessorType(accessor: AccessorDeclaration | undefined): Type | undefined { if (accessor) { if (accessor.kind === SyntaxKind.GetAccessor) { const getterTypeAnnotation = getEffectiveReturnTypeNode(accessor); @@ -5094,7 +5107,7 @@ namespace ts { return unknownType; } symbolInstantiationDepth++; - let type = instantiateType(getTypeOfSymbol(links.target), links.mapper); + let type = instantiateType(getTypeOfSymbol(links.target!), links.mapper!); symbolInstantiationDepth--; if (!popTypeResolution()) { type = reportCircularityError(symbol); @@ -5156,23 +5169,25 @@ namespace ts { return getObjectFlags(type) & ObjectFlags.Reference ? (type).target : type; } - function hasBaseType(type: Type, checkBase: Type) { + // TODO: GH#18217 If `checkBase` is undefined, we should not call this because this will always return false. + function hasBaseType(type: Type, checkBase: Type | undefined) { return check(type); function check(type: Type): boolean { if (getObjectFlags(type) & (ObjectFlags.ClassOrInterface | ObjectFlags.Reference)) { const target = getTargetType(type); - return target === checkBase || forEach(getBaseTypes(target), check); + return target === checkBase || some(getBaseTypes(target), check); } else if (type.flags & TypeFlags.Intersection) { - return forEach((type).types, check); + return some((type).types, check); } + return false; } } // Appends the type parameters given by a list of declarations to a set of type parameters and returns the resulting set. // The function allocates a new array if the input type parameter set is undefined, but otherwise it modifies the set // in-place and returns the same array. - function appendTypeParameters(typeParameters: TypeParameter[] | undefined, declarations: ReadonlyArray): TypeParameter[] { + function appendTypeParameters(typeParameters: TypeParameter[] | undefined, declarations: ReadonlyArray): TypeParameter[] | undefined { for (const declaration of declarations) { typeParameters = appendIfUnique(typeParameters, getDeclaredTypeOfTypeParameter(getSymbolOfNode(declaration))); } @@ -5180,9 +5195,9 @@ namespace ts { } // Return the outer type parameters of a node or undefined if the node has no outer type parameters. - function getOuterTypeParameters(node: Node, includeThisTypes?: boolean): TypeParameter[] { + function getOuterTypeParameters(node: Node, includeThisTypes?: boolean): TypeParameter[] | undefined { while (true) { - node = node.parent; + node = node.parent; // TODO: GH#18217 Use SourceFile kind check instead if (!node) { return undefined; } @@ -5216,21 +5231,21 @@ namespace ts { const outerAndOwnTypeParameters = appendTypeParameters(outerTypeParameters, getEffectiveTypeParameterDeclarations(node)); const thisType = includeThisTypes && (node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassExpression || node.kind === SyntaxKind.InterfaceDeclaration) && - getDeclaredTypeOfClassOrInterface(getSymbolOfNode(node)).thisType; + getDeclaredTypeOfClassOrInterface(getSymbolOfNode(node as ClassLikeDeclaration | InterfaceDeclaration)).thisType; return thisType ? append(outerAndOwnTypeParameters, thisType) : outerAndOwnTypeParameters; } } } // The outer type parameters are those defined by enclosing generic classes, methods, or functions. - function getOuterTypeParametersOfClassOrInterface(symbol: Symbol): TypeParameter[] { - const declaration = symbol.flags & SymbolFlags.Class ? symbol.valueDeclaration : getDeclarationOfKind(symbol, SyntaxKind.InterfaceDeclaration); + function getOuterTypeParametersOfClassOrInterface(symbol: Symbol): TypeParameter[] | undefined { + const declaration = symbol.flags & SymbolFlags.Class ? symbol.valueDeclaration : getDeclarationOfKind(symbol, SyntaxKind.InterfaceDeclaration)!; return getOuterTypeParameters(declaration); } // The local type parameters are the combined set of type parameters from all declarations of the class, // interface, or type alias. - function getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol: Symbol): TypeParameter[] { + function getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol: Symbol): TypeParameter[] | undefined { let result: TypeParameter[] | undefined; for (const node of symbol.declarations) { if (node.kind === SyntaxKind.InterfaceDeclaration || @@ -5246,7 +5261,7 @@ namespace ts { // The full set of type parameters for a generic class or interface type consists of its outer type parameters plus // its locally declared type parameters. - function getTypeParametersOfClassOrInterface(symbol: Symbol): TypeParameter[] { + function getTypeParametersOfClassOrInterface(symbol: Symbol): TypeParameter[] | undefined { return concatenate(getOuterTypeParametersOfClassOrInterface(symbol), getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol)); } @@ -5267,12 +5282,12 @@ namespace ts { } if (type.flags & TypeFlags.TypeVariable) { const constraint = getBaseConstraintOfType(type); - return constraint && isValidBaseType(constraint) && isMixinConstructorType(constraint); + return !!constraint && isValidBaseType(constraint) && isMixinConstructorType(constraint); } return false; } - function getBaseTypeNodeOfClass(type: InterfaceType): ExpressionWithTypeArguments { + function getBaseTypeNodeOfClass(type: InterfaceType): ExpressionWithTypeArguments | undefined { const decl = type.symbol.valueDeclaration; if (isInJavaScriptFile(decl)) { // Prefer an @augments tag because it may have type parameters. @@ -5285,17 +5300,17 @@ namespace ts { return getClassExtendsHeritageClauseElement(decl); } - function getConstructorsForTypeArguments(type: Type, typeArgumentNodes: ReadonlyArray, location: Node): Signature[] { + function getConstructorsForTypeArguments(type: Type, typeArgumentNodes: ReadonlyArray | undefined, location: Node): Signature[] { const typeArgCount = length(typeArgumentNodes); const isJavaScript = isInJavaScriptFile(location); return filter(getSignaturesOfType(type, SignatureKind.Construct), sig => (isJavaScript || typeArgCount >= getMinTypeArgumentCount(sig.typeParameters)) && typeArgCount <= length(sig.typeParameters)); } - function getInstantiatedConstructorsForTypeArguments(type: Type, typeArgumentNodes: ReadonlyArray, location: Node): Signature[] { + function getInstantiatedConstructorsForTypeArguments(type: Type, typeArgumentNodes: ReadonlyArray | undefined, location: Node): Signature[] { const signatures = getConstructorsForTypeArguments(type, typeArgumentNodes, location); const typeArguments = map(typeArgumentNodes, getTypeFromTypeNode); - return sameMap(signatures, sig => some(sig.typeParameters) ? getSignatureInstantiation(sig, typeArguments, isInJavaScriptFile(location)) : sig); + return sameMap(signatures, sig => some(sig.typeParameters) ? getSignatureInstantiation(sig, typeArguments, isInJavaScriptFile(location)) : sig); } /** @@ -5343,7 +5358,7 @@ namespace ts { function getBaseTypes(type: InterfaceType): BaseType[] { if (!type.resolvedBaseTypes) { if (type.objectFlags & ObjectFlags.Tuple) { - type.resolvedBaseTypes = [createArrayType(getUnionType(type.typeParameters))]; + type.resolvedBaseTypes = [createArrayType(getUnionType(type.typeParameters!))]; } else if (type.symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) { if (type.symbol.flags & SymbolFlags.Class) { @@ -5366,12 +5381,12 @@ namespace ts { if (!(baseConstructorType.flags & (TypeFlags.Object | TypeFlags.Intersection | TypeFlags.Any))) { return type.resolvedBaseTypes = emptyArray; } - const baseTypeNode = getBaseTypeNodeOfClass(type); + const baseTypeNode = getBaseTypeNodeOfClass(type)!; const typeArgs = typeArgumentsFromTypeReferenceNode(baseTypeNode); let baseType: Type; const originalBaseType = baseConstructorType && baseConstructorType.symbol ? getDeclaredTypeOfSymbol(baseConstructorType.symbol) : undefined; if (baseConstructorType.symbol && baseConstructorType.symbol.flags & SymbolFlags.Class && - areAllOuterTypeParametersApplied(originalBaseType)) { + areAllOuterTypeParametersApplied(originalBaseType!)) { // When base constructor type is a class with no captured type arguments we know that the constructors all have the same type parameters as the // class and all return the instance type of the class. There is no need for further checks and we can apply the // type arguments in the same manner as a type reference to get the same error reporting experience. @@ -5409,18 +5424,18 @@ namespace ts { // (otherwise there'd be an error from hasBaseType) - this is fine, but `.members` should be reset // as `getIndexedAccessType` via `instantiateType` via `getTypeFromClassOrInterfaceReference` forces a // partial instantiation of the members without the base types fully resolved - (type as Type as ResolvedType).members = undefined; + (type as Type as ResolvedType).members = undefined!; // TODO: GH#18217 } return type.resolvedBaseTypes = [baseType]; } - function areAllOuterTypeParametersApplied(type: Type): boolean { + function areAllOuterTypeParametersApplied(type: Type): boolean { // TODO: GH#18217 Shouldn't this take an InterfaceType? // An unapplied type parameter has its symbol still the same as the matching argument symbol. // Since parameters are applied outer-to-inner, only the last outer parameter needs to be checked. const outerTypeParameters = (type).outerTypeParameters; if (outerTypeParameters) { const last = outerTypeParameters.length - 1; - const typeArguments = (type).typeArguments; + const typeArguments = (type).typeArguments!; return outerTypeParameters[last].symbol !== typeArguments[last].symbol; } return true; @@ -5429,15 +5444,15 @@ namespace ts { // A valid base type is `any`, any non-generic object type or intersection of non-generic // object types. function isValidBaseType(type: Type): type is BaseType { - return type.flags & (TypeFlags.Object | TypeFlags.NonPrimitive | TypeFlags.Any) && !isGenericMappedType(type) || - type.flags & TypeFlags.Intersection && !forEach((type).types, t => !isValidBaseType(t)); + return !!(type.flags & (TypeFlags.Object | TypeFlags.NonPrimitive | TypeFlags.Any)) && !isGenericMappedType(type) || + !!(type.flags & TypeFlags.Intersection) && !some((type).types, t => !isValidBaseType(t)); } function resolveBaseTypesOfInterface(type: InterfaceType): void { type.resolvedBaseTypes = type.resolvedBaseTypes || emptyArray; for (const declaration of type.symbol.declarations) { if (declaration.kind === SyntaxKind.InterfaceDeclaration && getInterfaceBaseTypeNodes(declaration)) { - for (const node of getInterfaceBaseTypeNodes(declaration)) { + for (const node of getInterfaceBaseTypeNodes(declaration)!) { const baseType = getTypeFromTypeNode(node); if (baseType !== unknownType) { if (isValidBaseType(baseType)) { @@ -5578,7 +5593,7 @@ namespace ts { return (expr).operator === SyntaxKind.MinusToken && (expr).operand.kind === SyntaxKind.NumericLiteral; case SyntaxKind.Identifier: - return nodeIsMissing(expr) || !!getSymbolOfNode(member.parent).exports.get((expr).escapedText); + return nodeIsMissing(expr) || !!getSymbolOfNode(member.parent).exports!.get((expr).escapedText); case SyntaxKind.BinaryExpression: return isStringConcatExpression(expr); default: @@ -5608,7 +5623,7 @@ namespace ts { } function getBaseTypeOfEnumLiteralType(type: Type) { - return type.flags & TypeFlags.EnumLiteral && !(type.flags & TypeFlags.Union) ? getDeclaredTypeOfSymbol(getParentOfSymbol(type.symbol)) : type; + return type.flags & TypeFlags.EnumLiteral && !(type.flags & TypeFlags.Union) ? getDeclaredTypeOfSymbol(getParentOfSymbol(type.symbol)!) : type; } function getDeclaredTypeOfEnum(symbol: Symbol): Type { @@ -5622,7 +5637,7 @@ namespace ts { for (const declaration of symbol.declarations) { if (declaration.kind === SyntaxKind.EnumDeclaration) { for (const member of (declaration).members) { - const memberType = getLiteralType(getEnumMemberValue(member), enumCount, getSymbolOfNode(member)); + const memberType = getLiteralType(getEnumMemberValue(member)!, enumCount, getSymbolOfNode(member)); // TODO: GH#18217 getSymbolLinks(getSymbolOfNode(member)).declaredType = memberType; memberTypeList.push(memberType); } @@ -5645,7 +5660,7 @@ namespace ts { function getDeclaredTypeOfEnumMember(symbol: Symbol): Type { const links = getSymbolLinks(symbol); if (!links.declaredType) { - const enumType = getDeclaredTypeOfEnum(getParentOfSymbol(symbol)); + const enumType = getDeclaredTypeOfEnum(getParentOfSymbol(symbol)!); if (!links.declaredType) { links.declaredType = enumType; } @@ -5719,7 +5734,7 @@ namespace ts { case SyntaxKind.ArrayType: return isThislessType((node).elementType); case SyntaxKind.TypeReference: - return !(node as TypeReferenceNode).typeArguments || (node as TypeReferenceNode).typeArguments.every(isThislessType); + return !(node as TypeReferenceNode).typeArguments || (node as TypeReferenceNode).typeArguments!.every(isThislessType); } return false; } @@ -5746,7 +5761,7 @@ namespace ts { function isThislessFunctionLikeDeclaration(node: FunctionLikeDeclaration): boolean { const returnType = getEffectiveReturnTypeNode(node); const typeParameters = getEffectiveTypeParameterDeclarations(node); - return (node.kind === SyntaxKind.Constructor || (returnType && isThislessType(returnType))) && + return (node.kind === SyntaxKind.Constructor || (!!returnType && isThislessType(returnType))) && node.parameters.every(isThislessVariableLikeDeclaration) && typeParameters.every(isThislessTypeParameter); } @@ -5837,7 +5852,7 @@ namespace ts { */ function hasLateBindableName(node: Declaration): node is LateBoundDeclaration { const name = getNameOfDeclaration(node); - return name && isLateBindableName(name); + return !!name && isLateBindableName(name); } /** @@ -5857,13 +5872,14 @@ namespace ts { /** * Gets the symbolic name for a late-bound member from its type. */ - function getLateBoundNameFromType(type: LiteralType | UniqueESSymbolType) { + function getLateBoundNameFromType(type: LiteralType | UniqueESSymbolType): __String { if (type.flags & TypeFlags.UniqueESSymbol) { return `__@${type.symbol.escapedName}@${getSymbolId(type.symbol)}` as __String; } if (type.flags & TypeFlags.StringOrNumberLiteral) { return escapeLeadingUnderscores("" + (type).value); } + return Debug.fail(); } /** @@ -5882,8 +5898,7 @@ namespace ts { symbol.declarations.push(member); } if (symbolFlags & SymbolFlags.Value) { - const valueDeclaration = symbol.valueDeclaration; - if (!valueDeclaration || valueDeclaration.kind !== member.kind) { + if (!symbol.valueDeclaration || symbol.valueDeclaration.kind !== member.kind) { symbol.valueDeclaration = member; } } @@ -5960,7 +5975,7 @@ namespace ts { return links.resolvedSymbol; } - function getResolvedMembersOrExportsOfSymbol(symbol: Symbol, resolutionKind: MembersOrExportsResolutionKind) { + function getResolvedMembersOrExportsOfSymbol(symbol: Symbol, resolutionKind: MembersOrExportsResolutionKind): UnderscoreEscapedMap { const links = getSymbolLinks(symbol); if (!links[resolutionKind]) { const isStatic = resolutionKind === MembersOrExportsResolutionKind.resolvedExports; @@ -5989,7 +6004,7 @@ namespace ts { links[resolutionKind] = combineSymbolTables(earlySymbols, lateSymbols) || emptySymbols; } - return links[resolutionKind]; + return links[resolutionKind]!; } /** @@ -6015,10 +6030,10 @@ namespace ts { if (!links.lateSymbol && some(symbol.declarations, hasLateBindableName)) { // force late binding of members/exports. This will set the late-bound symbol if (some(symbol.declarations, hasStaticModifier)) { - getExportsOfSymbol(symbol.parent); + getExportsOfSymbol(symbol.parent!); } else { - getMembersOfSymbol(symbol.parent); + getMembersOfSymbol(symbol.parent!); } } return links.lateSymbol || (links.lateSymbol = symbol); @@ -6031,7 +6046,7 @@ namespace ts { const target = (type).target; const typeArguments = (type).typeArguments; if (length(target.typeParameters) === length(typeArguments)) { - const ref = createTypeReference(target, concatenate(typeArguments, [thisArgument || target.thisType])); + const ref = createTypeReference(target, concatenate(typeArguments, [thisArgument || target.thisType!])); return needApparentType ? getApparentType(ref) : ref; } } @@ -6045,9 +6060,9 @@ namespace ts { let mapper: TypeMapper; let members: SymbolTable; let callSignatures: Signature[]; - let constructSignatures: Signature[]; - let stringIndexInfo: IndexInfo; - let numberIndexInfo: IndexInfo; + let constructSignatures: Signature[] | undefined; + let stringIndexInfo: IndexInfo | undefined; + let numberIndexInfo: IndexInfo | undefined; if (rangeEquals(typeParameters, typeArguments, 0, typeParameters.length)) { mapper = identityMapper; members = source.symbol ? getMembersOfSymbol(source.symbol) : createSymbolTable(source.declaredProperties); @@ -6093,15 +6108,15 @@ namespace ts { function resolveTypeReferenceMembers(type: TypeReference): void { const source = resolveDeclaredMembers(type.target); - const typeParameters = concatenate(source.typeParameters, [source.thisType]); + const typeParameters = concatenate(source.typeParameters!, [source.thisType!]); const typeArguments = type.typeArguments && type.typeArguments.length === typeParameters.length ? type.typeArguments : concatenate(type.typeArguments, [type]); resolveObjectTypeMembers(type, source, typeParameters, typeArguments); } function createSignature( - declaration: SignatureDeclaration | JSDocSignature, - typeParameters: TypeParameter[], + declaration: SignatureDeclaration | JSDocSignature | undefined, + typeParameters: TypeParameter[] | undefined, thisParameter: Symbol | undefined, parameters: Symbol[], resolvedReturnType: Type | undefined, @@ -6134,9 +6149,9 @@ namespace ts { const baseConstructorType = getBaseConstructorTypeOfClass(classType); const baseSignatures = getSignaturesOfType(baseConstructorType, SignatureKind.Construct); if (baseSignatures.length === 0) { - return [createSignature(undefined, classType.localTypeParameters, undefined, emptyArray, classType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false)]; + return [createSignature(undefined, classType.localTypeParameters, undefined, emptyArray, classType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false)]; // TODO: GH#18217 } - const baseTypeNode = getBaseTypeNodeOfClass(classType); + const baseTypeNode = getBaseTypeNodeOfClass(classType)!; const isJavaScript = isInJavaScriptFile(baseTypeNode); const typeArguments = typeArgumentsFromTypeReferenceNode(baseTypeNode); const typeArgCount = length(typeArguments); @@ -6145,7 +6160,7 @@ namespace ts { const minTypeArgumentCount = getMinTypeArgumentCount(baseSig.typeParameters); const typeParamCount = length(baseSig.typeParameters); if (isJavaScript || typeArgCount >= minTypeArgumentCount && typeArgCount <= typeParamCount) { - const sig = typeParamCount ? createSignatureInstantiation(baseSig, fillMissingTypeArguments(typeArguments, baseSig.typeParameters, minTypeArgumentCount, isJavaScript)) : cloneSignature(baseSig); + const sig = typeParamCount ? createSignatureInstantiation(baseSig, fillMissingTypeArguments(typeArguments, baseSig.typeParameters, minTypeArgumentCount, isJavaScript)!) : cloneSignature(baseSig); sig.typeParameters = classType.localTypeParameters; sig.resolvedReturnType = classType; result.push(sig); @@ -6154,7 +6169,7 @@ namespace ts { return result; } - function findMatchingSignature(signatureList: Signature[], signature: Signature, partialMatch: boolean, ignoreThisTypes: boolean, ignoreReturnTypes: boolean): Signature { + function findMatchingSignature(signatureList: Signature[], signature: Signature, partialMatch: boolean, ignoreThisTypes: boolean, ignoreReturnTypes: boolean): Signature | undefined { for (const s of signatureList) { if (compareSignaturesIdentical(s, signature, partialMatch, ignoreThisTypes, ignoreReturnTypes, compareTypesIdentical)) { return s; @@ -6162,7 +6177,7 @@ namespace ts { } } - function findMatchingSignatures(signatureLists: Signature[][], signature: Signature, listIndex: number): Signature[] { + function findMatchingSignatures(signatureLists: Signature[][], signature: Signature, listIndex: number): Signature[] | undefined { if (signature.typeParameters) { // We require an exact match for generic signatures, so we only return signatures from the first // signature list and only if they have exact matches in the other signature lists. @@ -6176,7 +6191,7 @@ namespace ts { } return [signature]; } - let result: Signature[]; + let result: Signature[] | undefined; for (let i = 0; i < signatureLists.length; i++) { // Allow matching non-generic signatures to have excess parameters and different return types const match = i === listIndex ? signature : findMatchingSignature(signatureLists[i], signature, /*partialMatch*/ true, /*ignoreThisTypes*/ true, /*ignoreReturnTypes*/ true); @@ -6194,7 +6209,7 @@ namespace ts { // type is the union of the constituent return types. function getUnionSignatures(types: Type[], kind: SignatureKind): Signature[] { const signatureLists = map(types, t => getSignaturesOfType(t, kind)); - let result: Signature[]; + let result: Signature[] | undefined; for (let i = 0; i < signatureLists.length; i++) { for (const signature of signatureLists[i]) { // Only process signatures with parameter lists that aren't already in the result list @@ -6206,8 +6221,9 @@ namespace ts { if (unionSignatures.length > 1) { let thisParameter = signature.thisParameter; if (forEach(unionSignatures, sig => sig.thisParameter)) { + // TODO: GH#18217 We tested that *some* has thisParameter and now act as if *all* do const thisType = getUnionType(map(unionSignatures, sig => sig.thisParameter ? getTypeOfSymbol(sig.thisParameter) : anyType), UnionReduction.Subtype); - thisParameter = createSymbolWithType(signature.thisParameter, thisType); + thisParameter = createSymbolWithType(signature.thisParameter!, thisType); } s = cloneSignature(signature); s.thisParameter = thisParameter; @@ -6221,7 +6237,7 @@ namespace ts { return result || emptyArray; } - function getUnionIndexInfo(types: Type[], kind: IndexKind): IndexInfo { + function getUnionIndexInfo(types: Type[], kind: IndexKind): IndexInfo | undefined { const indexTypes: Type[] = []; let isAnyReadonly = false; for (const type of types) { @@ -6245,16 +6261,18 @@ namespace ts { setStructuredTypeMembers(type, emptySymbols, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); } - function intersectTypes(type1: Type, type2: Type): Type { + function intersectTypes(type1: Type, type2: Type): Type; + function intersectTypes(type1: Type | undefined, type2: Type | undefined): Type | undefined; + function intersectTypes(type1: Type | undefined, type2: Type | undefined): Type | undefined { return !type1 ? type2 : !type2 ? type1 : getIntersectionType([type1, type2]); } - function intersectIndexInfos(info1: IndexInfo, info2: IndexInfo): IndexInfo { + function intersectIndexInfos(info1: IndexInfo | undefined, info2: IndexInfo | undefined): IndexInfo | undefined { return !info1 ? info2 : !info2 ? info1 : createIndexInfo( getIntersectionType([info1.type, info2.type]), info1.isReadonly && info2.isReadonly); } - function unionSpreadIndexInfos(info1: IndexInfo, info2: IndexInfo): IndexInfo { + function unionSpreadIndexInfos(info1: IndexInfo | undefined, info2: IndexInfo | undefined): IndexInfo | undefined { return info1 && info2 && createIndexInfo( getUnionType([info1.type, info2.type]), info1.isReadonly || info2.isReadonly); } @@ -6277,8 +6295,8 @@ namespace ts { // intersection type use getPropertiesOfType (only the language service uses this). let callSignatures: Signature[] = emptyArray; let constructSignatures: Signature[] = emptyArray; - let stringIndexInfo: IndexInfo; - let numberIndexInfo: IndexInfo; + let stringIndexInfo: IndexInfo | undefined; + let numberIndexInfo: IndexInfo | undefined; const types = type.types; const mixinCount = countWhere(types, isMixinConstructorType); for (let i = 0; i < types.length; i++) { @@ -6312,11 +6330,11 @@ namespace ts { function resolveAnonymousTypeMembers(type: AnonymousType) { const symbol = type.symbol; if (type.target) { - const members = createInstantiatedSymbolTable(getPropertiesOfObjectType(type.target), type.mapper, /*mappingThisOnly*/ false); - const callSignatures = instantiateSignatures(getSignaturesOfType(type.target, SignatureKind.Call), type.mapper); - const constructSignatures = instantiateSignatures(getSignaturesOfType(type.target, SignatureKind.Construct), type.mapper); - const stringIndexInfo = instantiateIndexInfo(getIndexInfoOfType(type.target, IndexKind.String), type.mapper); - const numberIndexInfo = instantiateIndexInfo(getIndexInfoOfType(type.target, IndexKind.Number), type.mapper); + const members = createInstantiatedSymbolTable(getPropertiesOfObjectType(type.target), type.mapper!, /*mappingThisOnly*/ false); + const callSignatures = instantiateSignatures(getSignaturesOfType(type.target, SignatureKind.Call), type.mapper!); + const constructSignatures = instantiateSignatures(getSignaturesOfType(type.target, SignatureKind.Construct), type.mapper!); + const stringIndexInfo = instantiateIndexInfo(getIndexInfoOfType(type.target, IndexKind.String), type.mapper!); + const numberIndexInfo = instantiateIndexInfo(getIndexInfoOfType(type.target, IndexKind.Number), type.mapper!); setStructuredTypeMembers(type, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); } else if (symbol.flags & SymbolFlags.TypeLiteral) { @@ -6330,7 +6348,7 @@ namespace ts { else { // Combinations of function, class, enum and module let members = emptySymbols; - let stringIndexInfo: IndexInfo; + let stringIndexInfo: IndexInfo | undefined; if (symbol.exports) { members = getExportsOfSymbol(symbol); } @@ -6358,7 +6376,7 @@ namespace ts { // And likewise for construct signatures for classes if (symbol.flags & SymbolFlags.Class) { const classType = getDeclaredTypeOfClassOrInterface(symbol); - let constructSignatures = getSignaturesOfSymbol(symbol.members.get(InternalSymbolName.Constructor)); + let constructSignatures = getSignaturesOfSymbol(symbol.members!.get(InternalSymbolName.Constructor)); if (!constructSignatures.length) { constructSignatures = getDefaultConstructSignatures(classType); } @@ -6389,8 +6407,8 @@ namespace ts { /** Resolve the members of a mapped type { [P in K]: T } */ function resolveMappedTypeMembers(type: MappedType) { const members: SymbolTable = createSymbolTable(); - let stringIndexInfo: IndexInfo; - let numberIndexInfo: IndexInfo; + let stringIndexInfo: IndexInfo | undefined; + let numberIndexInfo: IndexInfo | undefined; // Resolve upfront such that recursive references see an empty object type. setStructuredTypeMembers(type, emptySymbols, emptyArray, emptyArray, undefined, undefined); // In { [P in K]: T }, we refer to P as the type parameter type, K as the constraint type, @@ -6483,7 +6501,7 @@ namespace ts { } function isMappedTypeWithKeyofConstraintDeclaration(type: MappedType) { - const constraintDeclaration = getConstraintDeclarationForMappedType(type); + const constraintDeclaration = getConstraintDeclarationForMappedType(type)!; // TODO: GH#18217 return constraintDeclaration.kind === SyntaxKind.TypeOperator && (constraintDeclaration).operator === SyntaxKind.KeyOfKeyword; } @@ -6531,7 +6549,7 @@ namespace ts { } function isGenericMappedType(type: Type): type is MappedType { - return getObjectFlags(type) & ObjectFlags.Mapped && isGenericIndexType(getConstraintTypeFromMappedType(type)); + return !!(getObjectFlags(type) & ObjectFlags.Mapped) && isGenericIndexType(getConstraintTypeFromMappedType(type)); } function resolveStructuredTypeMembers(type: StructuredType): ResolvedType { @@ -6574,7 +6592,7 @@ namespace ts { /** If the given type is an object type and that type has a property by the given name, * return the symbol for that property. Otherwise return undefined. */ - function getPropertyOfObjectType(type: Type, name: __String): Symbol { + function getPropertyOfObjectType(type: Type, name: __String): Symbol | undefined { if (type.flags & TypeFlags.Object) { const resolved = resolveStructuredTypeMembers(type); const symbol = resolved.members.get(name); @@ -6633,14 +6651,14 @@ namespace ts { return arrayFrom(props.values()); } - function getConstraintOfType(type: InstantiableType | UnionOrIntersectionType): Type { + function getConstraintOfType(type: InstantiableType | UnionOrIntersectionType): Type | undefined { return type.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(type) : type.flags & TypeFlags.IndexedAccess ? getConstraintOfIndexedAccess(type) : type.flags & TypeFlags.Conditional ? getConstraintOfConditionalType(type) : getBaseConstraintOfType(type); } - function getConstraintOfTypeParameter(typeParameter: TypeParameter): Type { + function getConstraintOfTypeParameter(typeParameter: TypeParameter): Type | undefined { return hasNonCircularBaseConstraint(typeParameter) ? getConstraintFromTypeParameter(typeParameter) : undefined; } @@ -6660,7 +6678,7 @@ namespace ts { return type.resolvedDefaultConstraint; } - function getConstraintOfDistributiveConditionalType(type: ConditionalType): Type { + function getConstraintOfDistributiveConditionalType(type: ConditionalType): Type | undefined { // Check if we have a conditional type of the form 'T extends U ? X : Y', where T is a constrained // type parameter. If so, create an instantiation of the conditional type where T is replaced // with its constraint. We do this because if the constraint is a union type it will be distributed @@ -6684,7 +6702,7 @@ namespace ts { } function getUnionConstraintOfIntersection(type: IntersectionType, targetIsUnion: boolean) { - let constraints: Type[]; + let constraints: Type[] | undefined; let hasDisjointDomainType = false; for (const t of type.types) { if (t.flags & TypeFlags.Instantiable) { @@ -6733,7 +6751,7 @@ namespace ts { } } - function getBaseConstraintOfType(type: Type): Type { + function getBaseConstraintOfType(type: Type): Type | undefined { const constraint = getBaseConstraintOfInstantiableNonPrimitiveUnionOrIntersection(type); if (!constraint && type.flags & TypeFlags.Index) { return keyofConstraintType; @@ -6759,14 +6777,14 @@ namespace ts { * circularly references the type variable. */ function getResolvedBaseConstraint(type: InstantiableType | UnionOrIntersectionType): Type { - let circular: boolean; + let circular: boolean | undefined; if (!type.resolvedBaseConstraint) { const constraint = getBaseConstraint(type); type.resolvedBaseConstraint = circular ? circularConstraintType : getTypeWithThisArgument(constraint || noConstraintType, type); } return type.resolvedBaseConstraint; - function getBaseConstraint(t: Type): Type { + function getBaseConstraint(t: Type): Type | undefined { if (!pushTypeResolution(t, TypeSystemPropertyName.ResolvedBaseConstraint)) { circular = true; return undefined; @@ -6779,7 +6797,7 @@ namespace ts { return result; } - function computeBaseConstraint(t: Type): Type { + function computeBaseConstraint(t: Type): Type | undefined { if (t.flags & TypeFlags.TypeParameter) { const constraint = getConstraintFromTypeParameter(t); return (t as TypeParameter).isThisType || !constraint ? @@ -6830,7 +6848,7 @@ namespace ts { if (!typeParameter.default) { if (typeParameter.target) { const targetDefault = getResolvedTypeParameterDefault(typeParameter.target); - typeParameter.default = targetDefault ? instantiateType(targetDefault, typeParameter.mapper) : noConstraintType; + typeParameter.default = targetDefault ? instantiateType(targetDefault, typeParameter.mapper!) : noConstraintType; } else { // To block recursion, set the initial value to the resolvingDefaultType. @@ -6891,7 +6909,7 @@ namespace ts { } function createUnionOrIntersectionProperty(containingType: UnionOrIntersectionType, name: __String): Symbol | undefined { - let props: Symbol[]; + let props: Symbol[] | undefined; const isUnion = containingType.flags & TypeFlags.Union; const excludeModifiers = isUnion ? ModifierFlags.NonPublicAccessibilityModifier : 0; // Flags we want to propagate to the result if they exist in all source symbols @@ -6926,12 +6944,12 @@ namespace ts { if (props.length === 1 && !(checkFlags & CheckFlags.Partial)) { return props[0]; } - let declarations: Declaration[]; - let commonType: Type; - let nameType: Type; + let declarations: Declaration[] | undefined; + let commonType: Type | undefined; + let nameType: Type | undefined; const propTypes: Type[] = []; let first = true; - let commonValueDeclaration: Declaration; + let commonValueDeclaration: Declaration | undefined; let hasNonUniformValueDeclaration = false; for (const prop of props) { if (!commonValueDeclaration) { @@ -6959,7 +6977,7 @@ namespace ts { if (!hasNonUniformValueDeclaration && commonValueDeclaration) { result.valueDeclaration = commonValueDeclaration; } - result.declarations = declarations; + result.declarations = declarations!; result.nameType = nameType; result.type = isUnion ? getUnionType(propTypes) : getIntersectionType(propTypes); return result; @@ -6970,7 +6988,7 @@ namespace ts { // constituents, in which case the isPartial flag is set when the containing type is union type. We need // these partial properties when identifying discriminant properties, but otherwise they are filtered out // and do not appear to be present in the union type. - function getUnionOrIntersectionProperty(type: UnionOrIntersectionType, name: __String): Symbol { + function getUnionOrIntersectionProperty(type: UnionOrIntersectionType, name: __String): Symbol | undefined { const properties = type.propertyCache || (type.propertyCache = createSymbolTable()); let property = properties.get(name); if (!property) { @@ -6982,7 +7000,7 @@ namespace ts { return property; } - function getPropertyOfUnionOrIntersectionType(type: UnionOrIntersectionType, name: __String): Symbol { + function getPropertyOfUnionOrIntersectionType(type: UnionOrIntersectionType, name: __String): Symbol | undefined { const property = getUnionOrIntersectionProperty(type, name); // We need to filter out partial properties in union types return property && !(getCheckFlags(property) & CheckFlags.Partial) ? property : undefined; @@ -7048,17 +7066,17 @@ namespace ts { // Return the indexing info of the given kind in the given type. Creates synthetic union index types when necessary and // maps primitive types and type parameters are to their apparent types. - function getIndexInfoOfType(type: Type, kind: IndexKind): IndexInfo { + function getIndexInfoOfType(type: Type, kind: IndexKind): IndexInfo | undefined { return getIndexInfoOfStructuredType(getApparentType(type), kind); } // Return the index type of the given kind in the given type. Creates synthetic union index types when necessary and // maps primitive types and type parameters are to their apparent types. - function getIndexTypeOfType(type: Type, kind: IndexKind): Type { + function getIndexTypeOfType(type: Type, kind: IndexKind): Type | undefined { return getIndexTypeOfStructuredType(getApparentType(type), kind); } - function getImplicitIndexTypeOfType(type: Type, kind: IndexKind): Type { + function getImplicitIndexTypeOfType(type: Type, kind: IndexKind): Type | undefined { if (isObjectTypeWithInferableIndex(type)) { const propTypes: Type[] = []; for (const prop of getPropertiesOfType(type)) { @@ -7153,7 +7171,7 @@ namespace ts { } } - function createIdentifierTypePredicate(parameterName: string | undefined, parameterIndex: number | undefined, type: Type): IdentifierTypePredicate { + function createIdentifierTypePredicate(parameterName: string, parameterIndex: number, type: Type): IdentifierTypePredicate { return { kind: TypePredicateKind.Identifier, parameterName, parameterIndex, type }; } @@ -7185,6 +7203,8 @@ namespace ts { * @param typeParameters The requested type parameters. * @param minTypeArgumentCount The minimum number of required type arguments. */ + function fillMissingTypeArguments(typeArguments: Type[], typeParameters: TypeParameter[] | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean): Type[]; + function fillMissingTypeArguments(typeArguments: Type[] | undefined, typeParameters: TypeParameter[] | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean): Type[] | undefined; function fillMissingTypeArguments(typeArguments: Type[] | undefined, typeParameters: TypeParameter[] | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean) { const numTypeParameters = length(typeParameters); if (numTypeParameters) { @@ -7201,14 +7221,14 @@ namespace ts { typeArguments[i] = getDefaultTypeArgumentType(isJavaScriptImplicitAny); } for (let i = numTypeArguments; i < numTypeParameters; i++) { - const mapper = createTypeMapper(typeParameters, typeArguments); - let defaultType = getDefaultFromTypeParameter(typeParameters[i]); + const mapper = createTypeMapper(typeParameters!, typeArguments); + let defaultType = getDefaultFromTypeParameter(typeParameters![i]); if (isJavaScriptImplicitAny && defaultType && isTypeIdenticalTo(defaultType, emptyObjectType)) { defaultType = anyType; } typeArguments[i] = defaultType ? instantiateType(defaultType, mapper) : getDefaultTypeArgumentType(isJavaScriptImplicitAny); } - typeArguments.length = typeParameters.length; + typeArguments.length = typeParameters!.length; } } return typeArguments; @@ -7220,8 +7240,8 @@ namespace ts { const parameters: Symbol[] = []; let hasLiteralTypes = false; let minArgumentCount = 0; - let thisParameter: Symbol; - let hasThisParameter: boolean; + let thisParameter: Symbol | undefined; + let hasThisParameter = false; const iife = getImmediatelyInvokedFunctionExpression(declaration); const isJSConstructSignature = isJSDocConstructSignature(declaration); const isUntypedSignatureInJSFile = !iife && @@ -7241,7 +7261,7 @@ namespace ts { // Include parameter symbol instead of property symbol in the signature if (paramSymbol && !!(paramSymbol.flags & SymbolFlags.Property) && !isBindingPattern(param.name)) { const resolvedSymbol = resolveName(param, paramSymbol.escapedName, SymbolFlags.Value, undefined, undefined, /*isUse*/ false); - paramSymbol = resolvedSymbol; + paramSymbol = resolvedSymbol!; } if (i === 0 && paramSymbol.escapedName === "this") { hasThisParameter = true; @@ -7314,9 +7334,9 @@ namespace ts { return true; } - function getSignatureReturnTypeFromDeclaration(declaration: SignatureDeclaration | JSDocSignature, isJSConstructSignature: boolean, classType: Type) { + function getSignatureReturnTypeFromDeclaration(declaration: SignatureDeclaration | JSDocSignature, isJSConstructSignature: boolean, classType: Type | undefined) { if (isJSConstructSignature) { - return getTypeFromTypeNode((declaration.parameters[0] as ParameterDeclaration).type); + return getTypeFromTypeNode((declaration.parameters[0] as ParameterDeclaration).type!); // TODO: GH#18217 } else if (classType) { return classType; @@ -7346,7 +7366,7 @@ namespace ts { links.containsArgumentsReference = true; } else { - links.containsArgumentsReference = traverse((declaration as FunctionLikeDeclaration).body); + links.containsArgumentsReference = traverse((declaration as FunctionLikeDeclaration).body!); } } return links.containsArgumentsReference; @@ -7361,21 +7381,21 @@ namespace ts { case SyntaxKind.MethodDeclaration: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: - return (node).name.kind === SyntaxKind.ComputedPropertyName - && traverse((node).name); + return (node).name!.kind === SyntaxKind.ComputedPropertyName + && traverse((node).name!); default: - return !nodeStartsNewLexicalEnvironment(node) && !isPartOfTypeNode(node) && forEachChild(node, traverse); + return !nodeStartsNewLexicalEnvironment(node) && !isPartOfTypeNode(node) && !!forEachChild(node, traverse); } } } - function getSignaturesOfSymbol(symbol: Symbol): Signature[] { + function getSignaturesOfSymbol(symbol: Symbol | undefined): Signature[] { if (!symbol) return emptyArray; const result: Signature[] = []; for (let i = 0; i < symbol.declarations.length; i++) { const decl = symbol.declarations[i]; - const node = isPropertyAccessExpression(decl) ? getAssignedJavascriptInitializer(decl) : decl; + const node = isPropertyAccessExpression(decl) ? getAssignedJavascriptInitializer(decl)! : decl; // TODO: GH#18217 if (!isFunctionLike(node)) continue; // Don't include signature if node is the implementation of an overloaded function. A node is considered // an implementation node if it has a body and the previous node is of the same kind and immediately @@ -7417,7 +7437,7 @@ namespace ts { if (!signature.resolvedTypePredicate) { if (signature.target) { const targetTypePredicate = getTypePredicateOfSignature(signature.target); - signature.resolvedTypePredicate = targetTypePredicate ? instantiateTypePredicate(targetTypePredicate, signature.mapper) : noTypePredicate; + signature.resolvedTypePredicate = targetTypePredicate ? instantiateTypePredicate(targetTypePredicate, signature.mapper!) : noTypePredicate; } else if (signature.unionSignatures) { signature.resolvedTypePredicate = getUnionTypePredicate(signature.unionSignatures) || noTypePredicate; @@ -7440,7 +7460,7 @@ namespace ts { } let type: Type; if (signature.target) { - type = instantiateType(getReturnTypeOfSignature(signature.target), signature.mapper); + type = instantiateType(getReturnTypeOfSignature(signature.target), signature.mapper!); } else if (signature.unionSignatures) { type = getUnionType(map(signature.unionSignatures, getReturnTypeOfSignature), UnionReduction.Subtype); @@ -7472,16 +7492,16 @@ namespace ts { function getRestTypeOfSignature(signature: Signature): Type { if (signature.hasRestParameter) { - const type = getTypeOfSymbol(lastOrUndefined(signature.parameters)); + const type = getTypeOfSymbol(last(signature.parameters)); if (getObjectFlags(type) & ObjectFlags.Reference && (type).target === globalArrayType) { - return (type).typeArguments[0]; + return (type).typeArguments![0]; } } return anyType; } - function getSignatureInstantiation(signature: Signature, typeArguments: Type[], isJavascript: boolean): Signature { - typeArguments = fillMissingTypeArguments(typeArguments, signature.typeParameters, getMinTypeArgumentCount(signature.typeParameters), isJavascript); + function getSignatureInstantiation(signature: Signature, typeArguments: Type[] | undefined, isJavascript: boolean): Signature { + typeArguments = fillMissingTypeArguments(typeArguments, signature.typeParameters, getMinTypeArgumentCount(signature.typeParameters), isJavascript)!; const instantiations = signature.instantiations || (signature.instantiations = createMap()); const id = getTypeListId(typeArguments); let instantiation = instantiations.get(id); @@ -7495,7 +7515,7 @@ namespace ts { return instantiateSignature(signature, createSignatureTypeMapper(signature, typeArguments), /*eraseTypeParameters*/ true); } function createSignatureTypeMapper(signature: Signature, typeArguments: Type[]): TypeMapper { - return createTypeMapper(signature.typeParameters, typeArguments); + return createTypeMapper(signature.typeParameters!, typeArguments); } function getErasedSignature(signature: Signature): Signature { @@ -7506,7 +7526,7 @@ namespace ts { function createErasedSignature(signature: Signature) { // Create an instantiation of the signature where all type arguments are the any type. - return instantiateSignature(signature, createTypeEraser(signature.typeParameters), /*eraseTypeParameters*/ true); + return instantiateSignature(signature, createTypeEraser(signature.typeParameters!), /*eraseTypeParameters*/ true); } function getCanonicalSignature(signature: Signature): Signature { @@ -7544,7 +7564,7 @@ namespace ts { // object type literal or interface (using the new keyword). Each way of declaring a constructor // will result in a different declaration kind. if (!signature.isolatedSignatureType) { - const isConstructor = signature.declaration.kind === SyntaxKind.Constructor || signature.declaration.kind === SyntaxKind.ConstructSignature; + const isConstructor = signature.declaration!.kind === SyntaxKind.Constructor || signature.declaration!.kind === SyntaxKind.ConstructSignature; // TODO: GH#18217 const type = createObjectType(ObjectFlags.Anonymous); type.members = emptySymbols; type.properties = emptyArray; @@ -7556,11 +7576,11 @@ namespace ts { return signature.isolatedSignatureType; } - function getIndexSymbol(symbol: Symbol): Symbol { - return symbol.members.get(InternalSymbolName.Index); + function getIndexSymbol(symbol: Symbol): Symbol | undefined { + return symbol.members!.get(InternalSymbolName.Index); } - function getIndexDeclarationOfSymbol(symbol: Symbol, kind: IndexKind): IndexSignatureDeclaration { + function getIndexDeclarationOfSymbol(symbol: Symbol, kind: IndexKind): IndexSignatureDeclaration | undefined { const syntaxKind = kind === IndexKind.Number ? SyntaxKind.NumberKeyword : SyntaxKind.StringKeyword; const indexSymbol = getIndexSymbol(symbol); if (indexSymbol) { @@ -7582,7 +7602,7 @@ namespace ts { return { type, isReadonly, declaration }; } - function getIndexInfoOfSymbol(symbol: Symbol, kind: IndexKind): IndexInfo { + function getIndexInfoOfSymbol(symbol: Symbol, kind: IndexKind): IndexInfo | undefined { const declaration = getIndexDeclarationOfSymbol(symbol, kind); if (declaration) { return createIndexInfo(declaration.type ? getTypeFromTypeNode(declaration.type) : anyType, @@ -7597,7 +7617,7 @@ namespace ts { } function getInferredTypeParameterConstraint(typeParameter: TypeParameter) { - let inferences: Type[]; + let inferences: Type[] | undefined; if (typeParameter.symbol) { for (const declaration of typeParameter.symbol.declarations) { // When an 'infer T' declaration is immediately contained in a type reference node @@ -7608,7 +7628,7 @@ namespace ts { const typeReference = declaration.parent.parent; const typeParameters = getTypeParametersForTypeReference(typeReference); if (typeParameters) { - const index = typeReference.typeArguments.indexOf(declaration.parent); + const index = typeReference.typeArguments!.indexOf(declaration.parent); if (index < typeParameters.length) { const declaredConstraint = getConstraintOfTypeParameter(typeParameters[index]); if (declaredConstraint) { @@ -7632,11 +7652,11 @@ namespace ts { return inferences && getIntersectionType(inferences); } - function getConstraintFromTypeParameter(typeParameter: TypeParameter): Type { + function getConstraintFromTypeParameter(typeParameter: TypeParameter): Type | undefined { if (!typeParameter.constraint) { if (typeParameter.target) { const targetConstraint = getConstraintOfTypeParameter(typeParameter.target); - typeParameter.constraint = targetConstraint ? instantiateType(targetConstraint, typeParameter.mapper) : noConstraintType; + typeParameter.constraint = targetConstraint ? instantiateType(targetConstraint, typeParameter.mapper!) : noConstraintType; } else { const constraintDeclaration = getConstraintDeclaration(typeParameter); @@ -7647,11 +7667,11 @@ namespace ts { return typeParameter.constraint === noConstraintType ? undefined : typeParameter.constraint; } - function getParentSymbolOfTypeParameter(typeParameter: TypeParameter): Symbol { - return getSymbolOfNode(getDeclarationOfKind(typeParameter.symbol, SyntaxKind.TypeParameter).parent); + function getParentSymbolOfTypeParameter(typeParameter: TypeParameter): Symbol | undefined { + return getSymbolOfNode(getDeclarationOfKind(typeParameter.symbol, SyntaxKind.TypeParameter)!.parent); } - function getTypeListId(types: Type[]) { + function getTypeListId(types: Type[] | undefined) { let result = ""; if (types) { const length = types.length; @@ -7689,7 +7709,7 @@ namespace ts { return result & TypeFlags.PropagatingFlags; } - function createTypeReference(target: GenericType, typeArguments: Type[]): TypeReference { + function createTypeReference(target: GenericType, typeArguments: Type[] | undefined): TypeReference { const id = getTypeListId(typeArguments); let type = target.instantiations.get(id); if (!type) { @@ -7718,7 +7738,7 @@ namespace ts { /** * Get type from type-reference that reference to class or interface */ - function getTypeFromClassOrInterfaceReference(node: NodeWithTypeArguments, symbol: Symbol, typeArgs: Type[]): Type { + function getTypeFromClassOrInterfaceReference(node: NodeWithTypeArguments, symbol: Symbol, typeArgs: Type[] | undefined): Type { const type = getDeclaredTypeOfSymbol(getMergedSymbol(symbol)); const typeParameters = type.localTypeParameters; if (typeParameters) { @@ -7751,14 +7771,14 @@ namespace ts { return checkNoTypeArguments(node, symbol) ? type : unknownType; } - function getTypeAliasInstantiation(symbol: Symbol, typeArguments: Type[]): Type { + function getTypeAliasInstantiation(symbol: Symbol, typeArguments: Type[] | undefined): Type { const type = getDeclaredTypeOfSymbol(symbol); const links = getSymbolLinks(symbol); - const typeParameters = links.typeParameters; + const typeParameters = links.typeParameters!; const id = getTypeListId(typeArguments); - let instantiation = links.instantiations.get(id); + let instantiation = links.instantiations!.get(id); if (!instantiation) { - links.instantiations.set(id, instantiation = instantiateType(type, createTypeMapper(typeParameters, fillMissingTypeArguments(typeArguments, typeParameters, getMinTypeArgumentCount(typeParameters), isInJavaScriptFile(symbol.valueDeclaration))))); + links.instantiations!.set(id, instantiation = instantiateType(type, createTypeMapper(typeParameters, fillMissingTypeArguments(typeArguments, typeParameters, getMinTypeArgumentCount(typeParameters), isInJavaScriptFile(symbol.valueDeclaration))))); } return instantiation; } @@ -7768,7 +7788,7 @@ namespace ts { * references to the type parameters of the alias. We replace those with the actual type arguments by instantiating the * declared type. Instantiations are cached using the type identities of the type arguments as the key. */ - function getTypeFromTypeAliasReference(node: NodeWithTypeArguments, symbol: Symbol, typeArguments: Type[]): Type { + function getTypeFromTypeAliasReference(node: NodeWithTypeArguments, symbol: Symbol, typeArguments: Type[] | undefined): Type { const type = getDeclaredTypeOfSymbol(symbol); const typeParameters = getSymbolLinks(symbol).typeParameters; if (typeParameters) { @@ -7806,7 +7826,7 @@ namespace ts { return undefined; } - function resolveTypeReferenceName(typeReferenceName: EntityNameExpression | EntityName, meaning: SymbolFlags) { + function resolveTypeReferenceName(typeReferenceName: EntityNameExpression | EntityName | undefined, meaning: SymbolFlags) { if (!typeReferenceName) { return unknownSymbol; } @@ -7814,7 +7834,7 @@ namespace ts { return resolveEntityName(typeReferenceName, meaning) || unknownSymbol; } - function getTypeReferenceType(node: NodeWithTypeArguments, symbol: Symbol) { + function getTypeReferenceType(node: NodeWithTypeArguments, symbol: Symbol): Type { const typeArguments = typeArgumentsFromTypeReferenceNode(node); // Do unconditionally so we mark type arguments as referenced. if (symbol === unknownSymbol) { return unknownType; @@ -7852,16 +7872,17 @@ namespace ts { * the symbol is a constructor function, return the inferred class type; otherwise, * the type of this reference is just the type of the value we resolved to. */ - function getJSDocTypeReference(node: NodeWithTypeArguments, symbol: Symbol, typeArguments: Type[]): Type | undefined { + function getJSDocTypeReference(node: NodeWithTypeArguments, symbol: Symbol, typeArguments: Type[] | undefined): Type | undefined { const assignedType = getAssignedClassType(symbol); const valueType = getTypeOfSymbol(symbol); const referenceType = valueType.symbol && valueType.symbol !== symbol && !isInferredClassType(valueType) && getTypeReferenceTypeWorker(node, valueType.symbol, typeArguments); if (referenceType || assignedType) { - return referenceType && assignedType ? getIntersectionType([assignedType, referenceType]) : referenceType || assignedType; + // TODO: GH#18217 (should the `|| assignedType` be at a lower precedence?) + return (referenceType && assignedType ? getIntersectionType([assignedType, referenceType]) : referenceType || assignedType)!; } } - function getTypeReferenceTypeWorker(node: NodeWithTypeArguments, symbol: Symbol, typeArguments: Type[]): Type | undefined { + function getTypeReferenceTypeWorker(node: NodeWithTypeArguments, symbol: Symbol, typeArguments: Type[] | undefined): Type | undefined { if (symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) { if (symbol.valueDeclaration && isBinaryExpression(symbol.valueDeclaration.parent)) { const jsdocType = getJSDocTypeReference(node, symbol, typeArguments); @@ -7894,14 +7915,14 @@ namespace ts { return node.kind === SyntaxKind.TupleType && (node).elementTypes.length === 1; } - function getImpliedConstraint(typeVariable: TypeVariable, checkNode: TypeNode, extendsNode: TypeNode): Type { + function getImpliedConstraint(typeVariable: TypeVariable, checkNode: TypeNode, extendsNode: TypeNode): Type | undefined { return isUnaryTupleTypeNode(checkNode) && isUnaryTupleTypeNode(extendsNode) ? getImpliedConstraint(typeVariable, (checkNode).elementTypes[0], (extendsNode).elementTypes[0]) : getActualTypeVariable(getTypeFromTypeNode(checkNode)) === typeVariable ? getTypeFromTypeNode(extendsNode) : undefined; } function getConstrainedTypeVariable(typeVariable: TypeVariable, node: Node) { - let constraints: Type[]; + let constraints: Type[] | undefined; while (node && !isStatement(node) && node.kind !== SyntaxKind.JSDocComment) { const parent = node.parent; if (parent.kind === SyntaxKind.ConditionalType && node === (parent).trueType) { @@ -7916,7 +7937,7 @@ namespace ts { } function isJSDocTypeReference(node: Node): node is TypeReferenceNode { - return node.flags & NodeFlags.JSDoc && node.kind === SyntaxKind.TypeReference; + return !!(node.flags & NodeFlags.JSDoc) && node.kind === SyntaxKind.TypeReference; } function checkNoTypeArguments(node: NodeWithTypeArguments, symbol?: Symbol) { @@ -7927,7 +7948,7 @@ namespace ts { return true; } - function getIntendedTypeFromJSDocTypeReference(node: TypeReferenceNode): Type { + function getIntendedTypeFromJSDocTypeReference(node: TypeReferenceNode): Type | undefined { if (isIdentifier(node.typeName)) { const typeArgs = node.typeArguments; switch (node.typeName.escapedText) { @@ -7965,7 +7986,7 @@ namespace ts { const indexed = getTypeFromTypeNode(typeArgs[0]); const target = getTypeFromTypeNode(typeArgs[1]); const index = createIndexInfo(target, /*isReadonly*/ false); - return createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, indexed === stringType && index, indexed === numberType && index); + return createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, indexed === stringType ? index : undefined, indexed === numberType ? index : undefined); } return anyType; } @@ -7983,8 +8004,8 @@ namespace ts { function getTypeFromTypeReference(node: TypeReferenceType): Type { const links = getNodeLinks(node); if (!links.resolvedType) { - let symbol: Symbol; - let type: Type; + let symbol: Symbol | undefined; + let type: Type | undefined; let meaning = SymbolFlags.Type; if (isJSDocTypeReference(node)) { type = getIntendedTypeFromJSDocTypeReference(node); @@ -8002,7 +8023,7 @@ namespace ts { return links.resolvedType; } - function typeArgumentsFromTypeReferenceNode(node: NodeWithTypeArguments): Type[] { + function typeArgumentsFromTypeReferenceNode(node: NodeWithTypeArguments): Type[] | undefined { return map(node.typeArguments, getTypeFromTypeNode); } @@ -8018,9 +8039,9 @@ namespace ts { return links.resolvedType; } - function getTypeOfGlobalSymbol(symbol: Symbol, arity: number): ObjectType { + function getTypeOfGlobalSymbol(symbol: Symbol | undefined, arity: number): ObjectType { - function getTypeDeclaration(symbol: Symbol): Declaration { + function getTypeDeclaration(symbol: Symbol): Declaration | undefined { const declarations = symbol.declarations; for (const declaration of declarations) { switch (declaration.kind) { @@ -8047,22 +8068,22 @@ namespace ts { return type; } - function getGlobalValueSymbol(name: __String, reportErrors: boolean): Symbol { + function getGlobalValueSymbol(name: __String, reportErrors: boolean): Symbol | undefined { return getGlobalSymbol(name, SymbolFlags.Value, reportErrors ? Diagnostics.Cannot_find_global_value_0 : undefined); } - function getGlobalTypeSymbol(name: __String, reportErrors: boolean): Symbol { + function getGlobalTypeSymbol(name: __String, reportErrors: boolean): Symbol | undefined { return getGlobalSymbol(name, SymbolFlags.Type, reportErrors ? Diagnostics.Cannot_find_global_type_0 : undefined); } - function getGlobalSymbol(name: __String, meaning: SymbolFlags, diagnostic: DiagnosticMessage): Symbol { + function getGlobalSymbol(name: __String, meaning: SymbolFlags, diagnostic: DiagnosticMessage | undefined): Symbol | undefined { // Don't track references for global symbols anyway, so value if `isReference` is arbitrary return resolveName(undefined, name, meaning, diagnostic, name, /*isUse*/ false); } function getGlobalType(name: __String, arity: 0, reportErrors: boolean): ObjectType; function getGlobalType(name: __String, arity: number, reportErrors: boolean): GenericType; - function getGlobalType(name: __String, arity: number, reportErrors: boolean): ObjectType { + function getGlobalType(name: __String, arity: number, reportErrors: boolean): ObjectType | undefined { const symbol = getGlobalTypeSymbol(name, reportErrors); return symbol || reportErrors ? getTypeOfGlobalSymbol(symbol, arity) : undefined; } @@ -8123,13 +8144,13 @@ namespace ts { return deferredGlobalIterableIteratorType || (deferredGlobalIterableIteratorType = getGlobalType("IterableIterator" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType; } - function getGlobalTypeOrUndefined(name: __String, arity = 0): ObjectType { + function getGlobalTypeOrUndefined(name: __String, arity = 0): ObjectType | undefined { const symbol = getGlobalSymbol(name, SymbolFlags.Type, /*diagnostic*/ undefined); return symbol && getTypeOfGlobalSymbol(symbol, arity); } function getGlobalExtractSymbol(): Symbol { - return deferredGlobalExtractSymbol || (deferredGlobalExtractSymbol = getGlobalSymbol("Extract" as __String, SymbolFlags.TypeAlias, Diagnostics.Cannot_find_global_type_0)); + return deferredGlobalExtractSymbol || (deferredGlobalExtractSymbol = getGlobalSymbol("Extract" as __String, SymbolFlags.TypeAlias, Diagnostics.Cannot_find_global_type_0)!); // TODO: GH#18217 } /** @@ -8404,7 +8425,7 @@ namespace ts { return getUnionTypeFromSortedList(typeSet, includes & TypeFlags.NotUnit ? 0 : TypeFlags.UnionOfUnitTypes, aliasSymbol, aliasTypeArguments); } - function getUnionTypePredicate(signatures: ReadonlyArray): TypePredicate { + function getUnionTypePredicate(signatures: ReadonlyArray): TypePredicate | undefined { let first: TypePredicate | undefined; const types: Type[] = []; for (const sig of signatures) { @@ -8681,7 +8702,7 @@ namespace ts { return indexType.flags & TypeFlags.Never ? stringType : indexType; } - function getTypeFromTypeOperatorNode(node: TypeOperatorNode) { + function getTypeFromTypeOperatorNode(node: TypeOperatorNode): Type { const links = getNodeLinks(node); if (!links.resolvedType) { switch (node.operator) { @@ -8695,7 +8716,7 @@ namespace ts { break; } } - return links.resolvedType; + return links.resolvedType!; // TODO: GH#18217 } function createIndexedAccessType(objectType: Type, indexType: Type) { @@ -8705,7 +8726,7 @@ namespace ts { return type; } - function getPropertyTypeForIndexType(objectType: Type, indexType: Type, accessNode: ElementAccessExpression | IndexedAccessTypeNode, cacheSymbol: boolean) { + function getPropertyTypeForIndexType(objectType: Type, indexType: Type, accessNode: ElementAccessExpression | IndexedAccessTypeNode | undefined, cacheSymbol: boolean) { const accessExpression = accessNode && accessNode.kind === SyntaxKind.ElementAccessExpression ? accessNode : undefined; const propName = isTypeUsableAsLateBoundName(indexType) ? getLateBoundNameFromType(indexType) : accessExpression && checkThatExpressionIsProperSymbolReference(accessExpression.argumentExpression, indexType, /*reportError*/ false) ? @@ -8721,7 +8742,7 @@ namespace ts { return unknownType; } if (cacheSymbol) { - getNodeLinks(accessNode).resolvedSymbol = prop; + getNodeLinks(accessNode!).resolvedSymbol = prop; } } return getTypeOfSymbol(prop); @@ -8784,18 +8805,18 @@ namespace ts { // Return true if the given type is a non-generic object type with a string index signature and no // other members. - function isStringIndexOnlyType(type: Type) { + function isStringIndexOnlyType(type: Type): boolean { if (type.flags & TypeFlags.Object && !isGenericMappedType(type)) { const t = resolveStructuredTypeMembers(type); return t.properties.length === 0 && t.callSignatures.length === 0 && t.constructSignatures.length === 0 && - t.stringIndexInfo && !t.numberIndexInfo; + !!t.stringIndexInfo && !t.numberIndexInfo; } return false; } - function isMappedTypeToNever(type: Type) { - return getObjectFlags(type) & ObjectFlags.Mapped && getTemplateTypeFromMappedType(type as MappedType) === neverType; + function isMappedTypeToNever(type: Type): boolean { + return !!(getObjectFlags(type) & ObjectFlags.Mapped) && getTemplateTypeFromMappedType(type as MappedType) === neverType; } function getSimplifiedType(type: Type): Type { @@ -8820,7 +8841,7 @@ namespace ts { const stringIndexTypes: Type[] = []; for (const t of (objectType).types) { if (isStringIndexOnlyType(t)) { - stringIndexTypes.push(getIndexTypeOfType(t, IndexKind.String)); + stringIndexTypes.push(getIndexTypeOfType(t, IndexKind.String)!); } else { regularTypes.push(t); @@ -8934,7 +8955,7 @@ namespace ts { return type.flags & TypeFlags.Substitution ? (type).typeVariable : type; } - function getConditionalType(root: ConditionalRoot, mapper: TypeMapper): Type { + function getConditionalType(root: ConditionalRoot, mapper: TypeMapper | undefined): Type { const checkType = instantiateType(root.checkType, mapper); const extendsType = instantiateType(root.extendsType, mapper); if (checkType === wildcardType || extendsType === wildcardType) { @@ -8944,7 +8965,7 @@ namespace ts { // resolution of the conditional type such that a later instantiation will properly distribute // over union types. const isDeferred = root.isDistributive && maybeTypeOfKind(checkType, TypeFlags.Instantiable); - let combinedMapper: TypeMapper; + let combinedMapper: TypeMapper | undefined; if (root.inferTypeParameters) { const context = createInferenceContext(root.inferTypeParameters, /*signature*/ undefined, InferenceFlags.None); if (!isDeferred) { @@ -8986,7 +9007,7 @@ namespace ts { result.mapper = mapper; result.combinedMapper = combinedMapper; result.aliasSymbol = root.aliasSymbol; - result.aliasTypeArguments = instantiateTypes(root.aliasTypeArguments, mapper); + result.aliasTypeArguments = instantiateTypes(root.aliasTypeArguments, mapper!); // TODO: GH#18217 return result; } @@ -8998,8 +9019,8 @@ namespace ts { return type.resolvedFalseType || (type.resolvedFalseType = instantiateType(type.root.falseType, type.mapper)); } - function getInferTypeParameters(node: ConditionalTypeNode): TypeParameter[] { - let result: TypeParameter[]; + function getInferTypeParameters(node: ConditionalTypeNode): TypeParameter[] | undefined { + let result: TypeParameter[] | undefined; if (node.locals) { node.locals.forEach(symbol => { if (symbol.flags & SymbolFlags.TypeParameter) { @@ -9096,7 +9117,7 @@ namespace ts { } const moduleSymbol = resolveExternalModuleSymbol(innerModuleSymbol, /*dontResolveAlias*/ false); if (!nodeIsMissing(node.qualifier)) { - const nameStack: Identifier[] = getIdentifierChain(node.qualifier); + const nameStack: Identifier[] = getIdentifierChain(node.qualifier!); let currentNamespace = moduleSymbol; let current: Identifier | undefined; while (current = nameStack.shift()) { @@ -9123,7 +9144,7 @@ namespace ts { } } } - return links.resolvedType; + return links.resolvedType!; // TODO: GH#18217 } function resolveImportSymbolType(node: ImportTypeNode, links: NodeLinks, symbol: Symbol, meaning: SymbolFlags) { @@ -9161,7 +9182,7 @@ namespace ts { return isTypeAlias(node.parent) ? getSymbolOfNode(node.parent) : undefined; } - function getTypeArgumentsForAliasSymbol(symbol: Symbol) { + function getTypeArgumentsForAliasSymbol(symbol: Symbol | undefined) { return symbol ? getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol) : undefined; } @@ -9170,7 +9191,7 @@ namespace ts { * this function should be called in a left folding style, with left = previous result of getSpreadType * and right = the new element to be spread. */ - function getSpreadType(left: Type, right: Type, symbol: Symbol, typeFlags: TypeFlags, objectFlags: ObjectFlags): Type { + function getSpreadType(left: Type, right: Type, symbol: Symbol | undefined, typeFlags: TypeFlags, objectFlags: ObjectFlags): Type { if (left.flags & TypeFlags.Any || right.flags & TypeFlags.Any) { return anyType; } @@ -9192,8 +9213,8 @@ namespace ts { const members = createSymbolTable(); const skippedPrivateMembers = createUnderscoreEscapedMap(); - let stringIndexInfo: IndexInfo; - let numberIndexInfo: IndexInfo; + let stringIndexInfo: IndexInfo | undefined; + let numberIndexInfo: IndexInfo | undefined; if (left === emptyObjectType) { // for the first spread element, left === emptyObjectType, so take the right's string indexer stringIndexInfo = getIndexInfoOfType(right, IndexKind.String); @@ -9222,10 +9243,10 @@ namespace ts { continue; } if (members.has(leftProp.escapedName)) { - const rightProp = members.get(leftProp.escapedName); + const rightProp = members.get(leftProp.escapedName)!; const rightType = getTypeOfSymbol(rightProp); if (rightProp.flags & SymbolFlags.Optional) { - const declarations: Declaration[] = concatenate(leftProp.declarations, rightProp.declarations); + const declarations = concatenate(leftProp.declarations, rightProp.declarations); const flags = SymbolFlags.Property | (leftProp.flags & SymbolFlags.Optional); const result = createSymbol(flags, leftProp.escapedName); result.type = getUnionType([getTypeOfSymbol(leftProp), getTypeWithFacts(rightType, TypeFacts.NEUndefined)]); @@ -9266,7 +9287,7 @@ namespace ts { return result; } - function getNonReadonlyIndexSignature(index: IndexInfo) { + function getNonReadonlyIndexSignature(index: IndexInfo | undefined) { if (index && index.isReadonly) { return createIndexInfo(index.type, /*isReadonly*/ false, index.declaration); } @@ -9277,14 +9298,14 @@ namespace ts { return prop.flags & SymbolFlags.Method && find(prop.declarations, decl => isClassLike(decl.parent)); } - function createLiteralType(flags: TypeFlags, value: string | number, symbol: Symbol) { + function createLiteralType(flags: TypeFlags, value: string | number, symbol: Symbol | undefined) { const type = createType(flags); - type.symbol = symbol; + type.symbol = symbol!; type.value = value; return type; } - function getFreshTypeOfLiteralType(type: Type) { + function getFreshTypeOfLiteralType(type: Type): Type { if (type.flags & TypeFlags.StringOrNumberLiteral && !(type.flags & TypeFlags.FreshLiteral)) { if (!(type).freshType) { const freshType = createLiteralType(type.flags | TypeFlags.FreshLiteral, (type).value, (type).symbol); @@ -9345,8 +9366,8 @@ namespace ts { const parent = container && container.parent; if (parent && (isClassLike(parent) || parent.kind === SyntaxKind.InterfaceDeclaration)) { if (!hasModifier(container, ModifierFlags.Static) && - (container.kind !== SyntaxKind.Constructor || isNodeDescendantOf(node, (container).body))) { - return getDeclaredTypeOfClassOrInterface(getSymbolOfNode(parent)).thisType; + (container.kind !== SyntaxKind.Constructor || isNodeDescendantOf(node, (container).body!))) { + return getDeclaredTypeOfClassOrInterface(getSymbolOfNode(parent as ClassLikeDeclaration | InterfaceDeclaration)).thisType!; } } error(node, Diagnostics.A_this_type_is_available_only_in_a_non_static_member_of_a_class_or_interface); @@ -9440,13 +9461,15 @@ namespace ts { case SyntaxKind.Identifier: case SyntaxKind.QualifiedName: const symbol = getSymbolAtLocation(node); - return symbol && getDeclaredTypeOfSymbol(symbol); + return (symbol && getDeclaredTypeOfSymbol(symbol))!; // TODO: GH#18217 default: return unknownType; } } - function instantiateList(items: T[], mapper: TypeMapper, instantiator: (item: T, mapper: TypeMapper) => T): T[] { + function instantiateList(items: T[], mapper: TypeMapper, instantiator: (item: T, mapper: TypeMapper) => T): T[]; + function instantiateList(items: T[] | undefined, mapper: TypeMapper, instantiator: (item: T, mapper: TypeMapper) => T): T[] | undefined; + function instantiateList(items: T[] | undefined, mapper: TypeMapper, instantiator: (item: T, mapper: TypeMapper) => T): T[] | undefined { if (items && items.length) { for (let i = 0; i < items.length; i++) { const item = items[i]; @@ -9464,11 +9487,13 @@ namespace ts { return items; } - function instantiateTypes(types: Type[], mapper: TypeMapper) { + function instantiateTypes(types: Type[], mapper: TypeMapper): Type[]; + function instantiateTypes(types: Type[] | undefined, mapper: TypeMapper): Type[] | undefined; + function instantiateTypes(types: Type[] | undefined, mapper: TypeMapper) { return instantiateList(types, mapper, instantiateType); } - function instantiateSignatures(signatures: Signature[], mapper: TypeMapper) { + function instantiateSignatures(signatures: Signature[], mapper: TypeMapper): Signature[] { return instantiateList(signatures, mapper, instantiateSignature); } @@ -9480,7 +9505,7 @@ namespace ts { return (t: Type) => t === source1 ? target1 : t === source2 ? target2 : t; } - function makeArrayTypeMapper(sources: Type[], targets: Type[]) { + function makeArrayTypeMapper(sources: Type[], targets: Type[] | undefined) { return (t: Type) => { for (let i = 0; i < sources.length; i++) { if (t === sources[i]) { @@ -9491,7 +9516,7 @@ namespace ts { }; } - function createTypeMapper(sources: TypeParameter[], targets: Type[]): TypeMapper { + function createTypeMapper(sources: TypeParameter[], targets: Type[] | undefined): TypeMapper { Debug.assert(targets === undefined || sources.length === targets.length); return sources.length === 1 ? makeUnaryTypeMapper(sources[0], targets ? targets[0] : anyType) : sources.length === 2 ? makeBinaryTypeMapper(sources[0], targets ? targets[0] : anyType, sources[1], targets ? targets[1] : anyType) : @@ -9520,6 +9545,8 @@ namespace ts { mapper; } + function combineTypeMappers(mapper1: TypeMapper | undefined, mapper2: TypeMapper): TypeMapper; + function combineTypeMappers(mapper1: TypeMapper, mapper2: TypeMapper | undefined): TypeMapper; function combineTypeMappers(mapper1: TypeMapper, mapper2: TypeMapper): TypeMapper { if (!mapper1) return mapper2; if (!mapper2) return mapper1; @@ -9559,7 +9586,7 @@ namespace ts { } function instantiateSignature(signature: Signature, mapper: TypeMapper, eraseTypeParameters?: boolean): Signature { - let freshTypeParameters: TypeParameter[]; + let freshTypeParameters: TypeParameter[] | undefined; if (signature.typeParameters && !eraseTypeParameters) { // First create a fresh set of type parameters, then include a mapping from the old to the // new type parameters in the mapper function. Finally store this mapper in the new type @@ -9597,8 +9624,8 @@ namespace ts { // If symbol being instantiated is itself a instantiation, fetch the original target and combine the // type mappers. This ensures that original type identities are properly preserved and that aliases // always reference a non-aliases. - symbol = links.target; - mapper = combineTypeMappers(links.mapper, mapper); + symbol = links.target!; + mapper = combineTypeMappers(links.mapper!, mapper); } // Keep the flags from the symbol we're instantiating. Mark that is instantiated, and // also transient so that we can just store data on it directly. @@ -9622,8 +9649,8 @@ namespace ts { } function getAnonymousTypeInstantiation(type: AnonymousType, mapper: TypeMapper) { - const target = type.objectFlags & ObjectFlags.Instantiated ? type.target : type; - const symbol = target.symbol; + const target = type.objectFlags & ObjectFlags.Instantiated ? type.target! : type; + const { symbol } = target; const links = getSymbolLinks(symbol); let typeParameters = links.outerTypeParameters; if (!typeParameters) { @@ -9660,14 +9687,14 @@ namespace ts { // We are instantiating an anonymous type that has one or more type parameters in scope. Apply the // mapper to the type parameters to produce the effective list of type arguments, and compute the // instantiation cache key from the type IDs of the type arguments. - const combinedMapper = type.objectFlags & ObjectFlags.Instantiated ? combineTypeMappers(type.mapper, mapper) : mapper; - const typeArguments = map(typeParameters, combinedMapper); + const combinedMapper = type.objectFlags & ObjectFlags.Instantiated ? combineTypeMappers(type.mapper!, mapper) : mapper; + const typeArguments: Type[] = map(typeParameters, combinedMapper); const id = getTypeListId(typeArguments); - let result = links.instantiations.get(id); + let result = links.instantiations!.get(id); if (!result) { const newMapper = createTypeMapper(typeParameters, typeArguments); result = target.objectFlags & ObjectFlags.Mapped ? instantiateMappedType(target, newMapper) : instantiateAnonymousType(target, newMapper); - links.instantiations.set(id, result); + links.instantiations!.set(id, result); } return result; } @@ -9686,21 +9713,21 @@ namespace ts { if (tp.symbol && tp.symbol.declarations && tp.symbol.declarations.length === 1) { const container = tp.symbol.declarations[0].parent; if (findAncestor(node, n => n.kind === SyntaxKind.Block ? "quit" : n === container)) { - return forEachChild(node, containsReference); + return !!forEachChild(node, containsReference); } } return true; function containsReference(node: Node): boolean { switch (node.kind) { case SyntaxKind.ThisType: - return tp.isThisType; + return !!tp.isThisType; case SyntaxKind.Identifier: return !tp.isThisType && isPartOfTypeNode(node) && maybeTypeParameterReference(node) && getTypeFromTypeNode(node) === tp; case SyntaxKind.TypeQuery: return true; } - return forEachChild(node, containsReference); + return !!forEachChild(node, containsReference); } } @@ -9752,11 +9779,11 @@ namespace ts { // instantiation cache key from the type IDs of the type arguments. const typeArguments = map(root.outerTypeParameters, mapper); const id = getTypeListId(typeArguments); - let result = root.instantiations.get(id); + let result = root.instantiations!.get(id); if (!result) { const newMapper = createTypeMapper(root.outerTypeParameters, typeArguments); result = instantiateConditionalType(root, newMapper); - root.instantiations.set(id, result); + root.instantiations!.set(id, result); } return result; } @@ -9777,7 +9804,9 @@ namespace ts { return getConditionalType(root, mapper); } - function instantiateType(type: Type, mapper: TypeMapper): Type { + function instantiateType(type: Type, mapper: TypeMapper | undefined): Type; + function instantiateType(type: Type | undefined, mapper: TypeMapper | undefined): Type | undefined; + function instantiateType(type: Type | undefined, mapper: TypeMapper | undefined): Type | undefined { if (type && mapper && mapper !== identityMapper) { if (type.flags & TypeFlags.TypeParameter) { return mapper(type); @@ -9830,7 +9859,7 @@ namespace ts { type.wildcardInstantiation || (type.wildcardInstantiation = instantiateType(type, wildcardMapper)); } - function instantiateIndexInfo(info: IndexInfo, mapper: TypeMapper): IndexInfo { + function instantiateIndexInfo(info: IndexInfo | undefined, mapper: TypeMapper): IndexInfo | undefined { return info && createIndexInfo(instantiateType(info.type, mapper), info.isReadonly, info.declaration); } @@ -9844,9 +9873,9 @@ namespace ts { case SyntaxKind.MethodDeclaration: return isContextSensitiveFunctionLikeDeclaration(node); case SyntaxKind.ObjectLiteralExpression: - return forEach((node).properties, isContextSensitive); + return some((node).properties, isContextSensitive); case SyntaxKind.ArrayLiteralExpression: - return forEach((node).elements, isContextSensitive); + return some((node).elements, isContextSensitive); case SyntaxKind.ConditionalExpression: return isContextSensitive((node).whenTrue) || isContextSensitive((node).whenFalse); @@ -9858,25 +9887,29 @@ namespace ts { case SyntaxKind.ParenthesizedExpression: return isContextSensitive((node).expression); case SyntaxKind.JsxAttributes: - return forEach((node).properties, isContextSensitive); - case SyntaxKind.JsxAttribute: + return some((node).properties, isContextSensitive); + case SyntaxKind.JsxAttribute: { // If there is no initializer, JSX attribute has a boolean value of true which is not context sensitive. - return (node).initializer && isContextSensitive((node).initializer); - case SyntaxKind.JsxExpression: + const { initializer } = node as JsxAttribute; + return !!initializer && isContextSensitive(initializer); + } + case SyntaxKind.JsxExpression: { // It is possible to that node.expression is undefined (e.g
) - return (node).expression && isContextSensitive((node).expression); + const { expression } = node as JsxExpression; + return !!expression && isContextSensitive(expression); + } } return false; } - function isContextSensitiveFunctionLikeDeclaration(node: FunctionLikeDeclaration) { + function isContextSensitiveFunctionLikeDeclaration(node: FunctionLikeDeclaration): boolean { // Functions with type parameters are not context sensitive. if (node.typeParameters) { return false; } // Functions with any parameters that lack type annotations are context sensitive. - if (forEach(node.parameters, p => !getEffectiveTypeAnnotationNode(p))) { + if (some(node.parameters, p => !getEffectiveTypeAnnotationNode(p))) { return true; } if (node.kind !== SyntaxKind.ArrowFunction) { @@ -9889,7 +9922,8 @@ namespace ts { } // TODO(anhans): A block should be context-sensitive if it has a context-sensitive return value. - return node.body.kind === SyntaxKind.Block ? false : isContextSensitive(node.body); + const body = node.body!; + return body.kind === SyntaxKind.Block ? false : isContextSensitive(body); } function isContextSensitiveFunctionOrObjectLiteralMethod(func: Node): func is FunctionExpression | ArrowFunction | MethodDeclaration { @@ -9971,7 +10005,7 @@ namespace ts { return isTypeComparableTo(type1, type2) || isTypeComparableTo(type2, type1); } - function checkTypeAssignableTo(source: Type, target: Type, errorNode: Node, headMessage?: DiagnosticMessage, containingMessageChain?: () => DiagnosticMessageChain | undefined): boolean { + function checkTypeAssignableTo(source: Type, target: Type, errorNode: Node | undefined, headMessage?: DiagnosticMessage, containingMessageChain?: () => DiagnosticMessageChain | undefined): boolean { return checkTypeRelatedTo(source, target, assignableRelation, errorNode, headMessage, containingMessageChain); } @@ -10000,7 +10034,7 @@ namespace ts { callbackCheck: CallbackCheck, ignoreReturnTypes: boolean, reportErrors: boolean, - errorReporter: ErrorReporter, + errorReporter: ErrorReporter | undefined, compareTypes: TypeComparer): Ternary { // TODO (drosen): De-duplicate code between related functions. if (source === target) { @@ -10029,7 +10063,7 @@ namespace ts { || compareTypes(targetThisType, sourceThisType, reportErrors); if (!related) { if (reportErrors) { - errorReporter(Diagnostics.The_this_types_of_each_signature_are_incompatible); + errorReporter!(Diagnostics.The_this_types_of_each_signature_are_incompatible); } return Ternary.False; } @@ -10058,11 +10092,12 @@ namespace ts { const callbacks = sourceSig && targetSig && !signatureHasTypePredicate(sourceSig) && !signatureHasTypePredicate(targetSig) && (getFalsyFlags(sourceType) & TypeFlags.Nullable) === (getFalsyFlags(targetType) & TypeFlags.Nullable); const related = callbacks ? - compareSignaturesRelated(targetSig, sourceSig, strictVariance ? CallbackCheck.Strict : CallbackCheck.Bivariant, /*ignoreReturnTypes*/ false, reportErrors, errorReporter, compareTypes) : + // TODO: GH#18217 It will work if they're both `undefined`, but not if only one is + compareSignaturesRelated(targetSig!, sourceSig!, strictVariance ? CallbackCheck.Strict : CallbackCheck.Bivariant, /*ignoreReturnTypes*/ false, reportErrors, errorReporter, compareTypes) : !callbackCheck && !strictVariance && compareTypes(sourceType, targetType, /*reportErrors*/ false) || compareTypes(targetType, sourceType, reportErrors); if (!related) { if (reportErrors) { - errorReporter(Diagnostics.Types_of_parameters_0_and_1_are_incompatible, + errorReporter!(Diagnostics.Types_of_parameters_0_and_1_are_incompatible, symbolName(sourceParams[i < sourceMax ? i : sourceMax]), symbolName(targetParams[i < targetMax ? i : targetMax])); } @@ -10083,11 +10118,11 @@ namespace ts { if (targetTypePredicate) { const sourceTypePredicate = getTypePredicateOfSignature(source); if (sourceTypePredicate) { - result &= compareTypePredicateRelatedTo(sourceTypePredicate, targetTypePredicate, source.declaration, target.declaration, reportErrors, errorReporter, compareTypes); + result &= compareTypePredicateRelatedTo(sourceTypePredicate, targetTypePredicate, source.declaration!, target.declaration!, reportErrors, errorReporter, compareTypes); // TODO: GH#18217 } else if (isIdentifierTypePredicate(targetTypePredicate)) { if (reportErrors) { - errorReporter(Diagnostics.Signature_0_must_be_a_type_predicate, signatureToString(source)); + errorReporter!(Diagnostics.Signature_0_must_be_a_type_predicate, signatureToString(source)); } return Ternary.False; } @@ -10111,12 +10146,12 @@ namespace ts { sourceDeclaration: SignatureDeclaration | JSDocSignature, targetDeclaration: SignatureDeclaration | JSDocSignature, reportErrors: boolean, - errorReporter: ErrorReporter, + errorReporter: ErrorReporter | undefined, compareTypes: (s: Type, t: Type, reportErrors?: boolean) => Ternary): Ternary { if (source.kind !== target.kind) { if (reportErrors) { - errorReporter(Diagnostics.A_this_based_type_guard_is_not_compatible_with_a_parameter_based_type_guard); - errorReporter(Diagnostics.Type_predicate_0_is_not_assignable_to_1, typePredicateToString(source), typePredicateToString(target)); + errorReporter!(Diagnostics.A_this_based_type_guard_is_not_compatible_with_a_parameter_based_type_guard); + errorReporter!(Diagnostics.Type_predicate_0_is_not_assignable_to_1, typePredicateToString(source), typePredicateToString(target)); } return Ternary.False; } @@ -10127,8 +10162,8 @@ namespace ts { const targetIndex = targetPredicate.parameterIndex - (getThisParameter(targetDeclaration) ? 1 : 0); if (sourceIndex !== targetIndex) { if (reportErrors) { - errorReporter(Diagnostics.Parameter_0_is_not_in_the_same_position_as_parameter_1, source.parameterName, targetPredicate.parameterName); - errorReporter(Diagnostics.Type_predicate_0_is_not_assignable_to_1, typePredicateToString(source), typePredicateToString(target)); + errorReporter!(Diagnostics.Parameter_0_is_not_in_the_same_position_as_parameter_1, source.parameterName, targetPredicate.parameterName); + errorReporter!(Diagnostics.Type_predicate_0_is_not_assignable_to_1, typePredicateToString(source), typePredicateToString(target)); } return Ternary.False; } @@ -10136,7 +10171,7 @@ namespace ts { const related = compareTypes(source.type, target.type, reportErrors); if (related === Ternary.False && reportErrors) { - errorReporter(Diagnostics.Type_predicate_0_is_not_assignable_to_1, typePredicateToString(source), typePredicateToString(target)); + errorReporter!(Diagnostics.Type_predicate_0_is_not_assignable_to_1, typePredicateToString(source), typePredicateToString(target)); } return related; } @@ -10195,8 +10230,8 @@ namespace ts { function isEmptyObjectType(type: Type): boolean { return type.flags & TypeFlags.Object ? isEmptyResolvedType(resolveStructuredTypeMembers(type)) : type.flags & TypeFlags.NonPrimitive ? true : - type.flags & TypeFlags.Union ? forEach((type).types, isEmptyObjectType) : - type.flags & TypeFlags.Intersection ? !forEach((type).types, t => !isEmptyObjectType(t)) : + type.flags & TypeFlags.Union ? some((type).types, isEmptyObjectType) : + type.flags & TypeFlags.Intersection ? !some((type).types, t => !isEmptyObjectType(t)) : false; } @@ -10251,7 +10286,7 @@ namespace ts { if (s & TypeFlags.Union && t & TypeFlags.Union && isEnumTypeRelatedTo(source.symbol, target.symbol, errorReporter)) return true; if (s & TypeFlags.Literal && t & TypeFlags.Literal && (source).value === (target).value && - isEnumTypeRelatedTo(getParentOfSymbol(source.symbol), getParentOfSymbol(target.symbol), errorReporter)) return true; + isEnumTypeRelatedTo(getParentOfSymbol(source.symbol)!, getParentOfSymbol(target.symbol)!, errorReporter)) return true; } if (s & TypeFlags.Undefined && (!strictNullChecks || t & (TypeFlags.Undefined | TypeFlags.Void))) return true; if (s & TypeFlags.Null && (!strictNullChecks || t & TypeFlags.Null)) return true; @@ -10310,11 +10345,11 @@ namespace ts { source: Type, target: Type, relation: Map, - errorNode: Node, + errorNode: Node | undefined, headMessage?: DiagnosticMessage, containingMessageChain?: () => DiagnosticMessageChain | undefined): boolean { - let errorInfo: DiagnosticMessageChain; + let errorInfo: DiagnosticMessageChain | undefined; let maybeKeys: string[]; let sourceStack: Type[]; let targetStack: Type[]; @@ -10338,13 +10373,13 @@ namespace ts { } } - diagnostics.add(createDiagnosticForNodeFromMessageChain(errorNode, errorInfo)); + diagnostics.add(createDiagnosticForNodeFromMessageChain(errorNode!, errorInfo)); // TODO: GH#18217 } // Check if we should issue an extra diagnostic to produce a quickfix for a slightly incorrect import statement if (headMessage && errorNode && !result && source.symbol) { const links = getSymbolLinks(source.symbol); if (links.originatingImport && !isImportCall(links.originatingImport)) { - const helpfulRetry = checkTypeRelatedTo(getTypeOfSymbol(links.target), target, relation, /*errorNode*/ undefined); + const helpfulRetry = checkTypeRelatedTo(getTypeOfSymbol(links.target!), target, relation, /*errorNode*/ undefined); if (helpfulRetry) { // Likely an incorrect import. Issue a helpful diagnostic to produce a quickfix to change the import diagnostics.add(createDiagnosticForNode(links.originatingImport, Diagnostics.A_namespace_style_import_cannot_be_called_or_constructed_and_will_cause_a_failure_at_runtime)); @@ -10358,7 +10393,7 @@ namespace ts { errorInfo = chainDiagnosticMessages(errorInfo, message, arg0, arg1, arg2); } - function reportRelationError(message: DiagnosticMessage, source: Type, target: Type) { + function reportRelationError(message: DiagnosticMessage | undefined, source: Type, target: Type) { let sourceType = typeToString(source); let targetType = typeToString(target); if (sourceType === targetType) { @@ -10418,7 +10453,7 @@ namespace ts { * * Ternary.Maybe if they are related with assumptions of other relationships, or * * Ternary.False if they are not related. */ - function isRelatedTo(source: Type, target: Type, reportErrors?: boolean, headMessage?: DiagnosticMessage): Ternary { + function isRelatedTo(source: Type, target: Type, reportErrors = false, headMessage?: DiagnosticMessage): Ternary { if (source.flags & TypeFlags.StringOrNumberLiteral && source.flags & TypeFlags.FreshLiteral) { source = (source).regularType; } @@ -10621,7 +10656,7 @@ namespace ts { // We know *exactly* where things went wrong when comparing the types. // Use this property as the error node as this will be more helpful in // reasoning about what went wrong. - Debug.assert(!!errorNode); + if (!errorNode) return Debug.fail(); if (isJsxAttributes(errorNode) || isJsxOpeningLikeElement(errorNode)) { // JsxAttributes has an object-literal flag and undergo same type-assignablity check as normal object-literal. // However, using an object-literal error message will be very confusing to the users so we give different a message. @@ -10637,8 +10672,9 @@ namespace ts { errorNode = propDeclaration; - if (isIdentifier(propDeclaration.name)) { - suggestion = getSuggestionForNonexistentProperty(propDeclaration.name, target); + const name = propDeclaration.name!; + if (isIdentifier(name)) { + suggestion = getSuggestionForNonexistentProperty(name, target); } } @@ -10692,7 +10728,7 @@ namespace ts { // Keep this up-to-date with the same logic within `getApparentTypeOfContextualType`, since they should behave similarly function findMatchingDiscriminantType(source: Type, target: UnionOrIntersectionType) { - let match: Type; + let match: Type | undefined; const sourceProperties = getPropertiesOfObjectType(source); if (sourceProperties) { const sourcePropertiesFiltered = findDiscriminantProperties(sourceProperties, target); @@ -10882,7 +10918,7 @@ namespace ts { function structuredTypeRelatedTo(source: Type, target: Type, reportErrors: boolean): Ternary { let result: Ternary; - let originalErrorInfo: DiagnosticMessageChain; + let originalErrorInfo: DiagnosticMessageChain | undefined; const saveErrorInfo = errorInfo; if (target.flags & TypeFlags.TypeParameter) { // A source type { [P in keyof T]: X } is related to a target type T if X is related to T[P]. @@ -11312,7 +11348,7 @@ namespace ts { // in the context of the target signature before checking the relationship. Ideally we'd do // this regardless of the number of signatures, but the potential costs are prohibitive due // to the quadratic nature of the logic below. - const eraseGenerics = relation === comparableRelation || compilerOptions.noStrictGenericChecks; + const eraseGenerics = relation === comparableRelation || !!compilerOptions.noStrictGenericChecks; result = signatureRelatedTo(sourceSignatures[0], targetSignatures[0], eraseGenerics, reportErrors); } else { @@ -11397,7 +11433,7 @@ namespace ts { return related; } - function indexTypesRelatedTo(source: Type, target: Type, kind: IndexKind, sourceIsPrimitive: boolean, reportErrors: boolean) { + function indexTypesRelatedTo(source: Type, target: Type, kind: IndexKind, sourceIsPrimitive: boolean, reportErrors: boolean): Ternary { if (relation === identityRelation) { return indexTypesIdenticalTo(source, target, kind); } @@ -11414,7 +11450,7 @@ namespace ts { if (isGenericMappedType(source)) { // A generic mapped type { [P in K]: T } is related to an index signature { [x: string]: U } // if T is related to U. - return kind === IndexKind.String && isRelatedTo(getTemplateTypeFromMappedType(source), targetInfo.type, reportErrors); + return (kind === IndexKind.String && isRelatedTo(getTemplateTypeFromMappedType(source), targetInfo.type, reportErrors)) as any as Ternary; // TODO: GH#18217 } if (isObjectTypeWithInferableIndex(source)) { let related = Ternary.True; @@ -11534,7 +11570,7 @@ namespace ts { // See comment at call in recursiveTypeRelatedTo for when this case matters. function hasCovariantVoidArgument(type: TypeReference, variances: Variance[]): boolean { for (let i = 0; i < variances.length; i++) { - if (variances[i] === Variance.Covariant && type.typeArguments[i].flags & TypeFlags.Void) { + if (variances[i] === Variance.Covariant && type.typeArguments![i].flags & TypeFlags.Void) { return true; } } @@ -11546,7 +11582,7 @@ namespace ts { } function isTypeReferenceWithGenericArguments(type: Type): boolean { - return getObjectFlags(type) & ObjectFlags.Reference && some((type).typeArguments, t => isUnconstrainedTypeParameter(t) || isTypeReferenceWithGenericArguments(t)); + return !!(getObjectFlags(type) & ObjectFlags.Reference) && some((type).typeArguments, t => isUnconstrainedTypeParameter(t) || isTypeReferenceWithGenericArguments(t)); } /** @@ -11555,7 +11591,7 @@ namespace ts { */ function getTypeReferenceId(type: TypeReference, typeParameters: Type[], depth = 0) { let result = "" + type.target.id; - for (const t of type.typeArguments) { + for (const t of type.typeArguments!) { if (isUnconstrainedTypeParameter(t)) { let index = typeParameters.indexOf(t); if (index < 0) { @@ -11593,9 +11629,9 @@ namespace ts { // Invoke the callback for each underlying property symbol of the given symbol and return the first // value that isn't undefined. - function forEachProperty(prop: Symbol, callback: (p: Symbol) => T): T { + function forEachProperty(prop: Symbol, callback: (p: Symbol) => T): T | undefined { if (getCheckFlags(prop) & CheckFlags.Synthetic) { - for (const t of (prop).containingType.types) { + for (const t of (prop).containingType!.types) { const p = getPropertyOfType(t, prop.escapedName); const result = p && forEachProperty(p, callback); if (result) { @@ -11609,12 +11645,12 @@ namespace ts { // Return the declaring class type of a property or undefined if property not declared in class function getDeclaringClass(prop: Symbol) { - return prop.parent && prop.parent.flags & SymbolFlags.Class ? getDeclaredTypeOfSymbol(getParentOfSymbol(prop)) : undefined; + return prop.parent && prop.parent.flags & SymbolFlags.Class ? getDeclaredTypeOfSymbol(getParentOfSymbol(prop)!) : undefined; } // Return true if some underlying source property is declared in a class that derives // from the given base class. - function isPropertyInClassDerivedFrom(prop: Symbol, baseClass: Type) { + function isPropertyInClassDerivedFrom(prop: Symbol, baseClass: Type | undefined) { return forEachProperty(prop, sp => { const sourceClass = getDeclaringClass(sp); return sourceClass ? hasBaseType(sourceClass, baseClass) : false; @@ -11779,7 +11815,7 @@ namespace ts { } function literalTypesWithSameBaseType(types: Type[]): boolean { - let commonBaseType: Type; + let commonBaseType: Type | undefined; for (const t of types) { const baseType = getBaseTypeOfLiteralType(t); if (!commonBaseType) { @@ -11798,7 +11834,7 @@ namespace ts { function getSupertypeOrUnion(types: Type[]): Type { return literalTypesWithSameBaseType(types) ? getUnionType(types) : - reduceLeft(types, (s, t) => isTypeSubtypeOf(s, t) ? t : s); + reduceLeft(types, (s, t) => isTypeSubtypeOf(s, t) ? t : s)!; } function getCommonSupertype(types: Type[]): Type { @@ -11813,11 +11849,11 @@ namespace ts { // Return the leftmost type for which no type to the right is a subtype. function getCommonSubtype(types: Type[]) { - return reduceLeft(types, (s, t) => isTypeSubtypeOf(t, s) ? t : s); + return reduceLeft(types, (s, t) => isTypeSubtypeOf(t, s) ? t : s)!; } function isArrayType(type: Type): boolean { - return getObjectFlags(type) & ObjectFlags.Reference && (type).target === globalArrayType; + return !!(getObjectFlags(type) & ObjectFlags.Reference) && (type).target === globalArrayType; } function isArrayLikeType(type: Type): boolean { @@ -11828,7 +11864,7 @@ namespace ts { } function isEmptyArrayLiteralType(type: Type): boolean { - const elementType = isArrayType(type) ? (type).typeArguments[0] : undefined; + const elementType = isArrayType(type) ? (type).typeArguments![0] : undefined; return elementType === undefinedWideningType || elementType === implicitNeverType; } @@ -11874,7 +11910,7 @@ namespace ts { type; } - function getWidenedLiteralLikeTypeForContextualType(type: Type, contextualType: Type) { + function getWidenedLiteralLikeTypeForContextualType(type: Type, contextualType: Type | undefined) { if (!isLiteralOfContextualType(type, contextualType)) { type = getWidenedUniqueESSymbolType(getWidenedLiteralType(type)); } @@ -11970,7 +12006,7 @@ namespace ts { !typeHasCallOrConstructSignatures(type); } - function createSymbolWithType(source: Symbol, type: Type) { + function createSymbolWithType(source: Symbol, type: Type | undefined) { const symbol = createSymbol(source.flags, source.escapedName); symbol.declarations = source.declarations; symbol.parent = source.parent; @@ -12023,16 +12059,16 @@ namespace ts { return regularNew; } - function createWideningContext(parent: WideningContext, propertyName: __String, siblings: Type[]): WideningContext { + function createWideningContext(parent: WideningContext | undefined, propertyName: __String | undefined, siblings: Type[] | undefined): WideningContext { return { parent, propertyName, siblings, resolvedProperties: undefined }; } function getSiblingsOfContext(context: WideningContext): Type[] { if (!context.siblings) { const siblings: Type[] = []; - for (const type of getSiblingsOfContext(context.parent)) { + for (const type of getSiblingsOfContext(context.parent!)) { if (isObjectLiteralType(type)) { - const prop = getPropertyOfObjectType(type, context.propertyName); + const prop = getPropertyOfObjectType(type, context.propertyName!); if (prop) { forEachType(getTypeOfSymbol(prop), t => { siblings.push(t); @@ -12060,7 +12096,7 @@ namespace ts { return context.resolvedProperties; } - function getWidenedProperty(prop: Symbol, context: WideningContext): Symbol { + function getWidenedProperty(prop: Symbol, context: WideningContext | undefined): Symbol { const original = getTypeOfSymbol(prop); const propContext = context && createWideningContext(context, prop.escapedName, /*siblings*/ undefined); const widened = getWidenedTypeWithContext(original, propContext); @@ -12078,7 +12114,7 @@ namespace ts { return result; } - function getWidenedTypeOfObjectLiteral(type: Type, context: WideningContext): Type { + function getWidenedTypeOfObjectLiteral(type: Type, context: WideningContext | undefined): Type { const members = createSymbolTable(); for (const prop of getPropertiesOfObjectType(type)) { // Since get accessors already widen their return value there is no need to @@ -12103,7 +12139,7 @@ namespace ts { return getWidenedTypeWithContext(type, /*context*/ undefined); } - function getWidenedTypeWithContext(type: Type, context: WideningContext): Type { + function getWidenedTypeWithContext(type: Type, context: WideningContext | undefined): Type { if (type.flags & TypeFlags.RequiresWidening) { if (type.flags & TypeFlags.Nullable) { return anyType; @@ -12153,7 +12189,7 @@ namespace ts { } } if (isArrayType(type) || isTupleType(type)) { - for (const t of (type).typeArguments) { + for (const t of (type).typeArguments!) { if (reportWideningErrorsInType(t)) { errorReported = true; } @@ -12302,13 +12338,13 @@ namespace ts { function couldUnionOrIntersectionContainTypeVariables(type: UnionOrIntersectionType): boolean { if (type.couldContainTypeVariables === undefined) { - type.couldContainTypeVariables = forEach(type.types, couldContainTypeVariables); + type.couldContainTypeVariables = some(type.types, couldContainTypeVariables); } return type.couldContainTypeVariables; } function isTypeParameterAtTopLevel(type: Type, typeParameter: TypeParameter): boolean { - return type === typeParameter || type.flags & TypeFlags.UnionOrIntersection && forEach((type).types, t => isTypeParameterAtTopLevel(t, typeParameter)); + return type === typeParameter || !!(type.flags & TypeFlags.UnionOrIntersection) && some((type).types, t => isTypeParameterAtTopLevel(t, typeParameter)); } /** Create an object with properties named in the string literal type. Every property has type `any` */ @@ -12337,7 +12373,7 @@ namespace ts { * property is computed by inferring from the source property type to X for the type * variable T[P] (i.e. we treat the type T[P] as the type variable we're inferring for). */ - function inferTypeForHomomorphicMappedType(source: Type, target: MappedType): Type { + function inferTypeForHomomorphicMappedType(source: Type, target: MappedType): Type | undefined { const key = source.id + "," + target.id; if (reverseMappedCache.has(key)) { return reverseMappedCache.get(key); @@ -12429,7 +12465,7 @@ namespace ts { // Source and target are types originating in the same generic type alias declaration. // Simply infer from source type arguments to target type arguments. const sourceTypes = source.aliasTypeArguments; - const targetTypes = target.aliasTypeArguments; + const targetTypes = target.aliasTypeArguments!; for (let i = 0; i < sourceTypes.length; i++) { inferFromTypes(sourceTypes[i], targetTypes[i]); } @@ -12451,7 +12487,7 @@ namespace ts { // and infer themselves as their type arguments. We have special handling for numeric // and string literals because the number and string types are not represented as unions // of all their possible values. - let matchingTypes: Type[]; + let matchingTypes: Type[] | undefined; for (const t of (source).types) { if (typeIdenticalToSomeType(t, (target).types)) { (matchingTypes || (matchingTypes = [])).push(t); @@ -12549,7 +12585,7 @@ namespace ts { else if (target.flags & TypeFlags.UnionOrIntersection) { const targetTypes = (target).types; let typeVariableCount = 0; - let typeVariable: TypeParameter | IndexedAccessType; + let typeVariable: TypeParameter | IndexedAccessType | undefined; // First infer to each type in union or intersection that isn't a type variable for (const t of targetTypes) { if (getInferenceInfoForType(t)) { @@ -12566,7 +12602,7 @@ namespace ts { if (typeVariableCount === 1) { const savePriority = priority; priority |= InferencePriority.NakedTypeVariable; - inferFromTypes(source, typeVariable); + inferFromTypes(source, typeVariable!); priority = savePriority; } } @@ -12757,7 +12793,7 @@ namespace ts { function hasPrimitiveConstraint(type: TypeParameter): boolean { const constraint = getConstraintOfTypeParameter(type); - return constraint && maybeTypeOfKind(constraint, TypeFlags.Primitive | TypeFlags.Index); + return !!constraint && maybeTypeOfKind(constraint, TypeFlags.Primitive | TypeFlags.Index); } function isObjectLiteralType(type: Type) { @@ -12776,12 +12812,12 @@ namespace ts { } function getContravariantInference(inference: InferenceInfo) { - return inference.priority & InferencePriority.PriorityImpliesCombination ? getIntersectionType(inference.contraCandidates) : getCommonSubtype(inference.contraCandidates); + return inference.priority! & InferencePriority.PriorityImpliesCombination ? getIntersectionType(inference.contraCandidates!) : getCommonSubtype(inference.contraCandidates!); } function getCovariantInference(inference: InferenceInfo, context: InferenceContext, signature: Signature) { // Extract all object literal types and replace them with a single widened and normalized type. - const candidates = widenObjectLiteralCandidates(inference.candidates); + const candidates = widenObjectLiteralCandidates(inference.candidates!); // We widen inferred literal types if // all inferences were made to top-level occurrences of the type parameter, and // the type parameter has no constraint or its constraint includes no primitive or literal types, and @@ -12795,7 +12831,7 @@ namespace ts { // If all inferences were made from contravariant positions, infer a common subtype. Otherwise, if // union types were requested or if all inferences were made from the return type position, infer a // union type. Otherwise, infer a common supertype. - const unwidenedType = context.flags & InferenceFlags.InferUnionTypes || inference.priority & InferencePriority.PriorityImpliesCombination ? + const unwidenedType = context.flags & InferenceFlags.InferUnionTypes || inference.priority! & InferencePriority.PriorityImpliesCombination ? getUnionType(baseCandidates, UnionReduction.Subtype) : getCommonSupertype(baseCandidates); return getWidenedType(unwidenedType); @@ -12835,7 +12871,7 @@ namespace ts { // parameter should be instantiated to the empty object type. inferredType = instantiateType(defaultType, combineTypeMappers( - createBackreferenceMapper(context.signature.typeParameters, index), + createBackreferenceMapper(context.signature!.typeParameters!, index), context)); } else { @@ -12930,7 +12966,8 @@ namespace ts { } function getBindingElementNameText(element: BindingElement): string | undefined { - if (element.parent.kind === SyntaxKind.ObjectBindingPattern) { + const parent = element.parent; + if (parent.kind === SyntaxKind.ObjectBindingPattern) { const name = element.propertyName || element.name; switch (name.kind) { case SyntaxKind.Identifier: @@ -12946,7 +12983,7 @@ namespace ts { } } else { - return "" + element.parent.elements.indexOf(element); + return "" + parent.elements.indexOf(element); } } @@ -12973,7 +13010,7 @@ namespace ts { } if (source.parent.parent.kind === SyntaxKind.VariableDeclaration) { const maybeId = (source.parent.parent as VariableDeclaration).initializer; - return maybeId && isMatchingReference(maybeId, t.expression); + return !!maybeId && isMatchingReference(maybeId, t.expression); } } return false; @@ -12999,7 +13036,7 @@ namespace ts { isDiscriminantProperty(getDeclaredTypeOfReference((target).expression), (target).name.escapedText); } - function getDeclaredTypeOfReference(expr: Node): Type { + function getDeclaredTypeOfReference(expr: Node): Type | undefined { if (expr.kind === SyntaxKind.Identifier) { return getTypeOfSymbol(getResolvedSymbol(expr)); } @@ -13010,12 +13047,12 @@ namespace ts { return undefined; } - function isDiscriminantProperty(type: Type, name: __String) { + function isDiscriminantProperty(type: Type | undefined, name: __String) { if (type && type.flags & TypeFlags.Union) { const prop = getUnionOrIntersectionProperty(type, name); if (prop && getCheckFlags(prop) & CheckFlags.SyntheticProperty) { if ((prop).isDiscriminantProperty === undefined) { - (prop).isDiscriminantProperty = (prop).checkFlags & CheckFlags.HasNonUniformType && isLiteralType(getTypeOfSymbol(prop)); + (prop).isDiscriminantProperty = !!((prop).checkFlags & CheckFlags.HasNonUniformType) && isLiteralType(getTypeOfSymbol(prop)); } return (prop).isDiscriminantProperty; } @@ -13024,7 +13061,7 @@ namespace ts { } function findDiscriminantProperties(sourceProperties: Symbol[], target: Type): Symbol[] | undefined { - let result: Symbol[]; + let result: Symbol[] | undefined; for (const sourceProperty of sourceProperties) { if (isDiscriminantProperty(target, sourceProperty.escapedName)) { if (result) { @@ -13219,11 +13256,11 @@ namespace ts { } function getAssignedTypeOfShorthandPropertyAssignment(node: ShorthandPropertyAssignment): Type { - return getTypeWithDefault(getAssignedTypeOfPropertyAssignment(node), node.objectAssignmentInitializer); + return getTypeWithDefault(getAssignedTypeOfPropertyAssignment(node), node.objectAssignmentInitializer!); } function getAssignedType(node: Expression): Type { - const parent = node.parent; + const { parent } = node; switch (parent.kind) { case SyntaxKind.ForInStatement: return stringType; @@ -13253,7 +13290,7 @@ namespace ts { !node.dotDotDotToken ? getTypeOfDestructuredArrayElement(parentType, pattern.elements.indexOf(node)) : getTypeOfDestructuredSpreadExpression(parentType); - return getTypeWithDefault(type, node.initializer); + return getTypeWithDefault(type, node.initializer!); } function getTypeOfInitializer(node: Expression) { @@ -13291,7 +13328,7 @@ namespace ts { function isEmptyArrayAssignment(node: VariableDeclaration | BindingElement | Expression) { return node.kind === SyntaxKind.VariableDeclaration && (node).initializer && - isEmptyArrayLiteral((node).initializer) || + isEmptyArrayLiteral((node).initializer!) || node.kind !== SyntaxKind.BindingElement && node.parent.kind === SyntaxKind.BinaryExpression && isEmptyArrayLiteral((node.parent).right); } @@ -13312,7 +13349,7 @@ namespace ts { } function getReferenceRoot(node: Node): Node { - const parent = node.parent; + const { parent } = node; return parent.kind === SyntaxKind.ParenthesizedExpression || parent.kind === SyntaxKind.BinaryExpression && (parent).operatorToken.kind === SyntaxKind.EqualsToken && (parent).left === node || parent.kind === SyntaxKind.BinaryExpression && (parent).operatorToken.kind === SyntaxKind.CommaToken && (parent).right === node ? @@ -13360,7 +13397,7 @@ namespace ts { return containsType(target.types, source); } - function forEachType(type: Type, f: (t: Type) => T): T { + function forEachType(type: Type, f: (t: Type) => T | undefined): T | undefined { return type.flags & TypeFlags.Union ? forEach((type).types, f) : f(type); } @@ -13376,7 +13413,9 @@ namespace ts { // Apply a mapping function to a type and return the resulting type. If the source type // is a union type, the mapping function is applied to each constituent type and a union // of the resulting types is returned. - function mapType(type: Type, mapper: (t: Type) => Type, noReductions?: boolean): Type { + function mapType(type: Type, mapper: (t: Type) => Type, noReductions?: boolean): Type; + function mapType(type: Type, mapper: (t: Type) => Type | undefined, noReductions?: boolean): Type | undefined; + function mapType(type: Type, mapper: (t: Type) => Type | undefined, noReductions?: boolean): Type | undefined { if (type.flags & TypeFlags.Never) { return type; } @@ -13384,8 +13423,8 @@ namespace ts { return mapper(type); } const types = (type).types; - let mappedType: Type; - let mappedTypes: Type[]; + let mappedType: Type | undefined; + let mappedTypes: Type[] | undefined; for (const current of types) { const t = mapper(current); if (t) { @@ -13543,7 +13582,7 @@ namespace ts { } function getFlowTypeOfReference(reference: Node, declaredType: Type, initialType = declaredType, flowContainer?: Node, couldBeUninitialized?: boolean) { - let key: string; + let key: string | undefined; let flowDepth = 0; if (flowAnalysisDisabled) { return unknownType; @@ -13586,7 +13625,7 @@ namespace ts { } } } - let type: FlowType; + let type: FlowType | undefined; if (flags & FlowFlags.AfterFinally) { // block flow edge: finally -> pre-try (for larger explanation check comment in binder.ts - bindTryStatement (flow).locked = true; @@ -13613,8 +13652,8 @@ namespace ts { type = getTypeAtSwitchClause(flow); } else if (flags & FlowFlags.Label) { - if ((flow).antecedents.length === 1) { - flow = (flow).antecedents[0]; + if ((flow).antecedents!.length === 1) { + flow = (flow).antecedents![0]; continue; } type = flags & FlowFlags.BranchLabel ? @@ -13632,7 +13671,7 @@ namespace ts { // Check if we should continue with the control flow of the containing function. const container = (flow).container; if (container && container !== flowContainer && reference.kind !== SyntaxKind.PropertyAccessExpression && reference.kind !== SyntaxKind.ThisKeyword) { - flow = container.flowNode; + flow = container.flowNode!; continue; } // At the top of the flow we have the initial type. @@ -13686,7 +13725,7 @@ namespace ts { return undefined; } - function getTypeAtFlowArrayMutation(flow: FlowArrayMutation): FlowType { + function getTypeAtFlowArrayMutation(flow: FlowArrayMutation): FlowType | undefined { if (declaredType === autoType || declaredType === autoArrayType) { const node = flow.node; const expr = node.kind === SyntaxKind.CallExpression ? @@ -13757,7 +13796,7 @@ namespace ts { const antecedentTypes: Type[] = []; let subtypeReduction = false; let seenIncomplete = false; - for (const antecedent of flow.antecedents) { + for (const antecedent of flow.antecedents!) { if (antecedent.flags & FlowFlags.PreFinally && (antecedent).lock.locked) { // if flow correspond to branch from pre-try to finally and this branch is locked - this means that // we initially have started following the flow outside the finally block. @@ -13820,11 +13859,11 @@ namespace ts { // each antecedent code path. const antecedentTypes: Type[] = []; let subtypeReduction = false; - let firstAntecedentType: FlowType; + let firstAntecedentType: FlowType | undefined; flowLoopNodes[flowLoopCount] = flow; flowLoopKeys[flowLoopCount] = key; flowLoopTypes[flowLoopCount] = antecedentTypes; - for (const antecedent of flow.antecedents) { + for (const antecedent of flow.antecedents!) { flowLoopCount++; const flowType = getTypeAtFlowNode(antecedent); flowLoopCount--; @@ -13856,7 +13895,7 @@ namespace ts { // The result is incomplete if the first antecedent (the non-looping control flow path) // is incomplete. const result = getUnionOrEvolvingArrayType(antecedentTypes, subtypeReduction ? UnionReduction.Subtype : UnionReduction.Literal); - if (isIncomplete(firstAntecedentType)) { + if (isIncomplete(firstAntecedentType!)) { return createFlowType(result, /*incomplete*/ true); } cache.set(key, result); @@ -13874,7 +13913,7 @@ namespace ts { const propName = propAccess.name.escapedText; const propType = getTypeOfPropertyOfType(type, propName); const narrowedPropType = propType && narrowType(propType); - return propType === narrowedPropType ? type : filterType(type, t => isTypeComparableTo(getTypeOfPropertyOfType(t, propName), narrowedPropType)); + return propType === narrowedPropType ? type : filterType(type, t => isTypeComparableTo(getTypeOfPropertyOfType(t, propName)!, narrowedPropType!)); } function narrowTypeByTruthiness(type: Type, expr: Expression, assumeTrue: boolean): Type { @@ -14063,7 +14102,7 @@ namespace ts { return type; } - let targetType: Type; + let targetType: Type | undefined; const prototypeProperty = getPropertyOfType(rightType, "prototype" as __String); if (prototypeProperty) { // Target type is type of the prototype property @@ -14080,7 +14119,7 @@ namespace ts { if (!targetType) { // Target type is type of construct signature - let constructSignatures: Signature[]; + let constructSignatures: Signature[] | undefined; if (getObjectFlags(rightType) & ObjectFlags.Interface) { constructSignatures = resolveDeclaredMembers(rightType).declaredConstructSignatures; } @@ -14220,7 +14259,7 @@ namespace ts { isFunctionLike(node) && !getImmediatelyInvokedFunctionExpression(node) || node.kind === SyntaxKind.ModuleBlock || node.kind === SyntaxKind.SourceFile || - node.kind === SyntaxKind.PropertyDeclaration); + node.kind === SyntaxKind.PropertyDeclaration)!; } // Check if a parameter is assigned anywhere within its declaring function. @@ -14280,7 +14319,9 @@ namespace ts { return type.flags & TypeFlags.InstantiableNonPrimitive && maybeTypeOfKind(getBaseConstraintOfType(type) || emptyObjectType, TypeFlags.Nullable); } - function getConstraintForLocation(type: Type, node: Node) { + function getConstraintForLocation(type: Type, node: Node): Type; + function getConstraintForLocation(type: Type | undefined, node: Node): Type | undefined; + function getConstraintForLocation(type: Type, node: Node): Type | undefined { // When a node is the left hand expression of a property access, element access, or call expression, // and the type of the node includes type variables with constraints that are nullable, we fetch the // apparent type of the node *before* performing control flow analysis such that narrowings apply to @@ -14310,7 +14351,7 @@ namespace ts { // To avoid that we will give an error to users if they use arguments objects in arrow function so that they // can explicitly bound arguments objects if (symbol === argumentsSymbol) { - const container = getContainingFunction(node); + const container = getContainingFunction(node)!; if (languageVersion < ScriptTarget.ES2015) { if (container.kind === SyntaxKind.ArrowFunction) { error(node, Diagnostics.The_arguments_object_cannot_be_referenced_in_an_arrow_function_in_ES3_and_ES5_Consider_using_a_standard_function_expression); @@ -14331,7 +14372,7 @@ namespace ts { } const localOrExportSymbol = getExportSymbolOfValueSymbolIfExported(symbol); - let declaration = localOrExportSymbol.valueDeclaration; + let declaration: Declaration | undefined = localOrExportSymbol.valueDeclaration; if (localOrExportSymbol.flags & SymbolFlags.Class) { // Due to the emit for class decorators, any reference to the class from inside of the class body @@ -14355,7 +14396,7 @@ namespace ts { // to the constructor in the initializer, we will need to substitute that // binding with an alias as the class name is not in scope. let container = getThisContainer(node, /*includeArrowFunctions*/ false); - while (container !== undefined) { + while (container.kind !== SyntaxKind.SourceFile) { if (container.parent === declaration) { if (container.kind === SyntaxKind.PropertyDeclaration && hasModifier(container, ModifierFlags.Static)) { getNodeLinks(declaration).flags |= NodeCheckFlags.ClassWithConstructorReference; @@ -14493,7 +14534,7 @@ namespace ts { // mark variables that are declared in loop initializer and reassigned inside the body of ForStatement. // if body of ForStatement will be converted to function then we'll need a extra machinery to propagate reassigned values back. if (container.kind === SyntaxKind.ForStatement && - getAncestor(symbol.valueDeclaration, SyntaxKind.VariableDeclarationList).parent === container && + getAncestor(symbol.valueDeclaration, SyntaxKind.VariableDeclarationList)!.parent === container && isAssignedInBodyOfForStatement(node, container)) { getNodeLinks(symbol.valueDeclaration).flags |= NodeCheckFlags.NeedsLoopOutParameter; } @@ -14565,10 +14606,10 @@ namespace ts { // Only trying to find super-call if we haven't yet tried to find one. Once we try, we will record the result if (links.hasSuperCall === undefined) { - links.superCall = findFirstSuperCall(constructor.body); + links.superCall = findFirstSuperCall(constructor.body!); links.hasSuperCall = links.superCall ? true : false; } - return links.superCall; + return links.superCall!; } /** @@ -14693,7 +14734,7 @@ namespace ts { if (isClassLike(container.parent)) { const symbol = getSymbolOfNode(container.parent); - const type = hasModifier(container, ModifierFlags.Static) ? getTypeOfSymbol(symbol) : (getDeclaredTypeOfSymbol(symbol)).thisType; + const type = hasModifier(container, ModifierFlags.Static) ? getTypeOfSymbol(symbol) : (getDeclaredTypeOfSymbol(symbol)).thisType!; return getFlowTypeOfReference(node, type); } @@ -14712,7 +14753,7 @@ namespace ts { if (jsDocFunctionType.parameters.length > 0 && jsDocFunctionType.parameters[0].name && (jsDocFunctionType.parameters[0].name as Identifier).escapedText === "this") { - return getTypeFromTypeNode(jsDocFunctionType.parameters[0].type); + return getTypeFromTypeNode(jsDocFunctionType.parameters[0].type!); } } } @@ -14927,17 +14968,17 @@ namespace ts { undefined; } - function getThisTypeArgument(type: Type): Type { - return getObjectFlags(type) & ObjectFlags.Reference && (type).target === globalThisType ? (type).typeArguments[0] : undefined; + function getThisTypeArgument(type: Type): Type | undefined { + return getObjectFlags(type) & ObjectFlags.Reference && (type).target === globalThisType ? (type).typeArguments![0] : undefined; } - function getThisTypeFromContextualType(type: Type): Type { + function getThisTypeFromContextualType(type: Type): Type | undefined { return mapType(type, t => { return t.flags & TypeFlags.Intersection ? forEach((t).types, getThisTypeArgument) : getThisTypeArgument(t); }); } - function getContextualThisParameterType(func: SignatureDeclaration): Type { + function getContextualThisParameterType(func: SignatureDeclaration): Type | undefined { if (func.kind === SyntaxKind.ArrowFunction) { return undefined; } @@ -14978,7 +15019,7 @@ namespace ts { } // In an assignment of the form 'obj.xxx = function(...)' or 'obj[xxx] = function(...)', the // contextual type for 'this' is 'obj'. - const { parent } = func; + const parent = func.parent; if (parent.kind === SyntaxKind.BinaryExpression && (parent).operatorToken.kind === SyntaxKind.EqualsToken) { const target = (parent).left; if (target.kind === SyntaxKind.PropertyAccessExpression || target.kind === SyntaxKind.ElementAccessExpression) { @@ -15041,7 +15082,7 @@ namespace ts { if (funcHasRestParameters && indexOfParameter === (func.parameters.length - 1) && isRestParameterIndex(contextualSignature, func.parameters.length - 1)) { - return getTypeOfSymbol(lastOrUndefined(contextualSignature.parameters)); + return getTypeOfSymbol(last(contextualSignature.parameters)); } } } @@ -15054,7 +15095,7 @@ namespace ts { // the contextual type of an initializer expression is the type implied by the binding pattern. // Otherwise, in a binding pattern inside a variable or parameter declaration, // the contextual type of an initializer expression is the type annotation of the containing declaration, if present. - function getContextualTypeForInitializerExpression(node: Expression): Type { + function getContextualTypeForInitializerExpression(node: Expression): Type | undefined { const declaration = node.parent; if (hasInitializer(declaration) && node === declaration.initializer) { const typeNode = getEffectiveTypeAnnotationNode(declaration); @@ -15087,7 +15128,7 @@ namespace ts { return undefined; } - function getContextualTypeForReturnExpression(node: Expression): Type { + function getContextualTypeForReturnExpression(node: Expression): Type | undefined { const func = getContainingFunction(node); if (func) { const functionFlags = getFunctionFlags(func); @@ -15103,7 +15144,7 @@ namespace ts { return undefined; } - function getContextualTypeForYieldOperand(node: YieldExpression): Type { + function getContextualTypeForYieldOperand(node: YieldExpression): Type | undefined { const func = getContainingFunction(node); if (func) { const functionFlags = getFunctionFlags(func); @@ -15134,7 +15175,7 @@ namespace ts { return false; } - function getContextualReturnType(functionDecl: SignatureDeclaration): Type { + function getContextualReturnType(functionDecl: SignatureDeclaration): Type | undefined { // If the containing function has a return type annotation, is a constructor, or is a get accessor whose // corresponding set accessor has a type annotation, return statements in the function are contextually typed if (functionDecl.kind === SyntaxKind.Constructor || @@ -15154,8 +15195,8 @@ namespace ts { } // In a typed function call, an argument or substitution expression is contextually typed by the type of the corresponding parameter. - function getContextualTypeForArgument(callTarget: CallLikeExpression, arg: Expression): Type { - const args = getEffectiveCallArguments(callTarget); + function getContextualTypeForArgument(callTarget: CallLikeExpression, arg: Expression): Type | undefined { + const args = getEffectiveCallArguments(callTarget)!; // TODO: GH#18217 const argIndex = args.indexOf(arg); // -1 for e.g. the expression of a CallExpression, or the tag of a TaggedTemplateExpression return argIndex === -1 ? undefined : getContextualTypeForArgumentAtIndex(callTarget, argIndex); } @@ -15213,7 +15254,7 @@ namespace ts { case SpecialPropertyAssignmentKind.Prototype: return false; default: - Debug.assertNever(kind); + return Debug.assertNever(kind); } } @@ -15236,7 +15277,7 @@ namespace ts { // In an object literal contextually typed by a type T, the contextual type of a property assignment is the type of // the matching property in T, if one exists. Otherwise, it is the type of the numeric index signature in T, if one // exists. Otherwise, it is the type of the string index signature in T, if one exists. - function getContextualTypeForObjectLiteralMethod(node: MethodDeclaration): Type { + function getContextualTypeForObjectLiteralMethod(node: MethodDeclaration): Type | undefined { Debug.assert(isObjectLiteralMethod(node)); if (node.flags & NodeFlags.InWithStatement) { // We cannot answer semantic questions within a with block, do not proceed any further @@ -15261,7 +15302,7 @@ namespace ts { } } - return isNumericName(element.name) && getIndexTypeOfContextualType(type, IndexKind.Number) || + return isNumericName(element.name!) && getIndexTypeOfContextualType(type, IndexKind.Number) || getIndexTypeOfContextualType(type, IndexKind.String); } @@ -15280,7 +15321,7 @@ namespace ts { } // In a contextually typed conditional expression, the true/false expressions are contextually typed by the same type. - function getContextualTypeForConditionalOperand(node: Expression): Type { + function getContextualTypeForConditionalOperand(node: Expression): Type | undefined { const conditional = node.parent; return node === conditional.whenTrue || node === conditional.whenFalse ? getContextualType(conditional) : undefined; } @@ -15292,7 +15333,7 @@ namespace ts { return attributesType && !isTypeAny(attributesType) && jsxChildrenPropertyName && jsxChildrenPropertyName !== "" ? getTypeOfPropertyOfContextualType(attributesType, jsxChildrenPropertyName) : undefined; } - function getContextualTypeForJsxExpression(node: JsxExpression): Type { + function getContextualTypeForJsxExpression(node: JsxExpression): Type | undefined { const exprParent = node.parent; return isJsxAttributeLike(exprParent) ? getContextualType(node) @@ -15339,7 +15380,7 @@ namespace ts { // Return the contextual type for a given expression node. During overload resolution, a contextual type may temporarily // be "pushed" onto a node using the contextualType property. - function getApparentTypeOfContextualType(node: Expression): Type { + function getApparentTypeOfContextualType(node: Expression): Type | undefined { let contextualType = getContextualType(node); contextualType = contextualType && mapType(contextualType, getApparentType); if (!(contextualType && contextualType.flags & TypeFlags.Union && isObjectLiteralExpression(node))) { @@ -15393,7 +15434,7 @@ namespace ts { if (node.contextualType) { return node.contextualType; } - const parent = node.parent; + const { parent } = node; switch (parent.kind) { case SyntaxKind.VariableDeclaration: case SyntaxKind.Parameter: @@ -15432,7 +15473,7 @@ namespace ts { case SyntaxKind.ParenthesizedExpression: { // Like in `checkParenthesizedExpression`, an `/** @type {xyz} */` comment before a parenthesized expression acts as a type cast. const tag = isInJavaScriptFile(parent) ? getJSDocTypeTag(parent) : undefined; - return tag ? getTypeFromTypeNode(tag.typeExpression.type) : getContextualType(parent); + return tag ? getTypeFromTypeNode(tag.typeExpression!.type) : getContextualType(parent); } case SyntaxKind.JsxExpression: return getContextualTypeForJsxExpression(parent); @@ -15447,8 +15488,8 @@ namespace ts { } function getContextualMapper(node: Node) { - node = findAncestor(node, n => !!n.contextualMapper); - return node ? node.contextualMapper : identityMapper; + const ancestor = findAncestor(node, n => !!n.contextualMapper); + return ancestor ? ancestor.contextualMapper! : identityMapper; } function getContextualJsxElementAttributesType(node: JsxOpeningLikeElement) { @@ -15582,7 +15623,7 @@ namespace ts { // If the given type is an object or union type with a single signature, and if that signature has at // least as many parameters as the given function, return the signature. Otherwise return undefined. - function getContextualCallSignature(type: Type, node: FunctionExpression | ArrowFunction | MethodDeclaration): Signature { + function getContextualCallSignature(type: Type, node: FunctionExpression | ArrowFunction | MethodDeclaration): Signature | undefined { const signatures = getSignaturesOfType(type, SignatureKind.Call); if (signatures.length === 1) { const signature = signatures[0]; @@ -15612,7 +15653,7 @@ namespace ts { return node.kind === SyntaxKind.FunctionExpression || node.kind === SyntaxKind.ArrowFunction; } - function getContextualSignatureForFunctionLikeDeclaration(node: FunctionLikeDeclaration): Signature { + function getContextualSignatureForFunctionLikeDeclaration(node: FunctionLikeDeclaration): Signature | undefined { // Only function expressions, arrow functions, and object literal methods are contextually typed. return isFunctionExpressionOrArrowFunction(node) || isObjectLiteralMethod(node) ? getContextualSignature(node) @@ -15630,9 +15671,9 @@ namespace ts { // If the contextual type is a union type, get the signature from each type possible and if they are // all identical ignoring their return type, the result is same signature but with return type as // union type of return types from these signatures - function getContextualSignature(node: FunctionExpression | ArrowFunction | MethodDeclaration): Signature { + function getContextualSignature(node: FunctionExpression | ArrowFunction | MethodDeclaration): Signature | undefined { Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node)); - let type: Type; + let type: Type | undefined; if (isInJavaScriptFile(node)) { const jsdoc = getJSDocType(node); if (jsdoc) { @@ -15648,7 +15689,7 @@ namespace ts { if (!(type.flags & TypeFlags.Union)) { return getContextualCallSignature(type, node); } - let signatureList: Signature[]; + let signatureList: Signature[] | undefined; const types = (type).types; for (const current of types) { const signature = getContextualCallSignature(current, node); @@ -15669,7 +15710,7 @@ namespace ts { } // Result is union of signatures collected (return type is union of return types of this signature set) - let result: Signature; + let result: Signature | undefined; if (signatureList) { result = cloneSignature(signatureList[0]); result.unionSignatures = signatureList; @@ -15743,7 +15784,7 @@ namespace ts { for (let i = elementTypes.length; i < patternElements.length; i++) { const patternElement = patternElements[i]; if (hasDefaultValue(patternElement)) { - elementTypes.push((contextualType).typeArguments[i]); + elementTypes.push((contextualType).typeArguments![i]); } else { if (patternElement.kind !== SyntaxKind.OmittedExpression) { @@ -15834,7 +15875,7 @@ namespace ts { function getObjectLiteralIndexInfo(propertyNodes: NodeArray, offset: number, properties: Symbol[], kind: IndexKind): IndexInfo { const propTypes: Type[] = []; for (let i = 0; i < properties.length; i++) { - if (kind === IndexKind.String || isNumericName(propertyNodes[i + offset].name)) { + if (kind === IndexKind.String || isNumericName(propertyNodes[i + offset].name!)) { propTypes.push(getTypeOfSymbol(properties[i])); } } @@ -15912,17 +15953,17 @@ namespace ts { prop.flags |= SymbolFlags.Optional; } } - else if (contextualTypeHasPattern && !(getObjectFlags(contextualType) & ObjectFlags.ObjectLiteralPatternWithComputedProperties)) { + else if (contextualTypeHasPattern && !(getObjectFlags(contextualType!) & ObjectFlags.ObjectLiteralPatternWithComputedProperties)) { // If object literal is contextually typed by the implied type of a binding pattern, and if the // binding pattern specifies a default value for the property, make the property optional. - const impliedProp = getPropertyOfType(contextualType, member.escapedName); + const impliedProp = getPropertyOfType(contextualType!, member.escapedName); if (impliedProp) { prop.flags |= impliedProp.flags & SymbolFlags.Optional; } - else if (!compilerOptions.suppressExcessPropertyErrors && !getIndexInfoOfType(contextualType, IndexKind.String)) { + else if (!compilerOptions.suppressExcessPropertyErrors && !getIndexInfoOfType(contextualType!, IndexKind.String)) { error(memberDecl.name, Diagnostics.Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1, - symbolToString(member), typeToString(contextualType)); + symbolToString(member), typeToString(contextualType!)); } } prop.declarations = member.declarations; @@ -15988,7 +16029,7 @@ namespace ts { // If object literal is contextually typed by the implied type of a binding pattern, augment the result // type with those properties for which the binding pattern specifies a default value. if (contextualTypeHasPattern) { - for (const prop of getPropertiesOfType(contextualType)) { + for (const prop of getPropertiesOfType(contextualType!)) { if (!propertiesTable.get(prop.escapedName) && !(spread && getPropertyOfType(spread, prop.escapedName))) { if (!(prop.flags & SymbolFlags.Optional)) { error(prop.valueDeclaration || (prop).bindingElement, @@ -16036,12 +16077,12 @@ namespace ts { type.flags & TypeFlags.UnionOrIntersection && !forEach((type).types, t => !isValidSpreadType(t))); } - function checkJsxSelfClosingElement(node: JsxSelfClosingElement, checkMode: CheckMode): Type { + function checkJsxSelfClosingElement(node: JsxSelfClosingElement, checkMode: CheckMode | undefined): Type { checkJsxOpeningLikeElementOrOpeningFragment(node, checkMode); return getJsxElementTypeAt(node) || anyType; } - function checkJsxElement(node: JsxElement, checkMode: CheckMode): Type { + function checkJsxElement(node: JsxElement, checkMode: CheckMode | undefined): Type { // Check attributes checkJsxOpeningLikeElementOrOpeningFragment(node.openingElement, checkMode); @@ -16056,7 +16097,7 @@ namespace ts { return getJsxElementTypeAt(node) || anyType; } - function checkJsxFragment(node: JsxFragment, checkMode: CheckMode): Type { + function checkJsxFragment(node: JsxFragment, checkMode: CheckMode | undefined): Type { checkJsxOpeningLikeElementOrOpeningFragment(node.openingFragment, checkMode); if (compilerOptions.jsx === JsxEmit.React && (compilerOptions.jsxFactory || getSourceFileOfNode(node).pragmas.has("jsx"))) { @@ -16079,7 +16120,7 @@ namespace ts { /** * Returns true iff React would emit this tag name as a string rather than an identifier or qualified name */ - function isJsxIntrinsicIdentifier(tagName: JsxTagNameExpression) { + function isJsxIntrinsicIdentifier(tagName: JsxTagNameExpression): boolean { // TODO (yuisu): comment switch (tagName.kind) { case SyntaxKind.PropertyAccessExpression: @@ -16088,7 +16129,7 @@ namespace ts { case SyntaxKind.Identifier: return isIntrinsicJsxName((tagName).escapedText); default: - Debug.fail(); + return Debug.fail(); } } @@ -16107,12 +16148,12 @@ namespace ts { * @remarks Because this function calls getSpreadType, it needs to use the same checks as checkObjectLiteral, * which also calls getSpreadType. */ - function createJsxAttributesTypeFromAttributesProperty(openingLikeElement: JsxOpeningLikeElement, checkMode: CheckMode) { + function createJsxAttributesTypeFromAttributesProperty(openingLikeElement: JsxOpeningLikeElement, checkMode: CheckMode | undefined) { const attributes = openingLikeElement.attributes; let attributesTable = createSymbolTable(); let spread: Type = emptyObjectType; let hasSpreadAnyType = false; - let typeToIntersect: Type; + let typeToIntersect: Type | undefined; let explicitlySpecifyChildrenAttribute = false; const jsxChildrenPropertyName = getJsxElementChildrenPropertyName(getJsxNamespaceAt(openingLikeElement)); @@ -16229,7 +16270,7 @@ namespace ts { * (See "checkApplicableSignatureForJsxOpeningLikeElement" for how the function is used) * @param node a JSXAttributes to be resolved of its type */ - function checkJsxAttributes(node: JsxAttributes, checkMode: CheckMode) { + function checkJsxAttributes(node: JsxAttributes, checkMode: CheckMode | undefined) { return createJsxAttributesTypeFromAttributesProperty(node.parent, checkMode); } @@ -16282,7 +16323,7 @@ namespace ts { function instantiateJsxSignatures(node: JsxOpeningLikeElement, signatures: Signature[]) { const instantiatedSignatures = []; - let candidateForTypeArgumentError: Signature; + let candidateForTypeArgumentError: Signature | undefined; let hasTypeArgumentError: boolean = !!node.typeArguments; for (const signature of signatures) { if (signature.typeParameters) { @@ -16317,7 +16358,7 @@ namespace ts { return instantiatedSignatures; } - function getJsxSignatureTypeArgumentInstantiation(signature: Signature, node: JsxOpeningLikeElement, isJavascript: boolean, reportErrors?: boolean) { + function getJsxSignatureTypeArgumentInstantiation(signature: Signature, node: JsxOpeningLikeElement, isJavascript: boolean, reportErrors = false) { if (!node.typeArguments) { return; } @@ -16331,7 +16372,7 @@ namespace ts { return getSignatureInstantiation(signature, args, isJavascript); } - function getJsxNamespaceAt(location: Node) { + function getJsxNamespaceAt(location: Node): Symbol { const namespaceName = getJsxNamespace(location); const resolvedNamespace = resolveName(location, namespaceName, SymbolFlags.Namespace, /*diagnosticMessage*/ undefined, namespaceName, /*isUse*/ false); if (resolvedNamespace) { @@ -16341,7 +16382,7 @@ namespace ts { } } // JSX global fallback - return getGlobalSymbol(JsxNames.JSX, SymbolFlags.Namespace, /*diagnosticMessage*/ undefined); + return getGlobalSymbol(JsxNames.JSX, SymbolFlags.Namespace, /*diagnosticMessage*/ undefined)!; // TODO: GH#18217 } /** @@ -16351,9 +16392,9 @@ namespace ts { * @param nameOfAttribPropContainer a string of value JsxNames.ElementAttributesPropertyNameContainer or JsxNames.ElementChildrenAttributeNameContainer * if other string is given or the container doesn't exist, return undefined. */ - function getNameFromJsxElementAttributesContainer(nameOfAttribPropContainer: __String, jsxNamespace: Symbol): __String { + function getNameFromJsxElementAttributesContainer(nameOfAttribPropContainer: __String, jsxNamespace: Symbol): __String | undefined { // JSX.ElementAttributesProperty | JSX.ElementChildrenAttribute [symbol] - const jsxElementAttribPropInterfaceSym = jsxNamespace && getSymbol(jsxNamespace.exports, nameOfAttribPropContainer, SymbolFlags.Type); + const jsxElementAttribPropInterfaceSym = jsxNamespace && getSymbol(jsxNamespace.exports!, nameOfAttribPropContainer, SymbolFlags.Type); // JSX.ElementAttributesProperty | JSX.ElementChildrenAttribute [type] const jsxElementAttribPropInterfaceType = jsxElementAttribPropInterfaceSym && getDeclaredTypeOfSymbol(jsxElementAttribPropInterfaceSym); // The properties of JSX.ElementAttributesProperty | JSX.ElementChildrenAttribute @@ -16370,7 +16411,7 @@ namespace ts { } else if (propertiesOfJsxElementAttribPropInterface.length > 1) { // More than one property on ElementAttributesProperty is an error - error(jsxElementAttribPropInterfaceSym.declarations[0], Diagnostics.The_global_type_JSX_0_may_not_have_more_than_one_property, unescapeLeadingUnderscores(nameOfAttribPropContainer)); + error(jsxElementAttribPropInterfaceSym!.declarations[0], Diagnostics.The_global_type_JSX_0_may_not_have_more_than_one_property, unescapeLeadingUnderscores(nameOfAttribPropContainer)); } } return undefined; @@ -16385,11 +16426,11 @@ namespace ts { return getNameFromJsxElementAttributesContainer(JsxNames.ElementAttributesPropertyNameContainer, jsxNamespace); } - function getJsxElementChildrenPropertyName(jsxNamespace: Symbol): __String { + function getJsxElementChildrenPropertyName(jsxNamespace: Symbol): __String | undefined { return getNameFromJsxElementAttributesContainer(JsxNames.ElementChildrenAttributeNameContainer, jsxNamespace); } - function getApparentTypeOfJsxPropsType(propsType: Type): Type { + function getApparentTypeOfJsxPropsType(propsType: Type | undefined): Type | undefined { if (!propsType) { return undefined; } @@ -16413,7 +16454,7 @@ namespace ts { * @param elemInstanceType an element instance type (the result of newing or invoking this tag) * @param elementClassType a JSX-ElementClass type. This is a result of looking up ElementClass interface in the JSX global */ - function defaultTryGetJsxStatelessFunctionAttributesType(openingLikeElement: JsxOpeningLikeElement, elementType: Type, elemInstanceType: Type, elementClassType?: Type): Type { + function defaultTryGetJsxStatelessFunctionAttributesType(openingLikeElement: JsxOpeningLikeElement, elementType: Type, elemInstanceType: Type, elementClassType?: Type): Type | undefined { Debug.assert(!(elementType.flags & TypeFlags.Union)); if (!elementClassType || !isTypeAssignableTo(elemInstanceType, elementClassType)) { const jsxStatelessElementType = getJsxStatelessElementTypeAt(openingLikeElement); @@ -16422,7 +16463,7 @@ namespace ts { const callSignature = getResolvedJsxStatelessFunctionSignature(openingLikeElement, elementType, /*candidatesOutArray*/ undefined); if (callSignature !== unknownSignature) { const callReturnType = callSignature && getReturnTypeOfSignature(callSignature); - let paramType = callReturnType && (callSignature.parameters.length === 0 ? emptyObjectType : getTypeOfSymbol(callSignature.parameters[0])); + let paramType = callReturnType && (callSignature!.parameters.length === 0 ? emptyObjectType : getTypeOfSymbol(callSignature!.parameters[0])); paramType = getApparentTypeOfJsxPropsType(paramType); if (callReturnType && isTypeAssignableTo(callReturnType, jsxStatelessElementType)) { // Intersect in JSX.IntrinsicAttributes if it exists @@ -16448,7 +16489,7 @@ namespace ts { * @param elemInstanceType an element instance type (the result of newing or invoking this tag) * @param elementClassType a JSX-ElementClass type. This is a result of looking up ElementClass interface in the JSX global */ - function tryGetAllJsxStatelessFunctionAttributesType(openingLikeElement: JsxOpeningLikeElement, elementType: Type, elemInstanceType: Type, elementClassType?: Type): Type { + function tryGetAllJsxStatelessFunctionAttributesType(openingLikeElement: JsxOpeningLikeElement, elementType: Type, elemInstanceType: Type, elementClassType?: Type): Type | undefined { Debug.assert(!(elementType.flags & TypeFlags.Union)); if (!elementClassType || !isTypeAssignableTo(elemInstanceType, elementClassType)) { // Is this is a stateless function component? See if its single signature's return type is assignable to the JSX Element Type @@ -16457,18 +16498,19 @@ namespace ts { // We don't call getResolvedSignature because here we have already resolve the type of JSX Element. const candidatesOutArray: Signature[] = []; getResolvedJsxStatelessFunctionSignature(openingLikeElement, elementType, candidatesOutArray); - let result: Type; - let allMatchingAttributesType: Type; + let result: Type | undefined; + let allMatchingAttributesType: Type | undefined; for (const candidate of candidatesOutArray) { const callReturnType = getReturnTypeOfSignature(candidate); - let paramType = callReturnType && (candidate.parameters.length === 0 ? emptyObjectType : getTypeOfSymbol(candidate.parameters[0])); + // TODO: GH#18217: callReturnType should always be defined... + let paramType: Type | undefined = callReturnType && (candidate.parameters.length === 0 ? emptyObjectType : getTypeOfSymbol(candidate.parameters[0])); paramType = getApparentTypeOfJsxPropsType(paramType); if (callReturnType && isTypeAssignableTo(callReturnType, jsxStatelessElementType)) { let shouldBeCandidate = true; for (const attribute of openingLikeElement.attributes.properties) { if (isJsxAttribute(attribute) && isUnhyphenatedJsxName(attribute.name.escapedText) && - !getPropertyOfType(paramType, attribute.name.escapedText)) { + !getPropertyOfType(paramType!, attribute.name.escapedText)) { // TODO: GH#18217 shouldBeCandidate = false; break; } @@ -16595,7 +16637,7 @@ namespace ts { if (!length(instantiatedSignatures)) { return unknownType; } - const elemInstanceType = getUnionType(map(instantiatedSignatures, getReturnTypeOfSignature), UnionReduction.Subtype); + const elemInstanceType = getUnionType(instantiatedSignatures!.map(getReturnTypeOfSignature), UnionReduction.Subtype); // If we should include all stateless attributes type, then get all attributes type from all stateless function signature. // Otherwise get only attributes type from the signature picked by choose-overload logic. @@ -16613,7 +16655,7 @@ namespace ts { } const isJs = isInJavaScriptFile(openingLikeElement); - return getUnionType(map(instantiatedSignatures, sig => getJsxPropsTypeFromClassType(sig, isJs, openingLikeElement, /*reportErrors*/ true))); + return getUnionType(instantiatedSignatures!.map(sig => getJsxPropsTypeFromClassType(sig, isJs, openingLikeElement, /*reportErrors*/ true))); } /** @@ -16630,7 +16672,7 @@ namespace ts { return links.resolvedJsxElementAttributesType = getTypeOfSymbol(symbol); } else if (links.jsxFlags & JsxFlags.IntrinsicIndexedElement) { - return links.resolvedJsxElementAttributesType = getIndexInfoOfSymbol(symbol, IndexKind.String).type; + return links.resolvedJsxElementAttributesType = getIndexInfoOfSymbol(symbol, IndexKind.String)!.type; } else { return links.resolvedJsxElementAttributesType = unknownType; @@ -16690,7 +16732,7 @@ namespace ts { return prop || unknownSymbol; } - function getJsxElementClassTypeAt(location: Node): Type { + function getJsxElementClassTypeAt(location: Node): Type | undefined { const type = getJsxType(JsxNames.ElementClass, location); if (type === unknownType) return undefined; return type; @@ -16700,7 +16742,7 @@ namespace ts { return getJsxType(JsxNames.Element, location); } - function getJsxStatelessElementTypeAt(location: Node): Type { + function getJsxStatelessElementTypeAt(location: Node): Type | undefined { const jsxElementType = getJsxElementTypeAt(location); if (jsxElementType) { return getUnionType([jsxElementType, nullType]); @@ -16728,7 +16770,7 @@ namespace ts { } } - function checkJsxOpeningLikeElementOrOpeningFragment(node: JsxOpeningLikeElement | JsxOpeningFragment, checkMode: CheckMode) { + function checkJsxOpeningLikeElementOrOpeningFragment(node: JsxOpeningLikeElement | JsxOpeningFragment, checkMode: CheckMode | undefined) { const isNodeOpeningLikeElement = isJsxOpeningLikeElement(node); if (isNodeOpeningLikeElement) { @@ -16800,7 +16842,7 @@ namespace ts { * Check assignablity between given attributes property, "source attributes", and the "target attributes" * @param openingLikeElement an opening-like JSX element to check its JSXAttributes */ - function checkJsxAttributesAssignableToTagNameAttributes(openingLikeElement: JsxOpeningLikeElement, checkMode: CheckMode) { + function checkJsxAttributesAssignableToTagNameAttributes(openingLikeElement: JsxOpeningLikeElement, checkMode: CheckMode | undefined) { // The function involves following steps: // 1. Figure out expected attributes type by resolving tagName of the JSX opening-like element, targetAttributesType. // During these steps, we will try to resolve the tagName as intrinsic name, stateless function, stateful component (in the order) @@ -16943,16 +16985,16 @@ namespace ts { // This error could mask a private property access error. But, a member // cannot simultaneously be private and abstract, so this will trigger an // additional error elsewhere. - error(errorNode, Diagnostics.Abstract_method_0_in_class_1_cannot_be_accessed_via_super_expression, symbolToString(prop), typeToString(getDeclaringClass(prop))); + error(errorNode, Diagnostics.Abstract_method_0_in_class_1_cannot_be_accessed_via_super_expression, symbolToString(prop), typeToString(getDeclaringClass(prop)!)); return false; } } // Referencing abstract properties within their own constructors is not allowed if ((flags & ModifierFlags.Abstract) && isThisProperty(node) && symbolHasNonMethodDeclaration(prop)) { - const declaringClassDeclaration = getClassLikeDeclarationOfSymbol(getParentOfSymbol(prop)); + const declaringClassDeclaration = getClassLikeDeclarationOfSymbol(getParentOfSymbol(prop)!); if (declaringClassDeclaration && isNodeWithinConstructorOfClass(node, declaringClassDeclaration)) { - error(errorNode, Diagnostics.Abstract_property_0_in_class_1_cannot_be_accessed_in_the_constructor, symbolToString(prop), getTextOfIdentifierOrLiteral(declaringClassDeclaration.name)); + error(errorNode, Diagnostics.Abstract_property_0_in_class_1_cannot_be_accessed_in_the_constructor, symbolToString(prop), getTextOfIdentifierOrLiteral(declaringClassDeclaration.name!)); // TODO: GH#18217 return false; } } @@ -16966,9 +17008,9 @@ namespace ts { // Private property is accessible if the property is within the declaring class if (flags & ModifierFlags.Private) { - const declaringClassDeclaration = getClassLikeDeclarationOfSymbol(getParentOfSymbol(prop)); + const declaringClassDeclaration = getClassLikeDeclarationOfSymbol(getParentOfSymbol(prop)!)!; if (!isNodeWithinClass(node, declaringClassDeclaration)) { - error(errorNode, Diagnostics.Property_0_is_private_and_only_accessible_within_class_1, symbolToString(prop), typeToString(getDeclaringClass(prop))); + error(errorNode, Diagnostics.Property_0_is_private_and_only_accessible_within_class_1, symbolToString(prop), typeToString(getDeclaringClass(prop)!)); return false; } return true; @@ -16984,7 +17026,7 @@ namespace ts { // Find the first enclosing class that has the declaring classes of the protected constituents // of the property as base classes const enclosingClass = forEachEnclosingClass(node, enclosingDeclaration => { - const enclosingClass = getDeclaredTypeOfSymbol(getSymbolOfNode(enclosingDeclaration)); + const enclosingClass = getDeclaredTypeOfSymbol(getSymbolOfNode(enclosingDeclaration)!); return isClassDerivedFromDeclaringClasses(enclosingClass, prop) ? enclosingClass : undefined; }); // A protected property is accessible if the property is within the declaring class or classes derived from it @@ -16998,7 +17040,7 @@ namespace ts { } if (type.flags & TypeFlags.TypeParameter) { // get the original type -- represented as the type constraint of the 'this' type - type = (type as TypeParameter).isThisType ? getConstraintOfTypeParameter(type) : getBaseConstraintOfType(type); + type = (type as TypeParameter).isThisType ? getConstraintOfTypeParameter(type)! : getBaseConstraintOfType(type)!; // TODO: GH#18217 Use a different variable that's allowed to be undefined } if (!type || !hasBaseType(type, enclosingClass)) { error(errorNode, Diagnostics.Property_0_is_protected_and_only_accessible_through_an_instance_of_class_1, symbolToString(prop), typeToString(enclosingClass)); @@ -17123,7 +17165,7 @@ namespace ts { } const flowType = getFlowTypeOfReference(node, propType, assumeUninitialized ? getOptionalType(propType) : propType); if (assumeUninitialized && !(getFalsyFlags(propType) & TypeFlags.Undefined) && getFalsyFlags(flowType) & TypeFlags.Undefined) { - error(right, Diagnostics.Property_0_is_used_before_being_assigned, symbolToString(prop)); + error(right, Diagnostics.Property_0_is_used_before_being_assigned, symbolToString(prop!)); // TODO: GH#18217 // Return the declared type to reduce follow-on errors return propType; } @@ -17168,12 +17210,12 @@ namespace ts { * In that case we won't consider it used before its declaration, because it gets its value from the superclass' declaration. */ function isPropertyDeclaredInAncestorClass(prop: Symbol): boolean { - if (!(prop.parent.flags & SymbolFlags.Class)) { + if (!(prop.parent!.flags & SymbolFlags.Class)) { return false; } - let classType = getTypeOfSymbol(prop.parent); + let classType: InterfaceType | undefined = getTypeOfSymbol(prop.parent!) as InterfaceType; while (true) { - classType = classType.symbol && getSuperClass(classType as InterfaceType); + classType = classType.symbol && getSuperClass(classType) as InterfaceType | undefined; if (!classType) { return false; } @@ -17193,7 +17235,7 @@ namespace ts { } function reportNonexistentProperty(propNode: Identifier, containingType: Type) { - let errorInfo: DiagnosticMessageChain; + let errorInfo: DiagnosticMessageChain | undefined; if (containingType.flags & TypeFlags.Union && !(containingType.flags & TypeFlags.Primitive)) { for (const subtype of (containingType as UnionType).types) { if (!getPropertyOfType(subtype, propNode.escapedText)) { @@ -17223,7 +17265,7 @@ namespace ts { return suggestion && symbolName(suggestion); } - function getSuggestionForNonexistentSymbol(location: Node, outerName: __String, meaning: SymbolFlags): string { + function getSuggestionForNonexistentSymbol(location: Node | undefined, outerName: __String, meaning: SymbolFlags): string | undefined { Debug.assert(outerName !== undefined, "outername should always be defined"); const result = resolveNameHelper(location, outerName, meaning, /*nameNotFoundMessage*/ undefined, outerName, /*isUse*/ false, /*excludeGlobals*/ false, (symbols, name, meaning) => { Debug.assertEqual(outerName, name, "name should equal outerName"); @@ -17357,7 +17399,7 @@ namespace ts { } } - (getCheckFlags(prop) & CheckFlags.Instantiated ? getSymbolLinks(prop).target : prop).isReferenced = SymbolFlags.All; + (getCheckFlags(prop) & CheckFlags.Instantiated ? getSymbolLinks(prop).target : prop)!.isReferenced = SymbolFlags.All; } function isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName | ImportTypeNode, propertyName: __String): boolean { @@ -17405,13 +17447,13 @@ namespace ts { const prop = getPropertyOfType(type, propertyName); return prop ? checkPropertyAccessibility(node, left, type, prop) // In js files properties of unions are allowed in completion - : isInJavaScriptFile(node) && (type.flags & TypeFlags.Union) && (type).types.some(elementType => isValidPropertyAccessWithType(node, left, propertyName, elementType)); + : isInJavaScriptFile(node) && (type.flags & TypeFlags.Union) !== 0 && (type).types.some(elementType => isValidPropertyAccessWithType(node, left, propertyName, elementType)); } /** * Return the symbol of the for-in variable declared or referenced by the given for-in statement. */ - function getForInVariableSymbol(node: ForInStatement): Symbol { + function getForInVariableSymbol(node: ForInStatement): Symbol | undefined { const initializer = node.initializer; if (initializer.kind === SyntaxKind.VariableDeclarationList) { const variable = (initializer).declarations[0]; @@ -17570,10 +17612,10 @@ namespace ts { // const b: B; // b('foo') // <- here overloads should be processed as [(x:'foo'): string, (x: string): void] function reorderCandidates(signatures: Signature[], result: Signature[]): void { - let lastParent: Node; - let lastSymbol: Symbol; + let lastParent: Node | undefined; + let lastSymbol: Symbol | undefined; let cutoffIndex = 0; - let index: number; + let index: number | undefined; let specializedIndex = -1; let spliceIndex: number; Debug.assert(!result.length); @@ -17582,7 +17624,7 @@ namespace ts { const parent = signature.declaration && signature.declaration.parent; if (!lastSymbol || symbol === lastSymbol) { if (lastParent && parent === lastParent) { - index++; + index = index! + 1; } else { lastParent = parent; @@ -17626,9 +17668,9 @@ namespace ts { } function hasCorrectArity(node: CallLikeExpression, args: ReadonlyArray, signature: Signature, signatureHelpTrailingComma = false) { - let argCount: number; // Apparent number of arguments we will have in this call - let typeArguments: NodeArray; // Type arguments (undefined if none) - let callIsIncomplete: boolean; // In incomplete call we want to be lenient when we have too few arguments + let argCount: number; // Apparent number of arguments we will have in this call + let typeArguments: NodeArray | undefined; // Type arguments (undefined if none) + let callIsIncomplete = false; // In incomplete call we want to be lenient when we have too few arguments let spreadArgIndex = -1; if (isJsxOpeningLikeElement(node)) { @@ -17645,8 +17687,7 @@ namespace ts { if (node.template.kind === SyntaxKind.TemplateExpression) { // If a tagged template expression lacks a tail literal, the call is incomplete. // Specifically, a template only can end in a TemplateTail or a Missing literal. - const lastSpan = lastOrUndefined(node.template.templateSpans); - Debug.assert(lastSpan !== undefined); // we should always have at least one span. + const lastSpan = last(node.template.templateSpans); // we should always have at least one span. callIsIncomplete = nodeIsMissing(lastSpan.literal) || !!lastSpan.literal.isUnterminated; } else { @@ -17660,7 +17701,7 @@ namespace ts { } else if (node.kind === SyntaxKind.Decorator) { typeArguments = undefined; - argCount = getEffectiveArgumentCount(node, /*args*/ undefined, signature); + argCount = getEffectiveArgumentCount(node, /*args*/ undefined!, signature); } else { if (!node.arguments) { @@ -17709,7 +17750,7 @@ namespace ts { } // If type has a single call signature and no other members, return that signature. Otherwise, return undefined. - function getSingleCallSignature(type: Type): Signature { + function getSingleCallSignature(type: Type): Signature | undefined { if (type.flags & TypeFlags.Object) { const resolved = resolveStructuredTypeMembers(type); if (resolved.callSignatures.length === 1 && resolved.constructSignatures.length === 0 && @@ -17722,7 +17763,7 @@ namespace ts { // Instantiate a generic signature in the context of a non-generic signature (section 3.8.5 in TypeScript spec) function instantiateSignatureInContextOf(signature: Signature, contextualSignature: Signature, contextualMapper?: TypeMapper, compareTypes?: TypeComparer): Signature { - const context = createInferenceContext(signature.typeParameters, signature, InferenceFlags.InferUnionTypes, compareTypes); + const context = createInferenceContext(signature.typeParameters!, signature, InferenceFlags.InferUnionTypes, compareTypes); forEachMatchingParameterType(contextualSignature, signature, (source, target) => { // Type parameters from outer context referenced by source type are fixed by instantiation of the source type inferTypes(context.inferences, instantiateType(source, contextualMapper || identityMapper), target); @@ -17747,7 +17788,7 @@ namespace ts { return getInferredTypes(context); } - function inferTypeArguments(node: CallLikeExpression, signature: Signature, args: ReadonlyArray, excludeArgument: boolean[], context: InferenceContext): Type[] { + function inferTypeArguments(node: CallLikeExpression, signature: Signature, args: ReadonlyArray, excludeArgument: boolean[] | undefined, context: InferenceContext): Type[] { // Clear out all the inference results from the last time inferTypeArguments was called on this context for (const inference of context.inferences) { // As an optimization, we don't have to clear (and later recompute) inferred types @@ -17810,7 +17851,7 @@ namespace ts { // For context sensitive arguments we pass the identityMapper, which is a signal to treat all // context sensitive function expressions as wildcards const mapper = excludeArgument && excludeArgument[i] !== undefined ? identityMapper : context; - argType = checkExpressionWithContextualType(arg, paramType, mapper); + argType = checkExpressionWithContextualType(arg!, paramType, mapper); } inferTypes(context.inferences, argType, paramType); @@ -17837,15 +17878,15 @@ namespace ts { function checkTypeArguments(signature: Signature, typeArgumentNodes: ReadonlyArray, reportErrors: boolean, headMessage?: DiagnosticMessage): Type[] | false { const isJavascript = isInJavaScriptFile(signature.declaration); - const typeParameters = signature.typeParameters; + const typeParameters = signature.typeParameters!; const typeArgumentTypes = fillMissingTypeArguments(map(typeArgumentNodes, getTypeFromTypeNode), typeParameters, getMinTypeArgumentCount(typeParameters), isJavascript); - let mapper: TypeMapper; + let mapper: TypeMapper | undefined; for (let i = 0; i < typeArgumentNodes.length; i++) { Debug.assert(typeParameters[i] !== undefined, "Should not call checkTypeArguments with too many type arguments"); const constraint = getConstraintOfTypeParameter(typeParameters[i]); if (!constraint) continue; - const errorInfo = reportErrors && headMessage && (() => chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Type_0_does_not_satisfy_the_constraint_1)); + const errorInfo = reportErrors && headMessage ? (() => chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Type_0_does_not_satisfy_the_constraint_1)) : undefined; const typeArgumentHeadMessage = headMessage || Diagnostics.Type_0_does_not_satisfy_the_constraint_1; if (!mapper) { mapper = createTypeMapper(typeParameters, typeArgumentTypes); @@ -17902,7 +17943,7 @@ namespace ts { args: ReadonlyArray, signature: Signature, relation: Map, - excludeArgument: boolean[], + excludeArgument: boolean[] | undefined, reportErrors: boolean) { if (isJsxOpeningLikeElement(node)) { return checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation); @@ -17916,7 +17957,7 @@ namespace ts { const thisArgumentType = thisArgumentNode ? checkExpression(thisArgumentNode) : voidType; const errorNode = reportErrors ? (thisArgumentNode || node) : undefined; const headMessage = Diagnostics.The_this_context_of_type_0_is_not_assignable_to_method_s_this_of_type_1; - if (!checkTypeRelatedTo(thisArgumentType, getThisTypeOfSignature(signature), relation, errorNode, headMessage)) { + if (!checkTypeRelatedTo(thisArgumentType, thisType, relation, errorNode, headMessage)) { return false; } } @@ -17931,7 +17972,7 @@ namespace ts { // If the effective argument type is undefined, there is no synthetic type for the argument. // In that case, we should check the argument. const argType = getEffectiveArgumentType(node, i) || - checkExpressionWithContextualType(arg, paramType, excludeArgument && excludeArgument[i] ? identityMapper : undefined); + checkExpressionWithContextualType(arg!, paramType, excludeArgument && excludeArgument[i] ? identityMapper : undefined); // If one or more arguments are still excluded (as indicated by a non-null excludeArgument parameter), // we obtain the regular type of any object literal arguments because we may not have inferred complete // parameter types yet and therefore excess property checks may yield false positives (see #17041). @@ -17950,7 +17991,7 @@ namespace ts { /** * Returns the this argument in calls like x.f(...) and x[f](...). Undefined otherwise. */ - function getThisArgumentOfCall(node: CallLikeExpression): LeftHandSideExpression { + function getThisArgumentOfCall(node: CallLikeExpression): LeftHandSideExpression | undefined { if (node.kind === SyntaxKind.CallExpression) { const callee = skipOuterExpressions(node.expression); if (callee.kind === SyntaxKind.PropertyAccessExpression || callee.kind === SyntaxKind.ElementAccessExpression) { @@ -17968,10 +18009,10 @@ namespace ts { * If 'node' is a Decorator, the argument list will be `undefined`, and its arguments and types * will be supplied from calls to `getEffectiveArgumentCount` and `getEffectiveArgumentType`. */ - function getEffectiveCallArguments(node: CallLikeExpression): ReadonlyArray { + function getEffectiveCallArguments(node: CallLikeExpression): ReadonlyArray | undefined { if (node.kind === SyntaxKind.TaggedTemplateExpression) { const template = node.template; - const args: Expression[] = [undefined]; + const args: Expression[] = [undefined!]; // TODO: GH#18217 if (template.kind === SyntaxKind.TemplateExpression) { forEach(template.templateSpans, span => { args.push(span.expression); @@ -18038,8 +18079,10 @@ namespace ts { case SyntaxKind.Parameter: // A parameter declaration decorator will have three arguments (see // `ParameterDecorator` in core.d.ts) - return 3; + + default: + return Debug.fail(); } } else { @@ -18064,7 +18107,7 @@ namespace ts { if (node.kind === SyntaxKind.ClassDeclaration) { // For a class decorator, the `target` is the type of the class (e.g. the // "static" or "constructor" side of the class) - const classSymbol = getSymbolOfNode(node); + const classSymbol = getSymbolOfNode(node as ClassDeclaration); return getTypeOfSymbol(classSymbol); } @@ -18073,7 +18116,7 @@ namespace ts { // parameter's containing method. node = node.parent; if (node.kind === SyntaxKind.Constructor) { - const classSymbol = getSymbolOfNode(node); + const classSymbol = getSymbolOfNode(node as ConstructorDeclaration); return getTypeOfSymbol(classSymbol); } } @@ -18135,15 +18178,16 @@ namespace ts { // otherwise, if the member name is a computed property name it will // be either string or symbol. const element = node; - switch (element.name.kind) { + const name = element.name!; + switch (name.kind) { case SyntaxKind.Identifier: - return getLiteralType(idText(element.name)); + return getLiteralType(idText(name)); case SyntaxKind.NumericLiteral: case SyntaxKind.StringLiteral: - return getLiteralType(element.name.text); + return getLiteralType(name.text); case SyntaxKind.ComputedPropertyName: - const nameType = checkComputedPropertyName(element.name); + const nameType = checkComputedPropertyName(name); if (isTypeAssignableToKind(nameType, TypeFlags.ESSymbolLike)) { return nameType; } @@ -18191,7 +18235,7 @@ namespace ts { node.kind === SyntaxKind.SetAccessor) { // The `descriptor` for a method decorator will be a `TypedPropertyDescriptor` // for the type of the member. - const propertyType = getTypeOfNode(node); + const propertyType = getTypeOfNode(node)!; // TODO: GH#18217 return createTypedPropertyDescriptorType(propertyType); } @@ -18220,7 +18264,7 @@ namespace ts { /** * Gets the effective argument type for an argument in a call expression. */ - function getEffectiveArgumentType(node: CallLikeExpression, argIndex: number): Type { + function getEffectiveArgumentType(node: CallLikeExpression, argIndex: number): Type | undefined { // Decorators provide special arguments, a tagged template expression provides // a special first argument, and string literals get string literal types // unless we're reporting errors @@ -18252,7 +18296,7 @@ namespace ts { /** * Gets the error node to use when reporting errors for an effective argument. */ - function getEffectiveArgumentErrorNode(node: CallLikeExpression, argIndex: number, arg: Expression) { + function getEffectiveArgumentErrorNode(node: CallLikeExpression, argIndex: number, arg: Expression | undefined): Expression | undefined { if (node.kind === SyntaxKind.Decorator) { // For a decorator, we use the expression of the decorator for error reporting. return node.expression; @@ -18277,12 +18321,12 @@ namespace ts { return createDiagnosticForNodeArray(getSourceFileOfNode(node), typeArguments, Diagnostics.Expected_0_type_arguments_but_got_1, paramCount, typeArguments.length); } - function resolveCall(node: CallLikeExpression, signatures: Signature[], candidatesOutArray: Signature[], fallbackError?: DiagnosticMessage): Signature { + function resolveCall(node: CallLikeExpression, signatures: Signature[], candidatesOutArray: Signature[] | undefined, fallbackError?: DiagnosticMessage): Signature { const isTaggedTemplate = node.kind === SyntaxKind.TaggedTemplateExpression; const isDecorator = node.kind === SyntaxKind.Decorator; const isJsxOpeningOrSelfClosingElement = isJsxOpeningLikeElement(node); - let typeArguments: NodeArray; + let typeArguments: NodeArray | undefined; if (!isDecorator) { typeArguments = (node).typeArguments; @@ -18318,15 +18362,15 @@ namespace ts { // For a decorator, no arguments are susceptible to contextual typing due to the fact // decorators are applied to a declaration by the emitter, and not to an expression. const isSingleNonGenericCandidate = candidates.length === 1 && !candidates[0].typeParameters; - let excludeArgument: boolean[]; + let excludeArgument: boolean[] | undefined; let excludeCount = 0; if (!isDecorator && !isSingleNonGenericCandidate) { // We do not need to call `getEffectiveArgumentCount` here as it only // applies when calculating the number of arguments for a decorator. - for (let i = isTaggedTemplate ? 1 : 0; i < args.length; i++) { - if (isContextSensitive(args[i])) { + for (let i = isTaggedTemplate ? 1 : 0; i < args!.length; i++) { + if (isContextSensitive(args![i])) { if (!excludeArgument) { - excludeArgument = new Array(args.length); + excludeArgument = new Array(args!.length); } excludeArgument[i] = true; excludeCount++; @@ -18355,9 +18399,9 @@ namespace ts { // function foo(): void; // foo(0); // - let candidateForArgumentError: Signature; - let candidateForTypeArgumentError: Signature; - let result: Signature; + let candidateForArgumentError: Signature | undefined; + let candidateForTypeArgumentError: Signature | undefined; + let result: Signature | undefined; // If we are in signature help, a trailing comma indicates that we intend to provide another argument, // so we will only accept overloads with arity at least 1 higher than the current number of provided arguments. @@ -18398,12 +18442,12 @@ namespace ts { // in arguments too early. If possible, we'd like to only type them once we know the correct // overload. However, this matters for the case where the call is correct. When the call is // an error, we don't need to exclude any arguments, although it would cause no harm to do so. - checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, /*excludeArgument*/ undefined, /*reportErrors*/ true); + checkApplicableSignature(node, args!, candidateForArgumentError, assignableRelation, /*excludeArgument*/ undefined, /*reportErrors*/ true); } else if (candidateForTypeArgumentError) { - checkTypeArguments(candidateForTypeArgumentError, (node as CallExpression | TaggedTemplateExpression).typeArguments, /*reportErrors*/ true, fallbackError); + checkTypeArguments(candidateForTypeArgumentError, (node as CallExpression | TaggedTemplateExpression).typeArguments!, /*reportErrors*/ true, fallbackError); } - else if (typeArguments && every(signatures, sig => length(sig.typeParameters) !== typeArguments.length)) { + else if (typeArguments && every(signatures, sig => length(sig.typeParameters) !== typeArguments!.length)) { diagnostics.add(getTypeArgumentArityError(node, signatures, typeArguments)); } else if (args) { @@ -18442,12 +18486,12 @@ namespace ts { // f(" if (!produceDiagnostics) { Debug.assert(candidates.length > 0); // Else would have exited above. - const bestIndex = getLongestCandidateIndex(candidates, apparentArgumentCount === undefined ? args.length : apparentArgumentCount); + const bestIndex = getLongestCandidateIndex(candidates, apparentArgumentCount === undefined ? args!.length : apparentArgumentCount); const candidate = candidates[bestIndex]; const { typeParameters } = candidate; if (typeParameters && callLikeExpressionMayHaveTypeArguments(node) && node.typeArguments) { - const typeArguments = node.typeArguments.map(getTypeOfNode); + const typeArguments = node.typeArguments.map(getTypeOfNode) as Type[]; // TODO: GH#18217 while (typeArguments.length > typeParameters.length) { typeArguments.pop(); } @@ -18471,10 +18515,10 @@ namespace ts { if (isSingleNonGenericCandidate) { const candidate = candidates[0]; - if (!hasCorrectArity(node, args, candidate, signatureHelpTrailingComma)) { + if (!hasCorrectArity(node, args!, candidate, signatureHelpTrailingComma)) { return undefined; } - if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, /*reportErrors*/ false)) { + if (!checkApplicableSignature(node, args!, candidate, relation, excludeArgument, /*reportErrors*/ false)) { candidateForArgumentError = candidate; return undefined; } @@ -18483,7 +18527,7 @@ namespace ts { for (let candidateIndex = 0; candidateIndex < candidates.length; candidateIndex++) { const originalCandidate = candidates[candidateIndex]; - if (!hasCorrectArity(node, args, originalCandidate, signatureHelpTrailingComma)) { + if (!hasCorrectArity(node, args!, originalCandidate, signatureHelpTrailingComma)) { continue; } @@ -18507,12 +18551,12 @@ namespace ts { } } else { - typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext); + typeArgumentTypes = inferTypeArguments(node, candidate, args!, excludeArgument, inferenceContext!); } const isJavascript = isInJavaScriptFile(candidate.declaration); candidate = getSignatureInstantiation(candidate, typeArgumentTypes, isJavascript); } - if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, /*reportErrors*/ false)) { + if (!checkApplicableSignature(node, args!, candidate, relation, excludeArgument, /*reportErrors*/ false)) { candidateForArgumentError = candidate; break; } @@ -18522,7 +18566,7 @@ namespace ts { } excludeCount--; if (excludeCount > 0) { - excludeArgument[excludeArgument.indexOf(/*value*/ true)] = false; + excludeArgument![excludeArgument!.indexOf(/*value*/ true)] = false; } else { excludeArgument = undefined; @@ -18552,7 +18596,7 @@ namespace ts { return maxParamsIndex; } - function resolveCallExpression(node: CallExpression, candidatesOutArray: Signature[]): Signature { + function resolveCallExpression(node: CallExpression, candidatesOutArray: Signature[] | undefined): Signature { if (node.expression.kind === SyntaxKind.SuperKeyword) { const superType = checkSuperExpression(node.expression); if (isTypeAny(superType)) { @@ -18561,7 +18605,7 @@ namespace ts { if (superType !== unknownType) { // In super call, the candidate signatures are the matching arity signatures of the base constructor function instantiated // with the type arguments specified in the extends clause. - const baseTypeNode = getClassExtendsHeritageClauseElement(getContainingClass(node)); + const baseTypeNode = getClassExtendsHeritageClauseElement(getContainingClass(node)!); if (baseTypeNode) { const baseConstructors = getInstantiatedConstructorsForTypeArguments(superType, baseTypeNode.typeArguments, baseTypeNode); return resolveCall(node, baseConstructors, candidatesOutArray); @@ -18631,7 +18675,7 @@ namespace ts { !numCallSignatures && !numConstructSignatures && !(apparentFuncType.flags & (TypeFlags.Union | TypeFlags.Never)) && isTypeAssignableTo(funcType, globalFunctionType); } - function resolveNewExpression(node: NewExpression, candidatesOutArray: Signature[]): Signature { + function resolveNewExpression(node: NewExpression, candidatesOutArray: Signature[] | undefined): Signature { if (node.arguments && languageVersion < ScriptTarget.ES5) { const spreadIndex = getSpreadArgumentIndex(node.arguments); if (spreadIndex >= 0) { @@ -18720,7 +18764,7 @@ namespace ts { return true; } - const declaringClassDeclaration = getClassLikeDeclarationOfSymbol(declaration.parent.symbol); + const declaringClassDeclaration = getClassLikeDeclarationOfSymbol(declaration.parent.symbol)!; const declaringClass = getDeclaredTypeOfSymbol(declaration.parent.symbol); // A private or protected constructor can only be instantiated within its own class (or a subclass, for protected) @@ -18766,13 +18810,13 @@ namespace ts { // Create a diagnostic on the originating import if possible onto which we can attach a quickfix // An import call expression cannot be rewritten into another form to correct the error - the only solution is to use `.default` at the use-site if (importNode && !isImportCall(importNode)) { - const sigs = getSignaturesOfType(getTypeOfSymbol(getSymbolLinks(apparentType.symbol).target), kind); + const sigs = getSignaturesOfType(getTypeOfSymbol(getSymbolLinks(apparentType.symbol).target!), kind); if (!sigs || !sigs.length) return; error(importNode, Diagnostics.A_namespace_style_import_cannot_be_called_or_constructed_and_will_cause_a_failure_at_runtime); } } - function resolveTaggedTemplateExpression(node: TaggedTemplateExpression, candidatesOutArray: Signature[]): Signature { + function resolveTaggedTemplateExpression(node: TaggedTemplateExpression, candidatesOutArray: Signature[] | undefined): Signature { const tagType = checkExpression(node.tag); const apparentType = getApparentType(tagType); @@ -18815,13 +18859,16 @@ namespace ts { case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: return Diagnostics.Unable_to_resolve_signature_of_method_decorator_when_called_as_an_expression; + + default: + return Debug.fail(); } } /** * Resolves a decorator as if it were a call expression. */ - function resolveDecorator(node: Decorator, candidatesOutArray: Signature[]): Signature { + function resolveDecorator(node: Decorator, candidatesOutArray: Signature[] | undefined): Signature { const funcType = checkExpression(node.expression); const apparentType = getApparentType(funcType); if (apparentType === unknownType) { @@ -18842,8 +18889,7 @@ namespace ts { const headMessage = getDiagnosticHeadMessageForDecoratorResolution(node); if (!callSignatures.length) { - let errorInfo: DiagnosticMessageChain; - errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures, typeToString(apparentType)); + let errorInfo = chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures, typeToString(apparentType)); errorInfo = chainDiagnosticMessages(errorInfo, headMessage); diagnostics.add(createDiagnosticForNodeFromMessageChain(node, errorInfo)); invocationErrorRecovery(apparentType, SignatureKind.Call); @@ -18862,7 +18908,7 @@ namespace ts { return signatures.length && every(signatures, signature => signature.minArgumentCount === 0 && !signature.hasRestParameter && - signature.parameters.length < getEffectiveArgumentCount(decorator, /*args*/ undefined, signature)); + signature.parameters.length < getEffectiveArgumentCount(decorator, /*args*/ undefined!, signature)); } /** @@ -18875,7 +18921,7 @@ namespace ts { * @param candidatesOutArray an array of signature to be filled in by the function. It is passed by signature help in the language service; * the function will fill it up with appropriate candidate signatures */ - function getResolvedJsxStatelessFunctionSignature(openingLikeElement: JsxOpeningLikeElement, elementType: Type, candidatesOutArray: Signature[]): Signature | undefined { + function getResolvedJsxStatelessFunctionSignature(openingLikeElement: JsxOpeningLikeElement, elementType: Type, candidatesOutArray: Signature[] | undefined): Signature | undefined { Debug.assert(!(elementType.flags & TypeFlags.Union)); const callSignatures = elementType && getSignaturesOfType(elementType, SignatureKind.Call); if (callSignatures && callSignatures.length > 0) { @@ -18906,12 +18952,12 @@ namespace ts { } const sigs = getInstantiatedJsxSignatures(node, exprType); if (candidatesOutArray && length(sigs)) { - candidatesOutArray.push(...sigs); + candidatesOutArray.push(...sigs!); } - return length(sigs) ? sigs[0] : unknownSignature; + return length(sigs) ? sigs![0] : unknownSignature; }) || unknownSignature; } - Debug.assertNever(node, "Branch in 'resolveSignature' should be unreachable."); + throw Debug.assertNever(node, "Branch in 'resolveSignature' should be unreachable."); } /** @@ -18954,7 +19000,7 @@ namespace ts { isVariableDeclaration(node) && node.initializer && isFunctionExpression(node.initializer) ? getSymbolOfNode(node.initializer) : undefined; - return symbol && symbol.members !== undefined; + return !!symbol && symbol.members !== undefined; } return false; @@ -18963,7 +19009,7 @@ namespace ts { function getJavaScriptClassType(symbol: Symbol): Type | undefined { const initializer = getDeclaredJavascriptInitializer(symbol.valueDeclaration); if (initializer) { - symbol = getSymbolOfNode(initializer); + symbol = getSymbolOfNode(initializer)!; } let inferred: Type | undefined; if (isJavaScriptConstructor(symbol.valueDeclaration)) { @@ -19066,7 +19112,7 @@ namespace ts { // In JavaScript files, calls to any identifier 'require' are treated as external module imports if (isInJavaScriptFile(node) && isCommonJsRequire(node)) { - return resolveExternalModuleTypeByLiteral(node.arguments[0] as StringLiteral); + return resolveExternalModuleTypeByLiteral(node.arguments![0] as StringLiteral); } const returnType = getReturnTypeOfSignature(signature); @@ -19158,7 +19204,7 @@ namespace ts { // Make sure require is not a local function if (!isIdentifier(node.expression)) return Debug.fail(); - const resolvedRequire = resolveName(node.expression, node.expression.escapedText, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true); + const resolvedRequire = resolveName(node.expression, node.expression.escapedText, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true)!; // TODO: GH#18217 if (resolvedRequire === requireSymbol) { return true; } @@ -19173,7 +19219,7 @@ namespace ts { ? SyntaxKind.VariableDeclaration : SyntaxKind.Unknown; if (targetDeclarationKind !== SyntaxKind.Unknown) { - const decl = getDeclarationOfKind(resolvedRequire, targetDeclarationKind); + const decl = getDeclarationOfKind(resolvedRequire, targetDeclarationKind)!; // function/variable declaration should be ambient return !!decl && !!(decl.flags & NodeFlags.Ambient); } @@ -19211,7 +19257,7 @@ namespace ts { return getNonNullableType(checkExpression(node.expression)); } - function checkMetaProperty(node: MetaProperty) { + function checkMetaProperty(node: MetaProperty): Type { checkGrammarMetaProperty(node); if (node.keywordToken === SyntaxKind.NewKeyword) { @@ -19221,6 +19267,8 @@ namespace ts { if (node.keywordToken === SyntaxKind.ImportKeyword) { return checkImportMetaProperty(node); } + + return Debug.assertNever(node.keywordToken); } function checkNewTargetMetaProperty(node: MetaProperty) { @@ -19230,11 +19278,11 @@ namespace ts { return unknownType; } else if (container.kind === SyntaxKind.Constructor) { - const symbol = getSymbolOfNode(container.parent); + const symbol = getSymbolOfNode(container.parent as ClassLikeDeclaration); return getTypeOfSymbol(symbol); } else { - const symbol = getSymbolOfNode(container); + const symbol = getSymbolOfNode(container)!; return getTypeOfSymbol(symbol); } } @@ -19296,7 +19344,7 @@ namespace ts { if (!parameter) { signature.thisParameter = createSymbolWithType(context.thisParameter, /*type*/ undefined); } - assignTypeToParameterAndFixTypeParameters(signature.thisParameter, getTypeOfSymbol(context.thisParameter)); + assignTypeToParameterAndFixTypeParameters(signature.thisParameter!, getTypeOfSymbol(context.thisParameter)); } } const len = signature.parameters.length - (signature.hasRestParameter ? 1 : 0); @@ -19309,9 +19357,9 @@ namespace ts { } if (signature.hasRestParameter && isRestParameterIndex(context, signature.parameters.length - 1)) { // parameter might be a transient symbol generated by use of `arguments` in the function body. - const parameter = lastOrUndefined(signature.parameters); + const parameter = last(signature.parameters); if (isTransientSymbol(parameter) || !getEffectiveTypeAnnotationNode(parameter.valueDeclaration)) { - const contextualParameterType = getTypeOfSymbol(lastOrUndefined(context.parameters)); + const contextualParameterType = getTypeOfSymbol(last(context.parameters)); assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType); } } @@ -19468,7 +19516,7 @@ namespace ts { } } - function checkAndAggregateYieldOperandTypes(func: FunctionLikeDeclaration, checkMode: CheckMode): Type[] { + function checkAndAggregateYieldOperandTypes(func: FunctionLikeDeclaration, checkMode: CheckMode | undefined): Type[] { const aggregatedTypes: Type[] = []; const isAsync = (getFunctionFlags(func) & FunctionFlags.Async) !== 0; forEachYieldExpression(func.body, yieldExpression => { @@ -19477,7 +19525,7 @@ namespace ts { return aggregatedTypes; } - function getYieldedTypeOfYieldExpression(node: YieldExpression, isAsync: boolean, checkMode?: CheckMode): Type { + function getYieldedTypeOfYieldExpression(node: YieldExpression, isAsync: boolean, checkMode?: CheckMode): Type | undefined { const errorNode = node.expression || node; const expressionType = node.expression ? checkExpressionCached(node.expression, checkMode) : undefinedWideningType; // A `yield*` expression effectively yields everything that its operand yields @@ -19514,7 +19562,7 @@ namespace ts { } /** NOTE: Return value of `[]` means a different thing than `undefined`. `[]` means func returns `void`, `undefined` means it returns `never`. */ - function checkAndAggregateReturnExpressionTypes(func: FunctionLikeDeclaration, checkMode: CheckMode): Type[] | undefined { + function checkAndAggregateReturnExpressionTypes(func: FunctionLikeDeclaration, checkMode: CheckMode | undefined): Type[] | undefined { const functionFlags = getFunctionFlags(func); const aggregatedTypes: Type[] = []; let hasReturnWithNoExpression = functionHasImplicitReturn(func); @@ -19570,7 +19618,7 @@ namespace ts { * * @param returnType - return type of the function, can be undefined if return type is not explicitly specified */ - function checkAllCodePathsInNonVoidFunctionReturnOrThrow(func: FunctionLikeDeclaration | MethodSignature, returnType: Type): void { + function checkAllCodePathsInNonVoidFunctionReturnOrThrow(func: FunctionLikeDeclaration | MethodSignature, returnType: Type | undefined): void { if (!produceDiagnostics) { return; } @@ -19582,7 +19630,7 @@ namespace ts { // If all we have is a function signature, or an arrow function with an expression body, then there is nothing to check. // also if HasImplicitReturn flag is not set this means that all codepaths in function body end with return or throw - if (func.kind === SyntaxKind.MethodSignature || nodeIsMissing(func.body) || func.body.kind !== SyntaxKind.Block || !functionHasImplicitReturn(func)) { + if (func.kind === SyntaxKind.MethodSignature || nodeIsMissing(func.body) || func.body!.kind !== SyntaxKind.Block || !functionHasImplicitReturn(func)) { return; } @@ -19766,10 +19814,10 @@ namespace ts { if (expr.kind === SyntaxKind.PropertyAccessExpression || expr.kind === SyntaxKind.ElementAccessExpression) { const node = skipParentheses((expr as PropertyAccessExpression | ElementAccessExpression).expression); if (node.kind === SyntaxKind.Identifier) { - const symbol = getNodeLinks(node).resolvedSymbol; + const symbol = getNodeLinks(node).resolvedSymbol!; if (symbol.flags & SymbolFlags.Alias) { const declaration = getDeclarationOfAliasSymbol(symbol); - return declaration && declaration.kind === SyntaxKind.NamespaceImport; + return !!declaration && declaration.kind === SyntaxKind.NamespaceImport; } } } @@ -19907,15 +19955,15 @@ namespace ts { if (strict && source.flags & (TypeFlags.Any | TypeFlags.Void | TypeFlags.Undefined | TypeFlags.Null)) { return false; } - return (kind & TypeFlags.NumberLike && isTypeAssignableTo(source, numberType)) || - (kind & TypeFlags.StringLike && isTypeAssignableTo(source, stringType)) || - (kind & TypeFlags.BooleanLike && isTypeAssignableTo(source, booleanType)) || - (kind & TypeFlags.Void && isTypeAssignableTo(source, voidType)) || - (kind & TypeFlags.Never && isTypeAssignableTo(source, neverType)) || - (kind & TypeFlags.Null && isTypeAssignableTo(source, nullType)) || - (kind & TypeFlags.Undefined && isTypeAssignableTo(source, undefinedType)) || - (kind & TypeFlags.ESSymbol && isTypeAssignableTo(source, esSymbolType)) || - (kind & TypeFlags.NonPrimitive && isTypeAssignableTo(source, nonPrimitiveType)); + return !!(kind & TypeFlags.NumberLike) && isTypeAssignableTo(source, numberType) || + !!(kind & TypeFlags.StringLike) && isTypeAssignableTo(source, stringType) || + !!(kind & TypeFlags.BooleanLike) && isTypeAssignableTo(source, booleanType) || + !!(kind & TypeFlags.Void) && isTypeAssignableTo(source, voidType) || + !!(kind & TypeFlags.Never) && isTypeAssignableTo(source, neverType) || + !!(kind & TypeFlags.Null) && isTypeAssignableTo(source, nullType) || + !!(kind & TypeFlags.Undefined) && isTypeAssignableTo(source, undefinedType) || + !!(kind & TypeFlags.ESSymbol) && isTypeAssignableTo(source, esSymbolType) || + !!(kind & TypeFlags.NonPrimitive) && isTypeAssignableTo(source, nonPrimitiveType); } function allTypesAssignableToKind(source: Type, kind: TypeFlags, strict?: boolean): boolean { @@ -19925,7 +19973,7 @@ namespace ts { } function isConstEnumObjectType(type: Type): boolean { - return getObjectFlags(type) & ObjectFlags.Anonymous && type.symbol && isConstEnumSymbol(type.symbol); + return !!(getObjectFlags(type) & ObjectFlags.Anonymous) && !!type.symbol && isConstEnumSymbol(type.symbol); } function isConstEnumSymbol(symbol: Symbol): boolean { @@ -20020,7 +20068,7 @@ namespace ts { const nonRestNames: PropertyName[] = []; if (allProperties) { for (let i = 0; i < allProperties.length - 1; i++) { - nonRestNames.push(allProperties[i].name); + nonRestNames.push(allProperties[i].name!); } } const type = getRestType(objectLiteralType, nonRestNames, objectLiteralType.symbol); @@ -20104,7 +20152,7 @@ namespace ts { !(getFalsyFlags(checkExpression(prop.objectAssignmentInitializer)) & TypeFlags.Undefined)) { sourceType = getTypeWithFacts(sourceType, TypeFacts.NEUndefined); } - checkBinaryLikeExpression(prop.name, prop.equalsToken, prop.objectAssignmentInitializer, checkMode); + checkBinaryLikeExpression(prop.name, prop.equalsToken!, prop.objectAssignmentInitializer, checkMode); } target = (exprOrAssignment).name; } @@ -20213,7 +20261,7 @@ namespace ts { return checkBinaryLikeExpression(node.left, node.operatorToken, node.right, checkMode, node); } - function checkBinaryLikeExpression(left: Expression, operatorToken: Node, right: Expression, checkMode?: CheckMode, errorNode?: Node) { + function checkBinaryLikeExpression(left: Expression, operatorToken: Node, right: Expression, checkMode?: CheckMode, errorNode?: Node): Type { const operator = operatorToken.kind; if (operator === SyntaxKind.EqualsToken && (left.kind === SyntaxKind.ObjectLiteralExpression || left.kind === SyntaxKind.ArrayLiteralExpression)) { return checkDestructuringAssignment(left, checkExpression(right, checkMode), checkMode); @@ -20250,7 +20298,7 @@ namespace ts { leftType = checkNonNullType(leftType, left); rightType = checkNonNullType(rightType, right); - let suggestedOperator: SyntaxKind; + let suggestedOperator: SyntaxKind | undefined; // if a user tries to apply a bitwise operator to 2 boolean operands // try and return them a helpful suggestion if ((leftType.flags & TypeFlags.BooleanLike) && @@ -20279,7 +20327,7 @@ namespace ts { rightType = checkNonNullType(rightType, right); } - let resultType: Type; + let resultType: Type | undefined; if (isTypeAssignableToKind(leftType, TypeFlags.NumberLike, /*strict*/ true) && isTypeAssignableToKind(rightType, TypeFlags.NumberLike, /*strict*/ true)) { // Operands of an enum type are treated as having the primitive type Number. // If both operands are of the Number primitive type, the result is of the Number primitive type. @@ -20356,6 +20404,9 @@ namespace ts { error(left, Diagnostics.Left_side_of_comma_operator_is_unused_and_has_no_side_effects); } return rightType; + + default: + return Debug.fail(); } function checkSpecialAssignment(left: Node, right: Expression) { @@ -20394,7 +20445,7 @@ namespace ts { return true; } - function getSuggestedBooleanOperator(operator: SyntaxKind): SyntaxKind { + function getSuggestedBooleanOperator(operator: SyntaxKind): SyntaxKind | undefined { switch (operator) { case SyntaxKind.BarToken: case SyntaxKind.BarEqualsToken: @@ -20462,7 +20513,8 @@ namespace ts { } const func = getContainingFunction(node); - const functionFlags = func ? getFunctionFlags(func) : FunctionFlags.Normal; + if (!func) return anyType; + const functionFlags = getFunctionFlags(func); if (!(functionFlags & FunctionFlags.Generator)) { // If the user's code is syntactically correct, the func should always have a star. After all, we are in a yield context. @@ -20485,7 +20537,7 @@ namespace ts { } const isAsync = (functionFlags & FunctionFlags.Async) !== 0; - const yieldedType = getYieldedTypeOfYieldExpression(node, isAsync); + const yieldedType = getYieldedTypeOfYieldExpression(node, isAsync)!; // TODO: GH#18217 // There is no point in doing an assignability check if the function // has no explicit return type because the return type is directly computed // from the yield expressions. @@ -20566,7 +20618,7 @@ namespace ts { function checkDeclarationInitializer(declaration: HasExpressionInitializer) { const inJs = isInJavaScriptFile(declaration); - const initializer = inJs && getDeclaredJavascriptInitializer(declaration) || declaration.initializer; + const initializer = inJs && getDeclaredJavascriptInitializer(declaration) || declaration.initializer!; const type = getTypeOfExpression(initializer, /*cache*/ true); const widened = getCombinedNodeFlags(declaration) & NodeFlags.Const || (getCombinedModifierFlags(declaration) & ModifierFlags.Readonly && !isParameterPropertyDeclaration(declaration)) || @@ -20597,7 +20649,7 @@ namespace ts { return false; } - function isLiteralOfContextualType(candidateType: Type, contextualType: Type): boolean { + function isLiteralOfContextualType(candidateType: Type, contextualType: Type | undefined): boolean { if (contextualType) { if (contextualType.flags & TypeFlags.UnionOrIntersection) { const types = (contextualType).types; @@ -20617,15 +20669,15 @@ namespace ts { } // If the contextual type is a literal of a particular primitive type, we consider this a // literal context for all literals of that primitive type. - return contextualType.flags & (TypeFlags.StringLiteral | TypeFlags.Index) && maybeTypeOfKind(candidateType, TypeFlags.StringLiteral) || + return !!(contextualType.flags & (TypeFlags.StringLiteral | TypeFlags.Index) && maybeTypeOfKind(candidateType, TypeFlags.StringLiteral) || contextualType.flags & TypeFlags.NumberLiteral && maybeTypeOfKind(candidateType, TypeFlags.NumberLiteral) || contextualType.flags & TypeFlags.BooleanLiteral && maybeTypeOfKind(candidateType, TypeFlags.BooleanLiteral) || - contextualType.flags & TypeFlags.UniqueESSymbol && maybeTypeOfKind(candidateType, TypeFlags.UniqueESSymbol); + contextualType.flags & TypeFlags.UniqueESSymbol && maybeTypeOfKind(candidateType, TypeFlags.UniqueESSymbol)); } return false; } - function checkExpressionForMutableLocation(node: Expression, checkMode: CheckMode, contextualType?: Type): Type { + function checkExpressionForMutableLocation(node: Expression, checkMode: CheckMode | undefined, contextualType?: Type): Type { if (arguments.length === 2) { contextualType = getContextualType(node); } @@ -20752,12 +20804,12 @@ namespace ts { function checkParenthesizedExpression(node: ParenthesizedExpression, checkMode?: CheckMode): Type { const tag = isInJavaScriptFile(node) ? getJSDocTypeTag(node) : undefined; if (tag) { - return checkAssertionWorker(tag, tag.typeExpression.type, node.expression, checkMode); + return checkAssertionWorker(tag, tag.typeExpression!.type, node.expression, checkMode); } return checkExpression(node.expression, checkMode); } - function checkExpressionWorker(node: Expression, checkMode: CheckMode): Type { + function checkExpressionWorker(node: Expression, checkMode: CheckMode | undefined): Type { switch (node.kind) { case SyntaxKind.Identifier: return checkIdentifier(node); @@ -20885,7 +20937,7 @@ namespace ts { checkGrammarDecoratorsAndModifiers(node); checkVariableLikeDeclaration(node); - const func = getContainingFunction(node); + const func = getContainingFunction(node)!; if (hasModifier(node, ModifierFlags.ParameterPropertyModifier)) { if (!(func.kind === SyntaxKind.Constructor && nodeIsPresent(func.body))) { error(node, Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation); @@ -20950,7 +21002,7 @@ namespace ts { else { const leadingError = () => chainDiagnosticMessages(/*details*/ undefined, Diagnostics.A_type_predicate_s_type_must_be_assignable_to_its_parameter_s_type); checkTypeAssignableTo(typePredicate.type, - getTypeOfNode(parent.parameters[typePredicate.parameterIndex]), + getTypeOfNode(parent.parameters[typePredicate.parameterIndex])!, // TODO: GH#18217 node.type, /*headMessage*/ undefined, leadingError); @@ -20972,7 +21024,7 @@ namespace ts { } } - function getTypePredicateParent(node: Node): SignatureDeclaration { + function getTypePredicateParent(node: Node): SignatureDeclaration | undefined { switch (node.parent.kind) { case SyntaxKind.ArrowFunction: case SyntaxKind.CallSignature: @@ -21123,23 +21175,24 @@ namespace ts { const isStatic = hasModifier(member, ModifierFlags.Static); const names = isStatic ? staticNames : instanceNames; - const memberName = member.name && getPropertyNameForPropertyNameNode(member.name); - if (memberName) { + const name = member.name; + const memberName = name && getPropertyNameForPropertyNameNode(name); + if (name && memberName) { switch (member.kind) { case SyntaxKind.GetAccessor: - addName(names, member.name, memberName, Declaration.Getter); + addName(names, name, memberName, Declaration.Getter); break; case SyntaxKind.SetAccessor: - addName(names, member.name, memberName, Declaration.Setter); + addName(names, name, memberName, Declaration.Setter); break; case SyntaxKind.PropertyDeclaration: - addName(names, member.name, memberName, Declaration.Property); + addName(names, name, memberName, Declaration.Property); break; case SyntaxKind.MethodDeclaration: - addName(names, member.name, memberName, Declaration.Method); + addName(names, name, memberName, Declaration.Method); break; } } @@ -21204,13 +21257,14 @@ namespace ts { for (const member of node.members) { if (member.kind === SyntaxKind.PropertySignature) { let memberName: string; - switch (member.name.kind) { + const name = member.name!; + switch (name.kind) { case SyntaxKind.StringLiteral: case SyntaxKind.NumericLiteral: - memberName = member.name.text; + memberName = name.text; break; case SyntaxKind.Identifier: - memberName = idText(member.name); + memberName = idText(name); break; default: continue; @@ -21229,7 +21283,7 @@ namespace ts { function checkTypeForDuplicateIndexSignatures(node: Node) { if (node.kind === SyntaxKind.InterfaceDeclaration) { - const nodeSymbol = getSymbolOfNode(node); + const nodeSymbol = getSymbolOfNode(node as InterfaceDeclaration); // in case of merging interface declaration it is possible that we'll enter this check procedure several times for every declaration // to prevent this run check only for the first declaration of a given kind if (nodeSymbol.declarations.length > 0 && nodeSymbol.declarations[0] !== node) { @@ -21240,14 +21294,14 @@ namespace ts { // TypeScript 1.0 spec (April 2014) // 3.7.4: An object type can contain at most one string index signature and one numeric index signature. // 8.5: A class declaration can have at most one string index member declaration and one numeric index member declaration - const indexSymbol = getIndexSymbol(getSymbolOfNode(node)); + const indexSymbol = getIndexSymbol(getSymbolOfNode(node)!); if (indexSymbol) { let seenNumericIndexer = false; let seenStringIndexer = false; for (const decl of indexSymbol.declarations) { const declaration = decl; if (declaration.parameters.length === 1 && declaration.parameters[0].type) { - switch (declaration.parameters[0].type.kind) { + switch (declaration.parameters[0].type!.kind) { case SyntaxKind.StringKeyword: if (!seenStringIndexer) { seenStringIndexer = true; @@ -21346,8 +21400,8 @@ namespace ts { // Skip past any prologue directives to find the first statement // to ensure that it was a super call. if (superCallShouldBeFirst) { - const statements = node.body.statements; - let superCallStatement: ExpressionStatement; + const statements = node.body!.statements; + let superCallStatement: ExpressionStatement | undefined; for (const statement of statements) { if (statement.kind === SyntaxKind.ExpressionStatement && isSuperCall((statement).expression)) { @@ -21418,7 +21472,7 @@ namespace ts { checkSourceElement(node.body); } - function checkAccessorDeclarationTypesIdentical(first: AccessorDeclaration, second: AccessorDeclaration, getAnnotatedType: (a: AccessorDeclaration) => Type, message: DiagnosticMessage) { + function checkAccessorDeclarationTypesIdentical(first: AccessorDeclaration, second: AccessorDeclaration, getAnnotatedType: (a: AccessorDeclaration) => Type | undefined, message: DiagnosticMessage) { const firstType = getAnnotatedType(first); const secondType = getAnnotatedType(second); if (firstType && secondType && !isTypeIdenticalTo(firstType, secondType)) { @@ -21430,14 +21484,14 @@ namespace ts { checkDecorators(node); } - function getEffectiveTypeArguments(node: TypeReferenceNode | ExpressionWithTypeArguments, typeParameters: TypeParameter[]) { - return fillMissingTypeArguments(map(node.typeArguments, getTypeFromTypeNode), typeParameters, + function getEffectiveTypeArguments(node: TypeReferenceNode | ExpressionWithTypeArguments, typeParameters: TypeParameter[]): Type[] { + return fillMissingTypeArguments(map(node.typeArguments!, getTypeFromTypeNode), typeParameters, getMinTypeArgumentCount(typeParameters), isInJavaScriptFile(node)); } function checkTypeArgumentConstraints(node: TypeReferenceNode | ExpressionWithTypeArguments, typeParameters: TypeParameter[]): boolean { - let typeArguments: Type[]; - let mapper: TypeMapper; + let typeArguments: Type[] | undefined; + let mapper: TypeMapper | undefined; let result = true; for (let i = 0; i < typeParameters.length; i++) { const constraint = getConstraintOfTypeParameter(typeParameters[i]); @@ -21448,8 +21502,8 @@ namespace ts { } result = result && checkTypeAssignableTo( typeArguments[i], - instantiateType(constraint, mapper), - node.typeArguments[i], + instantiateType(constraint, mapper!), + node.typeArguments![i], Diagnostics.Type_0_does_not_satisfy_the_constraint_1); } } @@ -21485,7 +21539,7 @@ namespace ts { } } } - if (type.flags & TypeFlags.Enum && getNodeLinks(node).resolvedSymbol.flags & SymbolFlags.EnumMember) { + if (type.flags & TypeFlags.Enum && getNodeLinks(node).resolvedSymbol!.flags & SymbolFlags.EnumMember) { error(node, Diagnostics.Enum_type_0_has_members_with_initializers_that_are_not_literals, typeToString(type)); } } @@ -21494,8 +21548,8 @@ namespace ts { function getTypeArgumentConstraint(node: TypeNode): Type | undefined { const typeReferenceNode = tryCast(node.parent, isTypeReferenceType); if (!typeReferenceNode) return undefined; - const typeParameters = getTypeParametersForTypeReference(typeReferenceNode); - const constraint = getConstraintOfTypeParameter(typeParameters[typeReferenceNode.typeArguments.indexOf(node)!]); + const typeParameters = getTypeParametersForTypeReference(typeReferenceNode)!; // TODO: GH#18217 + const constraint = getConstraintOfTypeParameter(typeParameters[typeReferenceNode.typeArguments!.indexOf(node)]); return constraint && instantiateType(constraint, createTypeMapper(typeParameters, getEffectiveTypeArguments(typeReferenceNode, typeParameters))); } @@ -21622,17 +21676,17 @@ namespace ts { return; } - function getCanonicalOverload(overloads: Declaration[], implementation: FunctionLikeDeclaration) { + function getCanonicalOverload(overloads: Declaration[], implementation: FunctionLikeDeclaration | undefined): Declaration { // Consider the canonical set of flags to be the flags of the bodyDeclaration or the first declaration // Error on all deviations from this canonical set of flags // The caveat is that if some overloads are defined in lib.d.ts, we don't want to // report the errors on those. To achieve this, we will say that the implementation is // the canonical signature only if it is in the same container as the first overload const implementationSharesContainerWithFirstOverload = implementation !== undefined && implementation.parent === overloads[0].parent; - return implementationSharesContainerWithFirstOverload ? implementation : overloads[0]; + return implementationSharesContainerWithFirstOverload ? implementation! : overloads[0]; } - function checkFlagAgreementBetweenOverloads(overloads: Declaration[], implementation: FunctionLikeDeclaration, flagsToCheck: ModifierFlags, someOverloadFlags: ModifierFlags, allOverloadFlags: ModifierFlags): void { + function checkFlagAgreementBetweenOverloads(overloads: Declaration[], implementation: FunctionLikeDeclaration | undefined, flagsToCheck: ModifierFlags, someOverloadFlags: ModifierFlags, allOverloadFlags: ModifierFlags): void { // Error if some overloads have a flag that is not shared by all overloads. To find the // deviations, we XOR someOverloadFlags with allOverloadFlags const someButNotAllOverloadFlags = someOverloadFlags ^ allOverloadFlags; @@ -21657,7 +21711,7 @@ namespace ts { } } - function checkQuestionTokenAgreementBetweenOverloads(overloads: Declaration[], implementation: FunctionLikeDeclaration, someHaveQuestionToken: boolean, allHaveQuestionToken: boolean): void { + function checkQuestionTokenAgreementBetweenOverloads(overloads: Declaration[], implementation: FunctionLikeDeclaration | undefined, someHaveQuestionToken: boolean, allHaveQuestionToken: boolean): void { if (someHaveQuestionToken !== allHaveQuestionToken) { const canonicalHasQuestionToken = hasQuestionToken(getCanonicalOverload(overloads, implementation)); forEach(overloads, o => { @@ -21675,9 +21729,9 @@ namespace ts { let someHaveQuestionToken = false; let allHaveQuestionToken = true; let hasOverloads = false; - let bodyDeclaration: FunctionLikeDeclaration; - let lastSeenNonAmbientDeclaration: FunctionLikeDeclaration; - let previousDeclaration: SignatureDeclaration; + let bodyDeclaration: FunctionLikeDeclaration | undefined; + let lastSeenNonAmbientDeclaration: FunctionLikeDeclaration | undefined; + let previousDeclaration: SignatureDeclaration | undefined; const declarations = symbol.declarations; const isConstructor = (symbol.flags & SymbolFlags.Constructor) !== 0; @@ -21720,7 +21774,7 @@ namespace ts { return; } else if (nodeIsPresent((subsequentNode).body)) { - error(errorNode, Diagnostics.Function_implementation_name_must_be_0, declarationNameToString(node.name)); + error(errorNode, Diagnostics.Function_implementation_name_must_be_0, declarationNameToString(node.name!)); return; } } @@ -21839,7 +21893,7 @@ namespace ts { if (!symbol) { // local symbol is undefined => this declaration is non-exported. // however symbol might contain other declarations that are exported - symbol = getSymbolOfNode(node); + symbol = getSymbolOfNode(node)!; if (!symbol.exportSymbol) { // this is a pure local symbol (all declarations are non-exported) - no need to check anything return; @@ -21929,7 +21983,7 @@ namespace ts { case SyntaxKind.NamespaceImport: case SyntaxKind.ImportClause: let result = DeclarationSpaces.None; - const target = resolveAlias(getSymbolOfNode(d)); + const target = resolveAlias(getSymbolOfNode(d)!); forEach(target.declarations, d => { result |= getDeclarationSpaces(d); }); return result; case SyntaxKind.VariableDeclaration: @@ -21938,7 +21992,7 @@ namespace ts { case SyntaxKind.ImportSpecifier: // https://github.com/Microsoft/TypeScript/pull/7591 return DeclarationSpaces.ExportValue; default: - Debug.fail(Debug.showSyntaxKind(d)); + return Debug.fail(Debug.showSyntaxKind(d)); } } } @@ -21953,7 +22007,7 @@ namespace ts { * @param type The type of the promise. * @remarks The "promised type" of a type is the type of the "value" parameter of the "onfulfilled" callback. */ - function getPromisedTypeOfPromise(promise: Type, errorNode?: Node): Type { + function getPromisedTypeOfPromise(promise: Type, errorNode?: Node): Type | undefined { // // { // promise // then( // thenFunction @@ -21974,10 +22028,10 @@ namespace ts { } if (isReferenceToType(promise, getGlobalPromiseType(/*reportErrors*/ false))) { - return typeAsPromise.promisedTypeOfPromise = (promise).typeArguments[0]; + return typeAsPromise.promisedTypeOfPromise = (promise).typeArguments![0]; } - const thenFunction = getTypeOfPropertyOfType(promise, "then" as __String); + const thenFunction = getTypeOfPropertyOfType(promise, "then" as __String)!; // TODO: GH#18217 if (isTypeAny(thenFunction)) { return undefined; } @@ -22028,9 +22082,9 @@ namespace ts { } if (type.flags & TypeFlags.Union) { - let types: Type[]; + let types: Type[] | undefined; for (const constituentType of (type).types) { - types = append(types, getAwaitedType(constituentType, errorNode, diagnosticMessage)); + types = append(types, getAwaitedType(constituentType, errorNode, diagnosticMessage)); } if (!types) { @@ -22112,7 +22166,7 @@ namespace ts { const thenFunction = getTypeOfPropertyOfType(type, "then" as __String); if (thenFunction && getSignaturesOfType(thenFunction, SignatureKind.Call).length > 0) { if (errorNode) { - Debug.assert(!!diagnosticMessage); + if (!diagnosticMessage) return Debug.fail(); error(errorNode, diagnosticMessage); } return undefined; @@ -22159,7 +22213,7 @@ namespace ts { // then(...): Promise; // } // - const returnTypeNode = getEffectiveReturnTypeNode(node); + const returnTypeNode = getEffectiveReturnTypeNode(node)!; // TODO: GH#18217 const returnType = getTypeFromTypeNode(returnTypeNode); if (languageVersion >= ScriptTarget.ES2015) { @@ -22215,7 +22269,7 @@ namespace ts { // Verify there is no local declaration that could collide with the promise constructor. const rootName = promiseConstructorName && getFirstIdentifier(promiseConstructorName); - const collidingSymbol = getSymbol(node.locals, rootName.escapedText, SymbolFlags.Value); + const collidingSymbol = getSymbol(node.locals!, rootName.escapedText, SymbolFlags.Value); if (collidingSymbol) { error(collidingSymbol.valueDeclaration, Diagnostics.Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions, idText(rootName), @@ -22238,7 +22292,7 @@ namespace ts { let expectedReturnType: Type; const headMessage = getDiagnosticHeadMessageForDecoratorResolution(node); - let errorInfo: DiagnosticMessageChain; + let errorInfo: DiagnosticMessageChain | undefined; switch (node.parent.kind) { case SyntaxKind.ClassDeclaration: const classSymbol = getSymbolOfNode(node.parent); @@ -22249,7 +22303,7 @@ namespace ts { case SyntaxKind.Parameter: expectedReturnType = voidType; errorInfo = chainDiagnosticMessages( - errorInfo, + /*details*/ undefined, Diagnostics.The_return_type_of_a_parameter_decorator_function_must_be_either_void_or_any); break; @@ -22257,17 +22311,20 @@ namespace ts { case SyntaxKind.PropertyDeclaration: expectedReturnType = voidType; errorInfo = chainDiagnosticMessages( - errorInfo, + /*details*/ undefined, Diagnostics.The_return_type_of_a_property_decorator_function_must_be_either_void_or_any); break; case SyntaxKind.MethodDeclaration: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: - const methodType = getTypeOfNode(node.parent); + const methodType = getTypeOfNode(node.parent)!; // TODO: GH#18217 const descriptorType = createTypedPropertyDescriptorType(methodType); expectedReturnType = getUnionType([descriptorType, voidType]); break; + + default: + return Debug.fail(); } checkTypeAssignableTo( @@ -22286,7 +22343,7 @@ namespace ts { markEntityNameOrEntityExpressionAsReference(node && getEntityNameFromTypeNode(node)); } - function markEntityNameOrEntityExpressionAsReference(typeName: EntityNameOrEntityNameExpression) { + function markEntityNameOrEntityExpressionAsReference(typeName: EntityNameOrEntityNameExpression | undefined) { if (!typeName) return; const rootName = getFirstIdentifier(typeName); @@ -22307,19 +22364,19 @@ namespace ts { * union and intersection type * @param node */ - function markDecoratorMedataDataTypeNodeAsReferenced(node: TypeNode): void { + function markDecoratorMedataDataTypeNodeAsReferenced(node: TypeNode | undefined): void { const entityName = getEntityNameForDecoratorMetadata(node); if (entityName && isEntityName(entityName)) { markEntityNameOrEntityExpressionAsReference(entityName); } } - function getEntityNameForDecoratorMetadata(node: TypeNode): EntityName { + function getEntityNameForDecoratorMetadata(node: TypeNode | undefined): EntityName | undefined { if (node) { switch (node.kind) { case SyntaxKind.IntersectionType: case SyntaxKind.UnionType: - let commonEntityName: EntityName; + let commonEntityName: EntityName | undefined; for (let typeNode of (node).types) { while (typeNode.kind === SyntaxKind.ParenthesizedType) { typeNode = (typeNode as ParenthesizedTypeNode).type; // Skip parens if need be @@ -22364,7 +22421,7 @@ namespace ts { } } - function getParameterTypeNodeForDecoratorCheck(node: ParameterDeclaration): TypeNode { + function getParameterTypeNodeForDecoratorCheck(node: ParameterDeclaration): TypeNode | undefined { const typeNode = getEffectiveTypeAnnotationNode(node); return isRestParameter(node) ? getRestParameterElementType(typeNode) : typeNode; } @@ -22436,8 +22493,8 @@ namespace ts { if (produceDiagnostics) { checkFunctionOrMethodDeclaration(node); checkGrammarForGenerator(node); - checkCollisionWithRequireExportsInGeneratedCode(node, node.name); - checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name); + checkCollisionWithRequireExportsInGeneratedCode(node, node.name!); + checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name!); } } @@ -22680,7 +22737,7 @@ namespace ts { } const symbol = getSymbolOfNode(member); if (!symbol.isReferenced && hasModifier(member, ModifierFlags.Private)) { - addDiagnostic(UnusedKind.Local, createDiagnosticForNode(member.name, Diagnostics._0_is_declared_but_its_value_is_never_read, symbolToString(symbol))); + addDiagnostic(UnusedKind.Local, createDiagnosticForNode(member.name!, Diagnostics._0_is_declared_but_its_value_is_never_read, symbolToString(symbol))); } break; case SyntaxKind.Constructor: @@ -22708,9 +22765,9 @@ namespace ts { // Only report errors on the last declaration for the type parameter container; // this ensures that all uses have been accounted for. const typeParameters = getEffectiveTypeParameterDeclarations(node); - if (!(node.flags & NodeFlags.Ambient) && last(getSymbolOfNode(node)!.declarations) === node) { + if (!(node.flags & NodeFlags.Ambient) && last(getSymbolOfNode(node).declarations) === node) { for (const typeParameter of typeParameters) { - if (!(getMergedSymbol(typeParameter.symbol).isReferenced & SymbolFlags.TypeParameter) && !isIdentifierThatStartsWithUnderScore(typeParameter.name)) { + if (!(getMergedSymbol(typeParameter.symbol).isReferenced! & SymbolFlags.TypeParameter) && !isIdentifierThatStartsWithUnderScore(typeParameter.name)) { addDiagnostic(UnusedKind.Parameter, createDiagnosticForNode(typeParameter.name, Diagnostics._0_is_declared_but_its_value_is_never_read, symbolName(typeParameter.symbol))); } } @@ -22739,10 +22796,10 @@ namespace ts { const unusedImports = createMap<[ImportClause, ImportedDeclaration[]]>(); const unusedDestructures = createMap<[ObjectBindingPattern, BindingElement[]]>(); const unusedVariables = createMap<[VariableDeclarationList, VariableDeclaration[]]>(); - nodeWithLocals.locals.forEach(local => { + nodeWithLocals.locals!.forEach(local => { // If it's purely a type parameter, ignore, will be checked in `checkUnusedTypeParameters`. // If it's a type parameter merged with a parameter, check if the parameter-side is used. - if (local.flags & SymbolFlags.TypeParameter ? !(local.flags & SymbolFlags.Variable && !(local.isReferenced & SymbolFlags.Variable)) : local.isReferenced || local.exportSymbol) { + if (local.flags & SymbolFlags.TypeParameter ? !(local.flags & SymbolFlags.Variable && !(local.isReferenced! & SymbolFlags.Variable)) : local.isReferenced || local.exportSymbol) { return; } @@ -22785,11 +22842,11 @@ namespace ts { : 0); if (nDeclarations === unuseds.length) { addDiagnostic(UnusedKind.Local, unuseds.length === 1 - ? createDiagnosticForNode(importDecl, Diagnostics._0_is_declared_but_its_value_is_never_read, idText(first(unuseds).name)) + ? createDiagnosticForNode(importDecl, Diagnostics._0_is_declared_but_its_value_is_never_read, idText(first(unuseds).name!)) : createDiagnosticForNode(importDecl, Diagnostics.All_imports_in_import_declaration_are_unused)); } else { - for (const unused of unuseds) errorUnusedLocal(unused, idText(unused.name), addDiagnostic); + for (const unused of unuseds) errorUnusedLocal(unused, idText(unused.name!), addDiagnostic); } }); unusedDestructures.forEach(([bindingPattern, bindingElements]) => { @@ -22875,7 +22932,7 @@ namespace ts { }); } - function needCollisionCheckForIdentifier(node: Node, identifier: Identifier, name: string): boolean { + function needCollisionCheckForIdentifier(node: Node, identifier: Identifier | undefined, name: string): boolean { if (!(identifier && identifier.escapedText === name)) { return false; } @@ -22917,6 +22974,7 @@ namespace ts { } return true; } + return false; }); } @@ -22932,6 +22990,7 @@ namespace ts { } return true; } + return false; }); } @@ -23024,7 +23083,7 @@ namespace ts { localDeclarationSymbol !== symbol && localDeclarationSymbol.flags & SymbolFlags.BlockScopedVariable) { if (getDeclarationNodeFlagsFromSymbol(localDeclarationSymbol) & NodeFlags.BlockScoped) { - const varDeclList = getAncestor(localDeclarationSymbol.valueDeclaration, SyntaxKind.VariableDeclarationList); + const varDeclList = getAncestor(localDeclarationSymbol.valueDeclaration, SyntaxKind.VariableDeclarationList)!; const container = varDeclList.parent.kind === SyntaxKind.VariableStatement && varDeclList.parent.parent ? varDeclList.parent.parent @@ -23059,7 +23118,7 @@ namespace ts { } const func = getContainingFunction(node); - visit(node.initializer); + visit(node.initializer!); function visit(n: Node): void { if (isTypeNode(n) || isDeclarationName(n)) { @@ -23160,10 +23219,10 @@ namespace ts { const parentType = getTypeForBindingElementParent(parent); const name = node.propertyName || node.name; if (!isBindingPattern(name)) { - const property = getPropertyOfType(parentType, getTextOfPropertyName(name)); + const property = getPropertyOfType(parentType!, getTextOfPropertyName(name))!; // TODO: GH#18217 markPropertyAsReferenced(property, /*nodeForCheckWriteOnly*/ undefined, /*isThisAccess*/ false); // A destructuring is never a write-only reference. if (parent.initializer && property) { - checkPropertyAccessibility(parent, parent.initializer, parentType, property); + checkPropertyAccessibility(parent, parent.initializer, parentType!, property); } } } @@ -23464,7 +23523,7 @@ namespace ts { return checkIteratedTypeOrElementType(expressionType, rhsExpression, /*allowStringInput*/ true, awaitModifier !== undefined); } - function checkIteratedTypeOrElementType(inputType: Type, errorNode: Node, allowStringInput: boolean, allowAsyncIterables: boolean): Type { + function checkIteratedTypeOrElementType(inputType: Type, errorNode: Node | undefined, allowStringInput: boolean, allowAsyncIterables: boolean): Type { if (isTypeAny(inputType)) { return inputType; } @@ -23477,9 +23536,9 @@ namespace ts { * we want to get the iterated type of an iterable for ES2015 or later, or the iterated type * of a iterable (if defined globally) or element type of an array like for ES2015 or earlier. */ - function getIteratedTypeOrElementType(inputType: Type, errorNode: Node, allowStringInput: boolean, allowAsyncIterables: boolean, checkAssignability: boolean): Type | undefined { + function getIteratedTypeOrElementType(inputType: Type, errorNode: Node | undefined, allowStringInput: boolean, allowAsyncIterables: boolean, checkAssignability: boolean): Type | undefined { if (inputType === neverType) { - reportTypeNotIterableError(errorNode, inputType, allowAsyncIterables); + reportTypeNotIterableError(errorNode!, inputType, allowAsyncIterables); // TODO: GH#18217 return undefined; } @@ -23628,7 +23687,7 @@ namespace ts { // or the global `AsyncIterableIterator` then just grab its type argument. if (isReferenceToType(type, getGlobalAsyncIterableType(/*reportErrors*/ false)) || isReferenceToType(type, getGlobalAsyncIterableIteratorType(/*reportErrors*/ false))) { - return typeAsIterable.iteratedTypeOfAsyncIterable = (type).typeArguments[0]; + return typeAsIterable.iteratedTypeOfAsyncIterable = (type).typeArguments![0]; } } @@ -23641,17 +23700,17 @@ namespace ts { // `IterableIterator` then just grab its type argument. if (isReferenceToType(type, getGlobalIterableType(/*reportErrors*/ false)) || isReferenceToType(type, getGlobalIterableIteratorType(/*reportErrors*/ false))) { - return typeAsIterable.iteratedTypeOfIterable = (type).typeArguments[0]; + return typeAsIterable.iteratedTypeOfIterable = (type).typeArguments![0]; } } const asyncMethodType = allowAsyncIterables && getTypeOfPropertyOfType(type, getPropertyNameForKnownSymbolName("asyncIterator")); - const methodType = asyncMethodType || (allowSyncIterables && getTypeOfPropertyOfType(type, getPropertyNameForKnownSymbolName("iterator"))); + const methodType = asyncMethodType || (allowSyncIterables ? getTypeOfPropertyOfType(type, getPropertyNameForKnownSymbolName("iterator")) : undefined); if (isTypeAny(methodType)) { return undefined; } - const signatures = methodType && getSignaturesOfType(methodType, SignatureKind.Call); + const signatures = methodType ? getSignaturesOfType(methodType, SignatureKind.Call) : undefined; if (!some(signatures)) { if (errorNode) { // only report on the first error @@ -23722,8 +23781,8 @@ namespace ts { const getIteratorType = isAsyncIterator ? getGlobalAsyncIteratorType : getGlobalIteratorType; if (isReferenceToType(type, getIteratorType(/*reportErrors*/ false))) { return isAsyncIterator - ? typeAsIterator.iteratedTypeOfAsyncIterator = (type).typeArguments[0] - : typeAsIterator.iteratedTypeOfIterator = (type).typeArguments[0]; + ? typeAsIterator.iteratedTypeOfAsyncIterator = (type).typeArguments![0] + : typeAsIterator.iteratedTypeOfIterator = (type).typeArguments![0]; } // Both async and non-async iterators must have a `next` method. @@ -23742,7 +23801,7 @@ namespace ts { return undefined; } - let nextResult = getUnionType(map(nextMethodSignatures, getReturnTypeOfSignature), UnionReduction.Subtype); + let nextResult: Type | undefined = getUnionType(map(nextMethodSignatures, getReturnTypeOfSignature), UnionReduction.Subtype); if (isTypeAny(nextResult)) { return undefined; } @@ -23776,7 +23835,7 @@ namespace ts { * `AsyncIterable`, or `AsyncIterableIterator`. This function can be used to extract * the iterated type from this return type for contextual typing and verifying signatures. */ - function getIteratedTypeOfGenerator(returnType: Type, isAsyncGenerator: boolean): Type { + function getIteratedTypeOfGenerator(returnType: Type, isAsyncGenerator: boolean): Type | undefined { if (isTypeAny(returnType)) { return undefined; } @@ -23794,14 +23853,14 @@ namespace ts { function isGetAccessorWithAnnotatedSetAccessor(node: SignatureDeclaration) { return node.kind === SyntaxKind.GetAccessor - && getEffectiveSetAccessorTypeAnnotationNode(getDeclarationOfKind(node.symbol, SyntaxKind.SetAccessor)) !== undefined; + && getEffectiveSetAccessorTypeAnnotationNode(getDeclarationOfKind(node.symbol, SyntaxKind.SetAccessor)!) !== undefined; } function isUnwrappedReturnTypeVoidOrAny(func: SignatureDeclaration, returnType: Type): boolean { const unwrappedReturnType = (getFunctionFlags(func) & FunctionFlags.AsyncGenerator) === FunctionFlags.Async ? getPromisedTypeOfPromise(returnType) // Async function : returnType; // AsyncGenerator function, Generator function, or normal function - return unwrappedReturnType && maybeTypeOfKind(unwrappedReturnType, TypeFlags.Void | TypeFlags.Any); + return !!unwrappedReturnType && maybeTypeOfKind(unwrappedReturnType, TypeFlags.Void | TypeFlags.Any); } function checkReturnStatement(node: ReturnStatement) { @@ -23938,6 +23997,7 @@ namespace ts { grammarErrorOnNode(node.label, Diagnostics.Duplicate_label_0, getTextOfNode(node.label)); return true; } + return false; }); } @@ -23976,7 +24036,7 @@ namespace ts { else { const blockLocals = catchClause.block.locals; if (blockLocals) { - forEachKey(catchClause.locals, caughtName => { + forEachKey(catchClause.locals!, caughtName => { const blockLocal = blockLocals.get(caughtName); if (blockLocal && (blockLocal.flags & SymbolFlags.BlockScopedVariable) !== 0) { grammarErrorOnNode(blockLocal.valueDeclaration, Diagnostics.Cannot_redeclare_identifier_0_in_catch_clause, caughtName); @@ -24008,8 +24068,8 @@ namespace ts { checkIndexConstraintForProperty(prop, propType, type, declaredNumberIndexer, numberIndexType, IndexKind.Number); }); - if (getObjectFlags(type) & ObjectFlags.Class && isClassLike(type.symbol.valueDeclaration)) { - const classDeclaration = type.symbol.valueDeclaration; + const classDeclaration = type.symbol.valueDeclaration; + if (getObjectFlags(type) & ObjectFlags.Class && isClassLike(classDeclaration)) { for (const member of classDeclaration.members) { // Only process instance properties with computed names here. // Static properties cannot be in conflict with indexers, @@ -24024,7 +24084,7 @@ namespace ts { } } - let errorNode: Node; + let errorNode: Node | undefined; if (stringIndexType && numberIndexType) { errorNode = declaredNumberIndexer || declaredStringIndexer; // condition 'errorNode === undefined' may appear if types does not declare nor string neither number indexer @@ -24034,17 +24094,17 @@ namespace ts { } } - if (errorNode && !isTypeAssignableTo(numberIndexType, stringIndexType)) { + if (errorNode && !isTypeAssignableTo(numberIndexType!, stringIndexType!)) { // TODO: GH#18217 error(errorNode, Diagnostics.Numeric_index_type_0_is_not_assignable_to_string_index_type_1, - typeToString(numberIndexType), typeToString(stringIndexType)); + typeToString(numberIndexType!), typeToString(stringIndexType!)); } function checkIndexConstraintForProperty( prop: Symbol, propertyType: Type, containingType: Type, - indexDeclaration: Declaration, - indexType: Type, + indexDeclaration: Declaration | undefined, + indexType: Type | undefined, indexKind: IndexKind): void { // ESSymbol properties apply to neither string nor numeric indexers. @@ -24061,7 +24121,7 @@ namespace ts { // perform property check if property or indexer is declared in 'type' // this allows us to rule out cases when both property and indexer are inherited from the base class - let errorNode: Node; + let errorNode: Node | undefined; if (propDeclaration && (propDeclaration.kind === SyntaxKind.BinaryExpression || getNameOfDeclaration(propDeclaration).kind === SyntaxKind.ComputedPropertyName || @@ -24146,7 +24206,7 @@ namespace ts { } const type = getDeclaredTypeOfSymbol(symbol); - if (!areTypeParametersIdentical(declarations, type.localTypeParameters)) { + if (!areTypeParametersIdentical(declarations, type.localTypeParameters!)) { // Report an error on every conflicting declaration. const name = symbolToString(symbol); for (const declaration of declarations) { @@ -24261,7 +24321,7 @@ namespace ts { if (some(baseTypeNode.typeArguments)) { forEach(baseTypeNode.typeArguments, checkSourceElement); for (const constructor of getConstructorsForTypeArguments(staticBaseType, baseTypeNode.typeArguments, baseTypeNode)) { - if (!checkTypeArgumentConstraints(baseTypeNode, constructor.typeParameters)) { + if (!checkTypeArgumentConstraints(baseTypeNode, constructor.typeParameters!)) { break; } } @@ -24360,7 +24420,7 @@ namespace ts { if (signatures.length) { const declaration = signatures[0].declaration; if (declaration && hasModifier(declaration, ModifierFlags.Private)) { - const typeClassDeclaration = getClassLikeDeclarationOfSymbol(type.symbol); + const typeClassDeclaration = getClassLikeDeclarationOfSymbol(type.symbol)!; if (!isNodeWithinClass(node, typeClassDeclaration)) { error(node, Diagnostics.Cannot_extend_a_class_0_Class_constructor_is_marked_as_private, getFullyQualifiedName(type.symbol)); } @@ -24371,7 +24431,7 @@ namespace ts { function getTargetSymbol(s: Symbol) { // if symbol is instantiated its flags are not copied from the 'target' // so we'll need to get back original 'target' symbol to work with correct set of flags - return getCheckFlags(s) & CheckFlags.Instantiated ? (s).target : s; + return getCheckFlags(s) & CheckFlags.Instantiated ? (s).target! : s; } function getClassOrInterfaceDeclarationsOfSymbol(symbol: Symbol) { @@ -24404,7 +24464,7 @@ namespace ts { continue; } - const derived = getTargetSymbol(getPropertyOfObjectType(type, base.escapedName)); + const derived = getTargetSymbol(getPropertyOfObjectType(type, base.escapedName)!); // TODO: GH#18217 const baseDeclarationFlags = getDeclarationModifierFlagsFromSymbol(base); Debug.assert(!!derived, "derived should point to something, even if it is the base class' declaration."); @@ -24416,7 +24476,7 @@ namespace ts { if (derived === base) { // derived class inherits base without override/redeclaration - const derivedClassDecl = getClassLikeDeclarationOfSymbol(type.symbol); + const derivedClassDecl = getClassLikeDeclarationOfSymbol(type.symbol)!; // It is an error to inherit an abstract member without implementing it or being declared abstract. // If there is no declaration for the derived class (as in the case of class expressions), @@ -24594,7 +24654,7 @@ namespace ts { const nodeLinks = getNodeLinks(node); if (!(nodeLinks.flags & NodeCheckFlags.EnumValuesComputed)) { nodeLinks.flags |= NodeCheckFlags.EnumValuesComputed; - let autoValue = 0; + let autoValue: number | undefined = 0; for (const member of node.members) { const value = computeMemberValue(member, autoValue); getNodeLinks(member).enumMemberValue = value; @@ -24603,7 +24663,7 @@ namespace ts { } } - function computeMemberValue(member: EnumMember, autoValue: number) { + function computeMemberValue(member: EnumMember, autoValue: number | undefined) { if (isComputedNonLiteralName(member.name)) { error(member.name, Diagnostics.Computed_property_names_are_not_allowed_in_enums); } @@ -24632,10 +24692,10 @@ namespace ts { return undefined; } - function computeConstantValue(member: EnumMember): string | number { + function computeConstantValue(member: EnumMember): string | number | undefined { const enumKind = getEnumKind(getSymbolOfNode(member.parent)); const isConstEnum = isConst(member.parent); - const initializer = member.initializer; + const initializer = member.initializer!; const value = enumKind === EnumKind.Literal && !isLiteralEnumMember(member) ? undefined : evaluate(initializer); if (value !== undefined) { if (isConstEnum && typeof value === "number" && !isFinite(value)) { @@ -24660,7 +24720,7 @@ namespace ts { } return value; - function evaluate(expr: Expression): string | number { + function evaluate(expr: Expression): string | number | undefined { switch (expr.kind) { case SyntaxKind.PrefixUnaryExpression: const value = evaluate((expr).operand); @@ -24728,7 +24788,7 @@ namespace ts { } function evaluateEnumMember(expr: Expression, enumSymbol: Symbol, name: __String) { - const memberSymbol = enumSymbol.exports.get(name); + const memberSymbol = enumSymbol.exports!.get(name); if (memberSymbol) { const declaration = memberSymbol.valueDeclaration; if (declaration !== member) { @@ -24813,7 +24873,7 @@ namespace ts { } } - function getFirstNonAmbientClassOrFunctionDeclaration(symbol: Symbol): Declaration { + function getFirstNonAmbientClassOrFunctionDeclaration(symbol: Symbol): Declaration | undefined { const declarations = symbol.declarations; for (const declaration of declarations) { if ((declaration.kind === SyntaxKind.ClassDeclaration || @@ -24875,7 +24935,7 @@ namespace ts { if (symbol.flags & SymbolFlags.ValueModule && symbol.declarations.length > 1 && !inAmbientContext - && isInstantiatedModule(node, compilerOptions.preserveConstEnums || compilerOptions.isolatedModules)) { + && isInstantiatedModule(node, !!compilerOptions.preserveConstEnums || !!compilerOptions.isolatedModules)) { const firstNonAmbientClassOrFunc = getFirstNonAmbientClassOrFunctionDeclaration(symbol); if (firstNonAmbientClassOrFunc) { if (getSourceFileOfNode(node) !== getSourceFileOfNode(firstNonAmbientClassOrFunc)) { @@ -24983,7 +25043,7 @@ namespace ts { let reportError = !(symbol.flags & SymbolFlags.Transient); if (!reportError) { // symbol should not originate in augmentation - reportError = isExternalModuleAugmentation(symbol.parent.declarations[0]); + reportError = isExternalModuleAugmentation(symbol.parent!.declarations[0]); } } break; @@ -25009,7 +25069,7 @@ namespace ts { function checkExternalImportOrExportDeclaration(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration): boolean { const moduleName = getExternalModuleName(node); - if (nodeIsMissing(moduleName)) { + if (!moduleName || nodeIsMissing(moduleName)) { // Should be a parse error. return false; } @@ -25071,8 +25131,8 @@ namespace ts { } function checkImportBinding(node: ImportEqualsDeclaration | ImportClause | NamespaceImport | ImportSpecifier) { - checkCollisionWithRequireExportsInGeneratedCode(node, node.name); - checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name); + checkCollisionWithRequireExportsInGeneratedCode(node, node.name!); + checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name!); checkAliasSymbol(node); } @@ -25123,7 +25183,7 @@ namespace ts { if (target.flags & SymbolFlags.Value) { // Target is a value symbol, check that it is not hidden by a local declaration with the same name const moduleName = getFirstIdentifier(node.moduleReference); - if (!(resolveEntityName(moduleName, SymbolFlags.Value | SymbolFlags.Namespace).flags & SymbolFlags.Namespace)) { + if (!(resolveEntityName(moduleName, SymbolFlags.Value | SymbolFlags.Namespace)!.flags & SymbolFlags.Namespace)) { error(moduleName, Diagnostics.Module_0_is_hidden_by_a_local_declaration_with_the_same_name, declarationNameToString(moduleName)); } } @@ -25166,7 +25226,7 @@ namespace ts { } else { // export * from "foo" - const moduleSymbol = resolveExternalModuleName(node, node.moduleSpecifier); + const moduleSymbol = resolveExternalModuleName(node, node.moduleSpecifier!); if (moduleSymbol && hasExportAssignmentSymbol(moduleSymbol)) { error(node.moduleSpecifier, Diagnostics.Module_0_uses_export_and_cannot_be_used_with_export_Asterisk, symbolToString(moduleSymbol)); } @@ -25256,14 +25316,14 @@ namespace ts { } function hasExportedMembers(moduleSymbol: Symbol) { - return forEachEntry(moduleSymbol.exports, (_, id) => id !== "export="); + return forEachEntry(moduleSymbol.exports!, (_, id) => id !== "export="); } function checkExternalModuleExports(node: SourceFile | ModuleDeclaration) { const moduleSymbol = getSymbolOfNode(node); const links = getSymbolLinks(moduleSymbol); if (!links.exportsChecked) { - const exportEqualsSymbol = moduleSymbol.exports.get("export=" as __String); + const exportEqualsSymbol = moduleSymbol.exports!.get("export=" as __String); if (exportEqualsSymbol && hasExportedMembers(moduleSymbol)) { const declaration = getDeclarationOfAliasSymbol(exportEqualsSymbol) || exportEqualsSymbol.valueDeclaration; if (!isTopLevelInExternalModuleAugmentation(declaration) && !isInJavaScriptFile(declaration)) { @@ -25311,15 +25371,13 @@ namespace ts { !!(declaration as FunctionDeclaration).body; } - function checkSourceElement(node: Node): void { + function checkSourceElement(node: Node | undefined): void { if (!node) { return; } - if (isInJavaScriptFile(node) && (node as JSDocContainer).jsDoc) { - for (const { tags } of (node as JSDocContainer).jsDoc) { - forEach(tags, checkSourceElement); - } + if (isInJavaScriptFile(node)) { + forEach((node as JSDocContainer).jsDoc, ({ tags }) => forEach(tags, checkSourceElement)); } const kind = node.kind; @@ -25499,7 +25557,7 @@ namespace ts { error(node, Diagnostics.JSDoc_may_only_appear_in_the_last_parameter_of_a_signature); } - const paramTag = parent.parent; + const paramTag = node.parent.parent; if (!isJSDocParameterTag(paramTag)) { error(node, Diagnostics.JSDoc_may_only_appear_in_the_last_parameter_of_a_signature); return; @@ -25520,8 +25578,8 @@ namespace ts { function getTypeFromJSDocVariadicType(node: JSDocVariadicType): Type { const type = getTypeFromTypeNode(node.type); const { parent } = node; - const paramTag = parent.parent; - if (isJSDocTypeExpression(parent) && isJSDocParameterTag(paramTag)) { + const paramTag = node.parent.parent; + if (isJSDocTypeExpression(node.parent) && isJSDocParameterTag(paramTag)) { // Else we will add a diagnostic, see `checkJSDocVariadicType`. const host = getHostSignatureFromJSDoc(paramTag); if (host) { @@ -25562,7 +25620,7 @@ namespace ts { } function checkDeferredNodes() { - for (const node of deferredNodes) { + for (const node of deferredNodes!) { switch (node.kind) { case SyntaxKind.FunctionExpression: case SyntaxKind.ArrowFunction: @@ -25591,9 +25649,9 @@ namespace ts { function unusedIsError(kind: UnusedKind): boolean { switch (kind) { case UnusedKind.Local: - return compilerOptions.noUnusedLocals; + return !!compilerOptions.noUnusedLocals; case UnusedKind.Parameter: - return compilerOptions.noUnusedParameters; + return !!compilerOptions.noUnusedParameters; default: return Debug.assertNever(kind); } @@ -25738,13 +25796,13 @@ namespace ts { switch (location.kind) { case SyntaxKind.ModuleDeclaration: - copySymbols(getSymbolOfNode(location).exports, meaning & SymbolFlags.ModuleMember); + copySymbols(getSymbolOfNode(location as ModuleDeclaration).exports!, meaning & SymbolFlags.ModuleMember); break; case SyntaxKind.EnumDeclaration: - copySymbols(getSymbolOfNode(location).exports, meaning & SymbolFlags.EnumMember); + copySymbols(getSymbolOfNode(location as EnumDeclaration).exports!, meaning & SymbolFlags.EnumMember); break; case SyntaxKind.ClassExpression: - const className = (location).name; + const className = (location as ClassExpression).name; if (className) { copySymbol(location.symbol, meaning); } @@ -25758,11 +25816,11 @@ namespace ts { // (type parameters of classDeclaration/classExpression and interface are in member property of the symbol. // Note: that the memberFlags come from previous iteration. if (!isStatic) { - copySymbols(getMembersOfSymbol(getSymbolOfNode(location)), meaning & SymbolFlags.Type); + copySymbols(getMembersOfSymbol(getSymbolOfNode(location as ClassDeclaration | InterfaceDeclaration)), meaning & SymbolFlags.Type); } break; case SyntaxKind.FunctionExpression: - const funcName = (location).name; + const funcName = (location as FunctionExpression).name; if (funcName) { copySymbol(location.symbol, meaning); } @@ -25814,7 +25872,7 @@ namespace ts { (name.parent).name === name; } - function isTypeDeclaration(node: Node): boolean { + function isTypeDeclaration(node: Node): node is TypeParameterDeclaration | ClassDeclaration | InterfaceDeclaration | TypeAliasDeclaration | EnumDeclaration { switch (node.kind) { case SyntaxKind.TypeParameter: case SyntaxKind.ClassDeclaration: @@ -25822,33 +25880,33 @@ namespace ts { case SyntaxKind.TypeAliasDeclaration: case SyntaxKind.EnumDeclaration: return true; + default: + return false; } } // True if the given identifier is part of a type reference - function isTypeReferenceIdentifier(entityName: EntityName): boolean { - let node: Node = entityName; - while (node.parent && node.parent.kind === SyntaxKind.QualifiedName) { - node = node.parent; + function isTypeReferenceIdentifier(node: EntityName): boolean { + while (node.parent.kind === SyntaxKind.QualifiedName) { + node = node.parent as QualifiedName; } - return node.parent && node.parent.kind === SyntaxKind.TypeReference ; + return node.parent.kind === SyntaxKind.TypeReference; } - function isHeritageClauseElementIdentifier(entityName: Node): boolean { - let node = entityName; - while (node.parent && node.parent.kind === SyntaxKind.PropertyAccessExpression) { + function isHeritageClauseElementIdentifier(node: Node): boolean { + while (node.parent.kind === SyntaxKind.PropertyAccessExpression) { node = node.parent; } - return node.parent && node.parent.kind === SyntaxKind.ExpressionWithTypeArguments; + return node.parent.kind === SyntaxKind.ExpressionWithTypeArguments; } - function forEachEnclosingClass(node: Node, callback: (node: Node) => T): T { - let result: T; + function forEachEnclosingClass(node: Node, callback: (node: Node) => T | undefined): T | undefined { + let result: T | undefined; while (true) { - node = getContainingClass(node); + node = getContainingClass(node)!; if (!node) break; if (result = callback(node)) break; } @@ -25873,17 +25931,17 @@ namespace ts { return !!forEachEnclosingClass(node, n => n === classDeclaration); } - function getLeftSideOfImportEqualsOrExportAssignment(nodeOnRightSide: EntityName): ImportEqualsDeclaration | ExportAssignment { + function getLeftSideOfImportEqualsOrExportAssignment(nodeOnRightSide: EntityName): ImportEqualsDeclaration | ExportAssignment | undefined { while (nodeOnRightSide.parent.kind === SyntaxKind.QualifiedName) { nodeOnRightSide = nodeOnRightSide.parent; } if (nodeOnRightSide.parent.kind === SyntaxKind.ImportEqualsDeclaration) { - return (nodeOnRightSide.parent).moduleReference === nodeOnRightSide && nodeOnRightSide.parent; + return (nodeOnRightSide.parent).moduleReference === nodeOnRightSide ? nodeOnRightSide.parent : undefined; } if (nodeOnRightSide.parent.kind === SyntaxKind.ExportAssignment) { - return (nodeOnRightSide.parent).expression === nodeOnRightSide && nodeOnRightSide.parent; + return (nodeOnRightSide.parent).expression === nodeOnRightSide ? nodeOnRightSide.parent : undefined; } return undefined; @@ -25983,7 +26041,7 @@ namespace ts { } } - if (entityName.parent!.kind === SyntaxKind.JSDocParameterTag) { + if (entityName.parent.kind === SyntaxKind.JSDocParameterTag) { return getParameterSymbolFromJSDoc(entityName.parent as JSDocParameterTag); } @@ -26042,6 +26100,8 @@ namespace ts { if (node.kind === SyntaxKind.SourceFile) { return isExternalModule(node) ? getMergedSymbol(node.symbol) : undefined; } + const { parent } = node; + const grandParent = parent.parent; if (node.flags & NodeFlags.InWithStatement) { // We cannot answer semantic questions within a with block, do not proceed any further @@ -26050,20 +26110,20 @@ namespace ts { if (isDeclarationNameOrImportPropertyName(node)) { // This is a declaration, call getSymbolOfNode - return getSymbolOfNode(node.parent); + return getSymbolOfNode(parent); } else if (isLiteralComputedPropertyDeclarationName(node)) { - return getSymbolOfNode(node.parent.parent); + return getSymbolOfNode(parent.parent); } if (node.kind === SyntaxKind.Identifier) { if (isInRightSideOfImportOrExportAssignment(node)) { return getSymbolOfEntityNameOrPropertyAccessExpression(node); } - else if (node.parent.kind === SyntaxKind.BindingElement && - node.parent.parent.kind === SyntaxKind.ObjectBindingPattern && - node === (node.parent).propertyName) { - const typeOfPattern = getTypeOfNode(node.parent.parent); + else if (parent.kind === SyntaxKind.BindingElement && + grandParent.kind === SyntaxKind.ObjectBindingPattern && + node === (parent).propertyName) { + const typeOfPattern = getTypeOfNode(grandParent); const propertyDeclaration = typeOfPattern && getPropertyOfType(typeOfPattern, (node).escapedText); if (propertyDeclaration) { @@ -26122,10 +26182,10 @@ namespace ts { case SyntaxKind.NumericLiteral: // index access - const objectType = isElementAccessExpression(node.parent) - ? node.parent.argumentExpression === node ? getTypeOfExpression(node.parent.expression) : undefined - : isLiteralTypeNode(node.parent) && isIndexedAccessTypeNode(node.parent.parent) - ? getTypeFromTypeNode(node.parent.parent.objectType) + const objectType = isElementAccessExpression(parent) + ? parent.argumentExpression === node ? getTypeOfExpression(parent.expression) : undefined + : isLiteralTypeNode(parent) && isIndexedAccessTypeNode(grandParent) + ? getTypeFromTypeNode(grandParent.objectType) : undefined; return objectType && getPropertyOfType(objectType, escapeLeadingUnderscores((node as StringLiteral | NumericLiteral).text)); @@ -26141,7 +26201,7 @@ namespace ts { } } - function getShorthandAssignmentValueSymbol(location: Node): Symbol { + function getShorthandAssignmentValueSymbol(location: Node): Symbol | undefined { if (location && location.kind === SyntaxKind.ShorthandPropertyAssignment) { return resolveEntityName((location).name, SymbolFlags.Value | SymbolFlags.Alias); } @@ -26149,13 +26209,13 @@ namespace ts { } /** Returns the target of an export specifier without following aliases */ - function getExportSpecifierLocalTargetSymbol(node: ExportSpecifier): Symbol { + function getExportSpecifierLocalTargetSymbol(node: ExportSpecifier): Symbol | undefined { return node.parent.parent.moduleSpecifier ? getExternalModuleMember(node.parent.parent, node) : resolveEntityName(node.propertyName || node.name, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias); } - function getTypeOfNode(node: Node): Type { + function getTypeOfNode(node: Node): Type | undefined { if (node.flags & NodeFlags.InWithStatement) { // We cannot answer semantic questions within a with block, do not proceed any further return unknownType; @@ -26165,7 +26225,7 @@ namespace ts { let typeFromTypeNode = getTypeFromTypeNode(node); if (typeFromTypeNode && isExpressionWithTypeArgumentsInClassImplementsClause(node)) { - const containingClass = getContainingClass(node); + const containingClass = getContainingClass(node)!; const classType = getTypeOfNode(containingClass) as InterfaceType; typeFromTypeNode = getTypeWithThisArgument(typeFromTypeNode, classType.thisType); } @@ -26180,7 +26240,7 @@ namespace ts { if (isExpressionWithTypeArgumentsInClassExtendsClause(node)) { // A SyntaxKind.ExpressionWithTypeArguments is considered a type node, except when it occurs in the // extends clause of a class. We handle that case here. - const classNode = getContainingClass(node); + const classNode = getContainingClass(node)!; const classType = getDeclaredTypeOfSymbol(getSymbolOfNode(classNode)) as InterfaceType; const baseType = getBaseTypes(classType)[0]; return baseType && getTypeWithThisArgument(baseType, classType.thisType); @@ -26248,7 +26308,7 @@ namespace ts { // for ({ skills: { primary, secondary } } = multiRobot, i = 0; i < 1; i++) { if (expr.parent.kind === SyntaxKind.PropertyAssignment) { const typeOfParentObjectLiteral = getTypeOfArrayLiteralOrObjectLiteralDestructuringAssignment(expr.parent.parent); - return checkObjectLiteralDestructuringPropertyAssignment(typeOfParentObjectLiteral || unknownType, expr.parent); + return checkObjectLiteralDestructuringPropertyAssignment(typeOfParentObjectLiteral || unknownType, expr.parent)!; // TODO: GH#18217 } // Array literal assignment - array destructuring pattern Debug.assert(expr.parent.kind === SyntaxKind.ArrayLiteralExpression); @@ -26256,7 +26316,7 @@ namespace ts { const typeOfArrayLiteral = getTypeOfArrayLiteralOrObjectLiteralDestructuringAssignment(expr.parent); const elementType = checkIteratedTypeOrElementType(typeOfArrayLiteral || unknownType, expr.parent, /*allowStringInput*/ false, /*allowAsyncIterables*/ false) || unknownType; return checkArrayLiteralDestructuringElementAssignment(expr.parent, typeOfArrayLiteral, - (expr.parent).elements.indexOf(expr), elementType || unknownType); + (expr.parent).elements.indexOf(expr), elementType || unknownType)!; // TODO: GH#18217 } // Gets the property symbol corresponding to the property in destructuring assignment @@ -26283,7 +26343,7 @@ namespace ts { * whether the element is declared as "static". */ function getParentTypeOfClassElement(node: ClassElement) { - const classSymbol = getSymbolOfNode(node.parent); + const classSymbol = getSymbolOfNode(node.parent)!; return hasModifier(node, ModifierFlags.Static) ? getTypeOfSymbol(classSymbol) : getDeclaredTypeOfSymbol(classSymbol); @@ -26314,11 +26374,11 @@ namespace ts { } function getImmediateRootSymbols(symbol: Symbol): ReadonlyArray | undefined { if (getCheckFlags(symbol) & CheckFlags.Synthetic) { - return mapDefined(getSymbolLinks(symbol).containingType.types, type => getPropertyOfType(type, symbol.escapedName)); + return mapDefined(getSymbolLinks(symbol).containingType!.types, type => getPropertyOfType(type, symbol.escapedName)); } else if (symbol.flags & SymbolFlags.Transient) { const { leftSpread, rightSpread, syntheticOrigin } = symbol as TransientSymbol; - return leftSpread ? [leftSpread, rightSpread] + return leftSpread ? [leftSpread, rightSpread!] : syntheticOrigin ? [syntheticOrigin] : singleElementArray(tryGetAliasTarget(symbol)); } @@ -26326,7 +26386,7 @@ namespace ts { } function tryGetAliasTarget(symbol: Symbol): Symbol | undefined { let target: Symbol | undefined; - let next = symbol; + let next: Symbol | undefined = symbol; while (next = getSymbolLinks(next).target) { target = next; } @@ -26335,9 +26395,9 @@ namespace ts { // Emitter support - function isArgumentsLocalBinding(node: Identifier): boolean { - if (!isGeneratedIdentifier(node)) { - node = getParseTreeNode(node, isIdentifier); + function isArgumentsLocalBinding(nodeIn: Identifier): boolean { + if (!isGeneratedIdentifier(nodeIn)) { + const node = getParseTreeNode(nodeIn, isIdentifier); if (node) { const isPropertyName = node.parent.kind === SyntaxKind.PropertyAccessExpression && (node.parent).name === node; return !isPropertyName && getReferencedValueSymbol(node) === argumentsSymbol; @@ -26368,7 +26428,7 @@ namespace ts { : forEachEntry(getExportsOfModule(moduleSymbol), isValue); } - return symbolLinks.exportsSomeValue; + return symbolLinks.exportsSomeValue!; function isValue(s: Symbol): boolean { s = resolveSymbol(s); @@ -26377,14 +26437,13 @@ namespace ts { } function isNameOfModuleOrEnumDeclaration(node: Identifier) { - const parent = node.parent; - return parent && isModuleOrEnumDeclaration(parent) && node === parent.name; + return isModuleOrEnumDeclaration(node.parent) && node === node.parent.name; } // When resolved as an expression identifier, if the given node references an exported entity, return the declaration // node of the exported entity's container. Otherwise, return undefined. - function getReferencedExportContainer(node: Identifier, prefixLocals?: boolean): SourceFile | ModuleDeclaration | EnumDeclaration | undefined { - node = getParseTreeNode(node, isIdentifier); + function getReferencedExportContainer(nodeIn: Identifier, prefixLocals?: boolean): SourceFile | ModuleDeclaration | EnumDeclaration | undefined { + const node = getParseTreeNode(nodeIn, isIdentifier); if (node) { // When resolving the export container for the name of a module or enum // declaration, we need to start resolution at the declaration's container. @@ -26396,7 +26455,7 @@ namespace ts { // If we reference an exported entity within the same module declaration, then whether // we prefix depends on the kind of entity. SymbolFlags.ExportHasLocal encompasses all the // kinds that we do NOT prefix. - const exportSymbol = getMergedSymbol(symbol.exportSymbol); + const exportSymbol = getMergedSymbol(symbol.exportSymbol!); if (!prefixLocals && exportSymbol.flags & SymbolFlags.ExportHasLocal && !(exportSymbol.flags & SymbolFlags.Variable)) { return undefined; } @@ -26419,8 +26478,8 @@ namespace ts { // When resolved as an expression identifier, if the given node references an import, return the declaration of // that import. Otherwise, return undefined. - function getReferencedImportDeclaration(node: Identifier): Declaration { - node = getParseTreeNode(node, isIdentifier); + function getReferencedImportDeclaration(nodeIn: Identifier): Declaration | undefined { + const node = getParseTreeNode(nodeIn, isIdentifier); if (node) { const symbol = getReferencedValueSymbol(node); // We should only get the declaration of an alias if there isn't a local value @@ -26471,7 +26530,7 @@ namespace ts { } } } - return links.isDeclarationWithCollidingName; + return links.isDeclarationWithCollidingName!; } return false; } @@ -26479,9 +26538,9 @@ namespace ts { // When resolved as an expression identifier, if the given node references a nested block scoped entity with // a name that either hides an existing name or might hide it when compiled downlevel, // return the declaration of that entity. Otherwise, return undefined. - function getReferencedDeclarationWithCollidingName(node: Identifier): Declaration { - if (!isGeneratedIdentifier(node)) { - node = getParseTreeNode(node, isIdentifier); + function getReferencedDeclarationWithCollidingName(nodeIn: Identifier): Declaration | undefined { + if (!isGeneratedIdentifier(nodeIn)) { + const node = getParseTreeNode(nodeIn, isIdentifier); if (node) { const symbol = getReferencedValueSymbol(node); if (symbol && isSymbolOfDeclarationWithCollidingName(symbol)) { @@ -26495,8 +26554,8 @@ namespace ts { // Return true if the given node is a declaration of a nested block scoped entity with a name that either hides an // existing name or might hide a name when compiled downlevel - function isDeclarationWithCollidingName(node: Declaration): boolean { - node = getParseTreeNode(node, isDeclaration); + function isDeclarationWithCollidingName(nodeIn: Declaration): boolean { + const node = getParseTreeNode(nodeIn, isDeclaration); if (node) { const symbol = getSymbolOfNode(node); if (symbol) { @@ -26517,7 +26576,7 @@ namespace ts { return isAliasResolvedToValue(getSymbolOfNode(node) || unknownSymbol); case SyntaxKind.ExportDeclaration: const exportClause = (node).exportClause; - return exportClause && forEach(exportClause.elements, isValueAliasDeclaration); + return !!exportClause && some(exportClause.elements, isValueAliasDeclaration); case SyntaxKind.ExportAssignment: return (node).expression && (node).expression.kind === SyntaxKind.Identifier @@ -26527,8 +26586,8 @@ namespace ts { return false; } - function isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean { - node = getParseTreeNode(node, isImportEqualsDeclaration); + function isTopLevelValueImportEqualsWithEntityName(nodeIn: ImportEqualsDeclaration): boolean { + const node = getParseTreeNode(nodeIn, isImportEqualsDeclaration); if (node === undefined || node.parent.kind !== SyntaxKind.SourceFile || !isInternalModuleImportEqualsDeclaration(node)) { // parent is not source file or it is not reference to internal module return false; @@ -26545,12 +26604,12 @@ namespace ts { } // const enums and modules that contain only const enums are not considered values from the emit perspective // unless 'preserveConstEnums' option is set to true - return target.flags & SymbolFlags.Value && + return !!(target.flags & SymbolFlags.Value) && (compilerOptions.preserveConstEnums || !isConstEnumOrConstEnumOnlyModule(target)); } function isConstEnumOrConstEnumOnlyModule(s: Symbol): boolean { - return isConstEnumSymbol(s) || s.constEnumOnlyModule; + return isConstEnumSymbol(s) || !!s.constEnumOnlyModule; } function isReferencedAliasDeclaration(node: Node, checkChildren?: boolean): boolean { @@ -26559,7 +26618,7 @@ namespace ts { if (symbol && getSymbolLinks(symbol).referenced) { return true; } - const target = getSymbolLinks(symbol).target; + const target = getSymbolLinks(symbol!).target; // TODO: GH#18217 if (target && getModifierFlags(node) & ModifierFlags.Export && target.flags & SymbolFlags.Value) { // An `export import ... =` of a value symbol is always considered referenced return true; @@ -26567,7 +26626,7 @@ namespace ts { } if (checkChildren) { - return forEachChild(node, node => isReferencedAliasDeclaration(node, checkChildren)); + return !!forEachChild(node, node => isReferencedAliasDeclaration(node, checkChildren)); } return false; } @@ -26594,11 +26653,11 @@ namespace ts { return false; } - function isRequiredInitializedParameter(parameter: ParameterDeclaration | JSDocParameterTag) { - return strictNullChecks && + function isRequiredInitializedParameter(parameter: ParameterDeclaration | JSDocParameterTag): boolean { + return !!strictNullChecks && !isOptionalParameter(parameter) && !isJSDocParameterTag(parameter) && - parameter.initializer && + !!parameter.initializer && !hasModifier(parameter, ModifierFlags.ParameterPropertyModifier); } @@ -26610,10 +26669,10 @@ namespace ts { } function getNodeCheckFlags(node: Node): NodeCheckFlags { - return getNodeLinks(node).flags; + return getNodeLinks(node).flags || 0; } - function getEnumMemberValue(node: EnumMember): string | number { + function getEnumMemberValue(node: EnumMember): string | number | undefined { computeEnumMemberValues(node.parent); return getNodeLinks(node).enumMemberValue; } @@ -26628,7 +26687,7 @@ namespace ts { return false; } - function getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): string | number { + function getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): string | number | undefined { if (node.kind === SyntaxKind.EnumMember) { return getEnumMemberValue(node); } @@ -26645,12 +26704,12 @@ namespace ts { } function isFunctionType(type: Type): boolean { - return type.flags & TypeFlags.Object && getSignaturesOfType(type, SignatureKind.Call).length > 0; + return !!(type.flags & TypeFlags.Object) && getSignaturesOfType(type, SignatureKind.Call).length > 0; } - function getTypeReferenceSerializationKind(typeName: EntityName, location?: Node): TypeReferenceSerializationKind { + function getTypeReferenceSerializationKind(typeNameIn: EntityName, location?: Node): TypeReferenceSerializationKind { // ensure both `typeName` and `location` are parse tree nodes. - typeName = getParseTreeNode(typeName, isEntityName); + const typeName = getParseTreeNode(typeNameIn, isEntityName); if (!typeName) return TypeReferenceSerializationKind.Unknown; if (location) { @@ -26715,8 +26774,8 @@ namespace ts { } } - function createTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker, addUndefined?: boolean) { - declaration = getParseTreeNode(declaration, isVariableLikeOrAccessor); + function createTypeOfDeclaration(declarationIn: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker, addUndefined?: boolean) { + const declaration = getParseTreeNode(declarationIn, isVariableLikeOrAccessor); if (!declaration) { return createToken(SyntaxKind.AnyKeyword) as KeywordTypeNode; } @@ -26735,8 +26794,8 @@ namespace ts { return nodeBuilder.typeToTypeNode(type, enclosingDeclaration, flags | NodeBuilderFlags.MultilineObjectLiterals, tracker); } - function createReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker) { - signatureDeclaration = getParseTreeNode(signatureDeclaration, isFunctionLike); + function createReturnTypeOfSignatureDeclaration(signatureDeclarationIn: SignatureDeclaration, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker) { + const signatureDeclaration = getParseTreeNode(signatureDeclarationIn, isFunctionLike); if (!signatureDeclaration) { return createToken(SyntaxKind.AnyKeyword) as KeywordTypeNode; } @@ -26744,8 +26803,8 @@ namespace ts { return nodeBuilder.typeToTypeNode(getReturnTypeOfSignature(signature), enclosingDeclaration, flags | NodeBuilderFlags.MultilineObjectLiterals, tracker); } - function createTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker) { - expr = getParseTreeNode(expr, isExpression); + function createTypeOfExpression(exprIn: Expression, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker) { + const expr = getParseTreeNode(exprIn, isExpression); if (!expr) { return createToken(SyntaxKind.AnyKeyword) as KeywordTypeNode; } @@ -26757,7 +26816,7 @@ namespace ts { return globals.has(escapeLeadingUnderscores(name)); } - function getReferencedValueSymbol(reference: Identifier, startInDeclarationContainer?: boolean): Symbol { + function getReferencedValueSymbol(reference: Identifier, startInDeclarationContainer?: boolean): Symbol | undefined { const resolvedSymbol = getNodeLinks(reference).resolvedSymbol; if (resolvedSymbol) { return resolvedSymbol; @@ -26776,9 +26835,9 @@ namespace ts { return resolveName(location, reference.escapedText, SymbolFlags.Value | SymbolFlags.ExportValue | SymbolFlags.Alias, /*nodeNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true); } - function getReferencedValueDeclaration(reference: Identifier): Declaration { - if (!isGeneratedIdentifier(reference)) { - reference = getParseTreeNode(reference, isIdentifier); + function getReferencedValueDeclaration(referenceIn: Identifier): Declaration | undefined { + if (!isGeneratedIdentifier(referenceIn)) { + const reference = getParseTreeNode(referenceIn, isIdentifier); if (reference) { const symbol = getReferencedValueSymbol(reference); if (symbol) { @@ -26819,7 +26878,7 @@ namespace ts { if (!resolvedDirective || !resolvedDirective.resolvedFileName) { return; } - const file = host.getSourceFile(resolvedDirective.resolvedFileName); + const file = host.getSourceFile(resolvedDirective.resolvedFileName)!; fileToDirective.set(file.path, key); }); } @@ -26841,7 +26900,7 @@ namespace ts { }, getNodeCheckFlags: node => { node = getParseTreeNode(node); - return node ? getNodeCheckFlags(node) : undefined; + return node ? getNodeCheckFlags(node) : 0; }, isTopLevelValueImportEqualsWithEntityName, isDeclarationVisible, @@ -26854,8 +26913,8 @@ namespace ts { createLiteralConstValue, isSymbolAccessible, isEntityNameVisible, - getConstantValue: node => { - node = getParseTreeNode(node, canHaveConstantValue); + getConstantValue: nodeIn => { + const node = getParseTreeNode(nodeIn, canHaveConstantValue); return node ? getConstantValue(node) : undefined; }, collectLinkedAliases, @@ -26868,14 +26927,14 @@ namespace ts { getTypeReferenceDirectivesForEntityName, getTypeReferenceDirectivesForSymbol, isLiteralConstDeclaration, - isLateBound: (node: Declaration): node is LateBoundDeclaration => { - node = getParseTreeNode(node, isDeclaration); + isLateBound: (nodeIn: Declaration): nodeIn is LateBoundDeclaration => { + const node = getParseTreeNode(nodeIn, isDeclaration); const symbol = node && getSymbolOfNode(node); return !!(symbol && getCheckFlags(symbol) & CheckFlags.Late); }, getJsxFactoryEntity: location => location ? (getJsxNamespace(location), (getSourceFileOfNode(location).localJsxFactory || _jsxFactoryEntity)) : _jsxFactoryEntity, getAllAccessorDeclarations(accessor: AccessorDeclaration): AllAccessorDeclarations { - accessor = getParseTreeNode(accessor, isGetOrSetAccessorDeclaration); + accessor = getParseTreeNode(accessor, isGetOrSetAccessorDeclaration)!; // TODO: GH#18217 const otherKind = accessor.kind === SyntaxKind.SetAccessor ? SyntaxKind.GetAccessor : SyntaxKind.SetAccessor; const otherAccessor = getDeclarationOfKind(getSymbolOfNode(accessor), otherKind); const firstAccessor = otherAccessor && (otherAccessor.pos < accessor.pos) ? otherAccessor : accessor; @@ -26896,7 +26955,7 @@ namespace ts { } // defined here to avoid outer scope pollution - function getTypeReferenceDirectivesForEntityName(node: EntityNameOrEntityNameExpression): string[] { + function getTypeReferenceDirectivesForEntityName(node: EntityNameOrEntityNameExpression): string[] | undefined { // program does not have any files with type reference directives - bail out if (!fileToDirective) { return undefined; @@ -26914,7 +26973,7 @@ namespace ts { } // defined here to avoid outer scope pollution - function getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags): string[] { + function getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags): string[] | undefined { // program does not have any files with type reference directives - bail out if (!fileToDirective) { return undefined; @@ -26923,10 +26982,10 @@ namespace ts { return undefined; } // check what declarations in the symbol can contribute to the target meaning - let typeReferenceDirectives: string[]; + let typeReferenceDirectives: string[] | undefined; for (const decl of symbol.declarations) { // check meaning of the local symbol to see if declaration needs to be analyzed further - if (decl.symbol && decl.symbol.flags & meaning) { + if (decl.symbol && decl.symbol.flags & meaning!) { const file = getSourceFileOfNode(decl); const typeReferenceDirective = fileToDirective.get(file.path); if (typeReferenceDirective) { @@ -26975,9 +27034,9 @@ namespace ts { } } - function getExternalModuleFileFromDeclaration(declaration: AnyImportOrReExport | ModuleDeclaration | ImportTypeNode): SourceFile { + function getExternalModuleFileFromDeclaration(declaration: AnyImportOrReExport | ModuleDeclaration | ImportTypeNode): SourceFile | undefined { const specifier = declaration.kind === SyntaxKind.ModuleDeclaration ? tryCast(declaration.name, isStringLiteral) : getExternalModuleName(declaration); - const moduleSymbol = resolveExternalModuleNameWorker(specifier, specifier, /*moduleNotFoundError*/ undefined); + const moduleSymbol = resolveExternalModuleNameWorker(specifier!, specifier!, /*moduleNotFoundError*/ undefined); // TODO: GH#18217 if (!moduleSymbol) { return undefined; } @@ -26991,10 +27050,10 @@ namespace ts { } // Initialize global symbol table - let augmentations: ReadonlyArray[]; + let augmentations: ReadonlyArray[] | undefined; for (const file of host.getSourceFiles()) { if (!isExternalOrCommonJsModule(file)) { - mergeSymbolTable(globals, file.locals); + mergeSymbolTable(globals, file.locals!); } if (file.patternAmbientModules && file.patternAmbientModules.length) { patternAmbientModules = concatenate(patternAmbientModules, file.patternAmbientModules); @@ -27079,7 +27138,7 @@ namespace ts { for (let helper = ExternalEmitHelpers.FirstEmitHelper; helper <= ExternalEmitHelpers.LastEmitHelper; helper <<= 1) { if (uncheckedHelpers & helper) { const name = getHelperName(helper); - const symbol = getSymbol(helpersModule.exports, escapeLeadingUnderscores(name), SymbolFlags.Value); + const symbol = getSymbol(helpersModule.exports!, escapeLeadingUnderscores(name), SymbolFlags.Value); if (!symbol) { error(location, Diagnostics.This_syntax_requires_an_imported_helper_named_1_but_module_0_has_no_exported_member_1, externalHelpersModuleNameText, name); } @@ -27110,7 +27169,7 @@ namespace ts { case ExternalEmitHelpers.AsyncValues: return "__asyncValues"; case ExternalEmitHelpers.ExportStar: return "__exportStar"; case ExternalEmitHelpers.MakeTemplateObject: return "__makeTemplateObject"; - default: Debug.fail("Unrecognized helper"); + default: return Debug.fail("Unrecognized helper"); } } @@ -27153,9 +27212,9 @@ namespace ts { return quickResult; } - let lastStatic: Node, lastDeclare: Node, lastAsync: Node, lastReadonly: Node; + let lastStatic: Node | undefined, lastDeclare: Node | undefined, lastAsync: Node | undefined, lastReadonly: Node | undefined; let flags = ModifierFlags.None; - for (const modifier of node.modifiers) { + for (const modifier of node.modifiers!) { if (modifier.kind !== SyntaxKind.ReadonlyKeyword) { if (node.kind === SyntaxKind.PropertySignature || node.kind === SyntaxKind.MethodSignature) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_type_member, tokenToString(modifier.kind)); @@ -27328,21 +27387,21 @@ namespace ts { if (node.kind === SyntaxKind.Constructor) { if (flags & ModifierFlags.Static) { - return grammarErrorOnNode(lastStatic, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "static"); + return grammarErrorOnNode(lastStatic!, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "static"); } if (flags & ModifierFlags.Abstract) { - return grammarErrorOnNode(lastStatic, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "abstract"); + return grammarErrorOnNode(lastStatic!, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "abstract"); // TODO: GH#18217 } else if (flags & ModifierFlags.Async) { - return grammarErrorOnNode(lastAsync, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "async"); + return grammarErrorOnNode(lastAsync!, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "async"); } else if (flags & ModifierFlags.Readonly) { - return grammarErrorOnNode(lastReadonly, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "readonly"); + return grammarErrorOnNode(lastReadonly!, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "readonly"); } - return; + return false; } else if ((node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.ImportEqualsDeclaration) && flags & ModifierFlags.Ambient) { - return grammarErrorOnNode(lastDeclare, Diagnostics.A_0_modifier_cannot_be_used_with_an_import_declaration, "declare"); + return grammarErrorOnNode(lastDeclare!, Diagnostics.A_0_modifier_cannot_be_used_with_an_import_declaration, "declare"); } else if (node.kind === SyntaxKind.Parameter && (flags & ModifierFlags.ParameterPropertyModifier) && isBindingPattern((node).name)) { return grammarErrorOnNode(node, Diagnostics.A_parameter_property_may_not_be_declared_using_a_binding_pattern); @@ -27351,8 +27410,9 @@ namespace ts { return grammarErrorOnNode(node, Diagnostics.A_parameter_property_cannot_be_declared_using_a_rest_parameter); } if (flags & ModifierFlags.Async) { - return checkGrammarAsyncModifier(node, lastAsync); + return checkGrammarAsyncModifier(node, lastAsync!); } + return false; } /** @@ -27407,7 +27467,7 @@ namespace ts { } } function nodeHasAnyModifiersExcept(node: Node, allowedModifier: SyntaxKind): boolean { - return node.modifiers.length > 1 || node.modifiers[0].kind !== allowedModifier; + return node.modifiers!.length > 1 || node.modifiers![0].kind !== allowedModifier; } function checkGrammarAsyncModifier(node: Node, asyncModifier: Node): boolean { @@ -27422,10 +27482,11 @@ namespace ts { return grammarErrorOnNode(asyncModifier, Diagnostics._0_modifier_cannot_be_used_here, "async"); } - function checkGrammarForDisallowedTrailingComma(list: NodeArray, diag = Diagnostics.Trailing_comma_not_allowed): boolean { + function checkGrammarForDisallowedTrailingComma(list: NodeArray | undefined, diag = Diagnostics.Trailing_comma_not_allowed): boolean { if (list && list.hasTrailingComma) { return grammarErrorAtPos(list[0], list.end - ",".length, ",".length, diag); } + return false; } function checkGrammarTypeParameterList(typeParameters: NodeArray | undefined, file: SourceFile): boolean { @@ -27434,6 +27495,7 @@ namespace ts { const end = skipTrivia(file.text, typeParameters.end) + ">".length; return grammarErrorAtPos(file, start, end - start, Diagnostics.Type_parameter_list_cannot_be_empty); } + return false; } function checkGrammarParameterList(parameters: NodeArray) { @@ -27531,7 +27593,7 @@ namespace ts { Diagnostics.An_index_signature_parameter_type_cannot_be_a_type_alias_Consider_writing_0_Colon_1_Colon_2_instead, getTextOfNode(parameter.name), typeToString(type), - typeToString(getTypeFromTypeNode(node.type))); + typeToString(getTypeFromTypeNode(node.type!))); } if (type.flags & TypeFlags.Union && allTypesAssignableToKind(type, TypeFlags.StringLiteral, /*strict*/ true)) { @@ -27544,6 +27606,7 @@ namespace ts { if (!node.type) { return grammarErrorOnNode(node, Diagnostics.An_index_signature_must_have_a_type_annotation); } + return false; } function checkGrammarIndexSignature(node: SignatureDeclaration) { @@ -27551,21 +27614,22 @@ namespace ts { return checkGrammarDecoratorsAndModifiers(node) || checkGrammarIndexSignatureParameters(node); } - function checkGrammarForAtLeastOneTypeArgument(node: Node, typeArguments: NodeArray): boolean { + function checkGrammarForAtLeastOneTypeArgument(node: Node, typeArguments: NodeArray | undefined): boolean { if (typeArguments && typeArguments.length === 0) { const sourceFile = getSourceFileOfNode(node); const start = typeArguments.pos - "<".length; const end = skipTrivia(sourceFile.text, typeArguments.end) + ">".length; return grammarErrorAtPos(sourceFile, start, end - start, Diagnostics.Type_argument_list_cannot_be_empty); } + return false; } - function checkGrammarTypeArguments(node: Node, typeArguments: NodeArray): boolean { + function checkGrammarTypeArguments(node: Node, typeArguments: NodeArray | undefined): boolean { return checkGrammarForDisallowedTrailingComma(typeArguments) || checkGrammarForAtLeastOneTypeArgument(node, typeArguments); } - function checkGrammarForOmittedArgument(args: NodeArray): boolean { + function checkGrammarForOmittedArgument(args: NodeArray | undefined): boolean { if (args) { for (const arg of args) { if (arg.kind === SyntaxKind.OmittedExpression) { @@ -27573,9 +27637,10 @@ namespace ts { } } } + return false; } - function checkGrammarArguments(args: NodeArray): boolean { + function checkGrammarArguments(args: NodeArray | undefined): boolean { return checkGrammarForOmittedArgument(args); } @@ -27588,7 +27653,7 @@ namespace ts { const listType = tokenToString(node.token); return grammarErrorAtPos(node, types.pos, 0, Diagnostics._0_list_cannot_be_empty, listType); } - return forEach(types, checkGrammarExpressionWithTypeArguments); + return some(types, checkGrammarExpressionWithTypeArguments); } function checkGrammarExpressionWithTypeArguments(node: ExpressionWithTypeArguments) { @@ -27665,6 +27730,7 @@ namespace ts { if (computedPropertyName.expression.kind === SyntaxKind.BinaryExpression && (computedPropertyName.expression).operatorToken.kind === SyntaxKind.CommaToken) { return grammarErrorOnNode(computedPropertyName.expression, Diagnostics.A_comma_expression_is_not_allowed_in_a_computed_property_name); } + return false; } function checkGrammarForGenerator(node: FunctionLikeDeclaration) { @@ -27674,18 +27740,16 @@ namespace ts { node.kind === SyntaxKind.FunctionExpression || node.kind === SyntaxKind.MethodDeclaration); if (node.flags & NodeFlags.Ambient) { - return grammarErrorOnNode(node.asteriskToken, Diagnostics.Generators_are_not_allowed_in_an_ambient_context); + return grammarErrorOnNode(node.asteriskToken!, Diagnostics.Generators_are_not_allowed_in_an_ambient_context); } if (!node.body) { - return grammarErrorOnNode(node.asteriskToken, Diagnostics.An_overload_signature_cannot_be_declared_as_a_generator); + return grammarErrorOnNode(node.asteriskToken!, Diagnostics.An_overload_signature_cannot_be_declared_as_a_generator); } } } - function checkGrammarForInvalidQuestionMark(questionToken: Node, message: DiagnosticMessage): boolean { - if (questionToken) { - return grammarErrorOnNode(questionToken, message); - } + function checkGrammarForInvalidQuestionMark(questionToken: Node | undefined, message: DiagnosticMessage): boolean { + return !!questionToken && grammarErrorOnNode(questionToken, message); } function checkGrammarObjectLiteralExpression(node: ObjectLiteralExpression, inDestructuring: boolean) { @@ -27710,12 +27774,12 @@ namespace ts { if (prop.kind === SyntaxKind.ShorthandPropertyAssignment && !inDestructuring && prop.objectAssignmentInitializer) { // having objectAssignmentInitializer is only valid in ObjectAssignmentPattern // outside of destructuring it is a syntax error - return grammarErrorOnNode(prop.equalsToken, Diagnostics.can_only_be_used_in_an_object_literal_property_inside_a_destructuring_assignment); + return grammarErrorOnNode(prop.equalsToken!, Diagnostics.can_only_be_used_in_an_object_literal_property_inside_a_destructuring_assignment); } // Modifiers are never allowed on properties except for 'async' on a method declaration if (prop.modifiers) { - for (const mod of prop.modifiers) { + for (const mod of prop.modifiers!) { // TODO: GH#19955 if (mod.kind !== SyntaxKind.AsyncKeyword || prop.kind !== SyntaxKind.MethodDeclaration) { grammarErrorOnNode(mod, Diagnostics._0_modifier_cannot_be_used_here, getTextOfNode(mod)); } @@ -27750,7 +27814,7 @@ namespace ts { currentKind = Flags.SetAccessor; break; default: - Debug.assertNever(prop, "Unexpected syntax kind:" + (prop).kind); + throw Debug.assertNever(prop, "Unexpected syntax kind:" + (prop).kind); } const effectiveName = getPropertyNameForPropertyNameNode(name); @@ -27897,6 +27961,7 @@ namespace ts { } } } + return false; } /** Does the accessor have the right number of parameters? @@ -27907,7 +27972,7 @@ namespace ts { return getAccessorThisParameter(accessor) || accessor.parameters.length === (accessor.kind === SyntaxKind.GetAccessor ? 0 : 1); } - function getAccessorThisParameter(accessor: AccessorDeclaration): ParameterDeclaration { + function getAccessorThisParameter(accessor: AccessorDeclaration): ParameterDeclaration | undefined { if (accessor.parameters.length === (accessor.kind === SyntaxKind.GetAccessor ? 1 : 2)) { return getThisParameter(accessor); } @@ -28152,6 +28217,7 @@ namespace ts { } } } + return false; } function checkGrammarNameInLetOrConstDeclarations(name: Identifier | BindingPattern): boolean { @@ -28168,6 +28234,7 @@ namespace ts { } } } + return false; } function checkGrammarVariableDeclarationList(declarationList: VariableDeclarationList): boolean { @@ -28179,6 +28246,7 @@ namespace ts { if (!declarationList.declarations.length) { return grammarErrorAtPos(declarationList, declarations.pos, declarations.end - declarations.pos, Diagnostics.Variable_declaration_list_cannot_be_empty); } + return false; } function allowLetAndConstDeclarations(parent: Node): boolean { @@ -28236,6 +28304,7 @@ namespace ts { diagnostics.add(createFileDiagnostic(sourceFile, span.start, span.length, message, arg0, arg1, arg2)); return true; } + return false; } function grammarErrorAtPos(nodeForSourceFile: Node, start: number, length: number, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): boolean { @@ -28244,6 +28313,7 @@ namespace ts { diagnostics.add(createFileDiagnostic(sourceFile, start, length, message, arg0, arg1, arg2)); return true; } + return false; } function grammarErrorOnNode(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): boolean { @@ -28252,6 +28322,7 @@ namespace ts { diagnostics.add(createDiagnosticForNode(node, message, arg0, arg1, arg2)); return true; } + return false; } function checkGrammarConstructorTypeParameters(node: ConstructorDeclaration) { @@ -28337,6 +28408,7 @@ namespace ts { } } } + return false; } function checkGrammarSourceFile(node: SourceFile): boolean { @@ -28374,6 +28446,7 @@ namespace ts { // Debug.assert(isStatement(node.parent)); } } + return false; } function checkGrammarNumericLiteral(node: NumericLiteral): boolean { @@ -28395,6 +28468,7 @@ namespace ts { return grammarErrorOnNode(withMinus ? node.parent : node, diagnosticMessage, literal); } } + return false; } function grammarErrorAfterFirstToken(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): boolean { @@ -28404,6 +28478,7 @@ namespace ts { diagnostics.add(createFileDiagnostic(sourceFile, textSpanEnd(span), /*length*/ 0, message, arg0, arg1, arg2)); return true; } + return false; } function getAmbientModules(): Symbol[] { @@ -28412,7 +28487,7 @@ namespace ts { globals.forEach((global, sym) => { // No need to `unescapeLeadingUnderscores`, an escaped symbol is never an ambient module. if (ambientModuleSymbolRegex.test(sym as string)) { - ambientModulesCache.push(global); + ambientModulesCache!.push(global); } }); } @@ -28438,6 +28513,7 @@ namespace ts { if (isSpreadElement(nodeArguments[0])) { return grammarErrorOnNode(nodeArguments[0], Diagnostics.Specifier_of_dynamic_import_cannot_be_spread_element); } + return false; } } diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 8b963409ab6ad..2f205f1e44e31 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -814,7 +814,7 @@ namespace ts { case "string": return map(values, v => v || ""); default: - return filter(map(values, v => parseCustomTypeOption(opt.element, v, errors)), v => !!v); + return mapDefined(values, v => parseCustomTypeOption(opt.element, v, errors)); } } @@ -965,7 +965,7 @@ namespace ts { * Reads the config file, reports errors if any and exits if the config file cannot be found */ export function getParsedCommandLineOfConfigFile(configFileName: string, optionsToExtend: CompilerOptions, host: ParseConfigFileHost): ParsedCommandLine | undefined { - let configFileText: string; + let configFileText: string | undefined; try { configFileText = host.readFile(configFileName); } @@ -1035,7 +1035,7 @@ namespace ts { function getTsconfigRootOptionsMap() { if (_tsconfigRootOptions === undefined) { _tsconfigRootOptions = { - name: undefined, // should never be needed since this is root + name: undefined!, // should never be needed since this is root type: "object", elementOptions: commandLineOptionsToMap([ { @@ -1194,7 +1194,7 @@ namespace ts { if (parentOption) { if (isValidOptionValue) { // Notify option set in the parent if its a valid option value - jsonConversionNotifier.onSetValidOptionKeyValueInParent(parentOption, option, value); + jsonConversionNotifier.onSetValidOptionKeyValueInParent(parentOption, option!, value); } } else if (isRootOptionMap(knownOptions)) { @@ -1220,7 +1220,7 @@ namespace ts { return (returnValue ? elements.map : elements.forEach).call(elements, (element: Expression) => convertPropertyValueToJson(element, elementOption)); } - function convertPropertyValueToJson(valueExpression: Expression, option: CommandLineOption): any { + function convertPropertyValueToJson(valueExpression: Expression, option: CommandLineOption | undefined): any { switch (valueExpression.kind) { case SyntaxKind.TrueKeyword: reportInvalidOptionValue(option && option.type !== "boolean"); @@ -1303,9 +1303,9 @@ namespace ts { return undefined; - function reportInvalidOptionValue(isError: boolean) { + function reportInvalidOptionValue(isError: boolean | undefined) { if (isError) { - errors.push(createDiagnosticForNodeInSourceFile(sourceFile, valueExpression, Diagnostics.Compiler_option_0_requires_a_value_of_type_1, option.name, getCompilerOptionValueTypeString(option))); + errors.push(createDiagnosticForNodeInSourceFile(sourceFile, valueExpression, Diagnostics.Compiler_option_0_requires_a_value_of_type_1, option!.name, getCompilerOptionValueTypeString(option!))); } } } @@ -1321,7 +1321,7 @@ namespace ts { isString(option.type) ? option.type : "string"; } - function isCompilerOptionsValue(option: CommandLineOption, value: any): value is CompilerOptionsValue { + function isCompilerOptionsValue(option: CommandLineOption | undefined, value: any): value is CompilerOptionsValue { if (option) { if (isNullOrUndefined(value)) return true; // All options are undefinable/nullable if (option.type === "list") { @@ -1330,6 +1330,7 @@ namespace ts { const expectedType = isString(option.type) ? option.type : "string"; return typeof value === expectedType; } + return false; } /** @@ -1373,7 +1374,7 @@ namespace ts { if (hasProperty(options, name)) { // tsconfig only options cannot be specified via command line, // so we can assume that only types that can appear here string | number | boolean - if (optionsNameMap.has(name) && optionsNameMap.get(name).category === Diagnostics.Command_line_Options) { + if (optionsNameMap.has(name) && optionsNameMap.get(name)!.category === Diagnostics.Command_line_Options) { continue; } const value = options[name]; @@ -1387,7 +1388,7 @@ namespace ts { } else { if (optionDefinition.type === "list") { - result.set(name, (value as ReadonlyArray).map(element => getNameOfCompilerOptionValue(element, customTypeMap))); + result.set(name, (value as ReadonlyArray).map(element => getNameOfCompilerOptionValue(element, customTypeMap)!)); // TODO: GH#18217 } else { // There is a typeMap associated with this command-line option so use it to map value back to its name @@ -1436,7 +1437,7 @@ namespace ts { const { category } = option; if (isAllowedOption(option)) { - categorizedOptions.add(getLocaleSpecificMessage(category), option); + categorizedOptions.add(getLocaleSpecificMessage(category!), option); } } @@ -1517,7 +1518,7 @@ namespace ts { } /*@internal*/ - export function setConfigFileInOptions(options: CompilerOptions, configFile: TsConfigSourceFile) { + export function setConfigFileInOptions(options: CompilerOptions, configFile: TsConfigSourceFile | undefined) { if (configFile) { Object.defineProperty(options, "configFile", { enumerable: false, writable: false, value: configFile }); } @@ -1545,7 +1546,7 @@ namespace ts { */ function parseJsonConfigFileContentWorker( json: any, - sourceFile: TsConfigSourceFile, + sourceFile: TsConfigSourceFile | undefined, host: ParseConfigHost, basePath: string, existingOptions: CompilerOptions = {}, @@ -1575,7 +1576,7 @@ namespace ts { }; function getFileNames(): ExpandResult { - let filesSpecs: ReadonlyArray; + let filesSpecs: ReadonlyArray | undefined; if (hasProperty(raw, "files") && !isNullOrUndefined(raw.files)) { if (isArray(raw.files)) { filesSpecs = >raw.files; @@ -1588,7 +1589,7 @@ namespace ts { } } - let includeSpecs: ReadonlyArray; + let includeSpecs: ReadonlyArray | undefined; if (hasProperty(raw, "include") && !isNullOrUndefined(raw.include)) { if (isArray(raw.include)) { includeSpecs = >raw.include; @@ -1598,7 +1599,7 @@ namespace ts { } } - let excludeSpecs: ReadonlyArray; + let excludeSpecs: ReadonlyArray | undefined; if (hasProperty(raw, "exclude") && !isNullOrUndefined(raw.exclude)) { if (isArray(raw.exclude)) { excludeSpecs = >raw.exclude; @@ -1692,10 +1693,10 @@ namespace ts { */ function parseConfig( json: any, - sourceFile: TsConfigSourceFile, + sourceFile: TsConfigSourceFile | undefined, host: ParseConfigHost, basePath: string, - configFileName: string, + configFileName: string | undefined, resolutionStack: string[], errors: Push, ): ParsedTsconfig { @@ -1704,17 +1705,17 @@ namespace ts { if (resolutionStack.indexOf(resolvedPath) >= 0) { errors.push(createCompilerDiagnostic(Diagnostics.Circularity_detected_while_resolving_configuration_Colon_0, [...resolutionStack, resolvedPath].join(" -> "))); - return { raw: json || convertToObject(sourceFile, errors) }; + return { raw: json || convertToObject(sourceFile!, errors) }; } const ownConfig = json ? parseOwnConfigOfJson(json, host, basePath, configFileName, errors) : - parseOwnConfigOfJsonSourceFile(sourceFile, host, basePath, configFileName, errors); + parseOwnConfigOfJsonSourceFile(sourceFile!, host, basePath, configFileName, errors); if (ownConfig.extendedConfigPath) { // copy the resolution stack so it is never reused between branches in potential diamond-problem scenarios. resolutionStack = resolutionStack.concat([resolvedPath]); - const extendedConfig = getExtendedConfig(sourceFile, ownConfig.extendedConfigPath, host, basePath, resolutionStack, errors); + const extendedConfig = getExtendedConfig(sourceFile!, ownConfig.extendedConfigPath, host, basePath, resolutionStack, errors); if (extendedConfig && isSuccessfulParsedTsconfig(extendedConfig)) { const baseRaw = extendedConfig.raw; const raw = ownConfig.raw; @@ -1754,7 +1755,7 @@ namespace ts { // It should be removed in future releases - use typeAcquisition instead. const typeAcquisition = convertTypeAcquisitionFromJsonWorker(json.typeAcquisition || json.typingOptions, basePath, errors, configFileName); json.compileOnSave = convertCompileOnSaveOptionFromJson(json, basePath, errors); - let extendedConfigPath: string; + let extendedConfigPath: string | undefined; if (json.extends) { if (!isString(json.extends)) { @@ -1776,8 +1777,8 @@ namespace ts { errors: Push ): ParsedTsconfig { const options = getDefaultCompilerOptions(configFileName); - let typeAcquisition: TypeAcquisition, typingOptionstypeAcquisition: TypeAcquisition; - let extendedConfigPath: string; + let typeAcquisition: TypeAcquisition | undefined, typingOptionstypeAcquisition: TypeAcquisition | undefined; + let extendedConfigPath: string | undefined; const optionsIterator: JsonConversionNotifier = { onSetValidOptionKeyValueInParent(parentOption: string, option: CommandLineOption, value: CompilerOptionsValue) { @@ -1879,7 +1880,7 @@ namespace ts { const extendedConfig = parseConfig(/*json*/ undefined, extendedResult, host, extendedDirname, getBaseFileName(extendedConfigPath), resolutionStack, errors); if (sourceFile) { - sourceFile.extendedSourceFiles.push(...extendedResult.extendedSourceFiles); + sourceFile.extendedSourceFiles!.push(...extendedResult.extendedSourceFiles!); } if (isSuccessfulParsedTsconfig(extendedConfig)) { @@ -1903,13 +1904,10 @@ namespace ts { function convertCompileOnSaveOptionFromJson(jsonOption: any, basePath: string, errors: Push): boolean { if (!hasProperty(jsonOption, compileOnSaveCommandLineOption.name)) { - return undefined; + return false; } const result = convertJsonOption(compileOnSaveCommandLineOption, jsonOption.compileOnSave, basePath, errors); - if (typeof result === "boolean" && result) { - return result; - } - return false; + return typeof result === "boolean" && result; } export function convertCompilerOptionsFromJson(jsonOptions: any, basePath: string, configFileName?: string): { options: CompilerOptions, errors: Diagnostic[] } { @@ -1943,7 +1941,7 @@ namespace ts { } function getDefaultTypeAcquisition(configFileName?: string): TypeAcquisition { - return { enable: configFileName && getBaseFileName(configFileName) === "jsconfig.json", include: [], exclude: [] }; + return { enable: !!configFileName && getBaseFileName(configFileName) === "jsconfig.json", include: [], exclude: [] }; } function convertTypeAcquisitionFromJsonWorker(jsonOptions: any, @@ -2106,18 +2104,18 @@ namespace ts { * @param errors An array for diagnostic reporting. */ function matchFileNames( - filesSpecs: ReadonlyArray, - includeSpecs: ReadonlyArray, - excludeSpecs: ReadonlyArray, + filesSpecs: ReadonlyArray | undefined, + includeSpecs: ReadonlyArray | undefined, + excludeSpecs: ReadonlyArray | undefined, basePath: string, options: CompilerOptions, host: ParseConfigHost, errors: Push, extraFileExtensions: ReadonlyArray, - jsonSourceFile: TsConfigSourceFile + jsonSourceFile: TsConfigSourceFile | undefined ): ExpandResult { basePath = normalizePath(basePath); - let validatedIncludeSpecs: ReadonlyArray, validatedExcludeSpecs: ReadonlyArray; + let validatedIncludeSpecs: ReadonlyArray | undefined, validatedExcludeSpecs: ReadonlyArray | undefined; // The exclude spec list is converted into a regular expression, which allows us to quickly // test whether a file or directory should be excluded before recursively traversing the @@ -2223,7 +2221,7 @@ namespace ts { }; } - function validateSpecs(specs: ReadonlyArray, errors: Push, allowTrailingRecursion: boolean, jsonSourceFile: TsConfigSourceFile, specKey: string): ReadonlyArray { + function validateSpecs(specs: ReadonlyArray, errors: Push, allowTrailingRecursion: boolean, jsonSourceFile: TsConfigSourceFile | undefined, specKey: string): ReadonlyArray { return specs.filter(spec => { const diag = specToDiagnostic(spec, allowTrailingRecursion); if (diag !== undefined) { @@ -2235,7 +2233,7 @@ namespace ts { function createDiagnostic(message: DiagnosticMessage, spec: string): Diagnostic { const element = getTsConfigPropArrayElementValue(jsonSourceFile, specKey, spec); return element ? - createDiagnosticForNodeInSourceFile(jsonSourceFile, element, message, spec) : + createDiagnosticForNodeInSourceFile(jsonSourceFile!, element, message, spec) : createCompilerDiagnostic(message, spec); } } @@ -2252,7 +2250,7 @@ namespace ts { /** * Gets directories in a set of include patterns that should be watched for changes. */ - function getWildcardDirectories(include: ReadonlyArray, exclude: ReadonlyArray, path: string, useCaseSensitiveFileNames: boolean): MapLike { + function getWildcardDirectories(include: ReadonlyArray | undefined, exclude: ReadonlyArray | undefined, path: string, useCaseSensitiveFileNames: boolean): MapLike { // We watch a directory recursively if it contains a wildcard anywhere in a directory segment // of the pattern: // @@ -2394,7 +2392,7 @@ namespace ts { if (optionEnumValue === value) { return optionStringValue; } - }); + })!; // TODO: GH#18217 } } } diff --git a/src/compiler/comments.ts b/src/compiler/comments.ts index de629cccfe141..989935a5edbf3 100644 --- a/src/compiler/comments.ts +++ b/src/compiler/comments.ts @@ -3,8 +3,8 @@ namespace ts { export interface CommentWriter { reset(): void; setSourceFile(sourceFile: SourceFile): void; - setWriter(writer: EmitTextWriter): void; - emitNodeWithComments(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void; + setWriter(writer: EmitTextWriter | undefined): void; + emitNodeWithComments(hint: EmitHint, node: Node | undefined, emitCallback: (hint: EmitHint, node: Node) => void): void; emitBodyWithDetachedComments(node: Node, detachedRange: TextRange, emitCallback: (node: Node) => void): void; emitTrailingCommentsOfPosition(pos: number, prefixSpace?: boolean): void; emitLeadingCommentsOfPosition(pos: number): void; @@ -20,9 +20,9 @@ namespace ts { let currentSourceFile: SourceFile; let currentText: string; let currentLineMap: ReadonlyArray; - let detachedCommentsInfo: { nodePos: number, detachedCommentEndPos: number}[]; + let detachedCommentsInfo: { nodePos: number, detachedCommentEndPos: number}[] | undefined; let hasWrittenComment = false; - let disabled: boolean = printerOptions.removeComments; + let disabled: boolean = !!printerOptions.removeComments; return { reset, @@ -44,7 +44,7 @@ namespace ts { hasWrittenComment = false; const emitNode = node.emitNode; - const emitFlags = emitNode && emitNode.flags; + const emitFlags = emitNode && emitNode.flags || 0; const { pos, end } = emitNode && emitNode.commentRange || node; if ((pos < 0 && end < 0) || (pos === end)) { // Both pos and end are synthesized, so just emit the node without comments. @@ -114,7 +114,7 @@ namespace ts { } } - function emitNodeWithSynthesizedComments(hint: EmitHint, node: Node, emitNode: EmitNode, emitFlags: EmitFlags, emitCallback: (hint: EmitHint, node: Node) => void) { + function emitNodeWithSynthesizedComments(hint: EmitHint, node: Node, emitNode: EmitNode | undefined, emitFlags: EmitFlags, emitCallback: (hint: EmitHint, node: Node) => void) { const leadingComments = emitNode && emitNode.leadingComments; if (some(leadingComments)) { if (extendedDiagnostics) { @@ -170,7 +170,7 @@ namespace ts { function writeSynthesizedComment(comment: SynthesizedComment) { const text = formatSynthesizedComment(comment); const lineMap = comment.kind === SyntaxKind.MultiLineCommentTrivia ? computeLineStarts(text) : undefined; - writeCommentRange(text, lineMap, writer, 0, text.length, newLine); + writeCommentRange(text, lineMap!, writer, 0, text.length, newLine); } function formatSynthesizedComment(comment: SynthesizedComment) { @@ -364,9 +364,9 @@ namespace ts { } function reset() { - currentSourceFile = undefined; - currentText = undefined; - currentLineMap = undefined; + currentSourceFile = undefined!; + currentText = undefined!; + currentLineMap = undefined!; detachedCommentsInfo = undefined; } @@ -382,14 +382,14 @@ namespace ts { } function hasDetachedComments(pos: number) { - return detachedCommentsInfo !== undefined && lastOrUndefined(detachedCommentsInfo).nodePos === pos; + return detachedCommentsInfo !== undefined && last(detachedCommentsInfo).nodePos === pos; } function forEachLeadingCommentWithoutDetachedComments(cb: (commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean, rangePos: number) => void) { // get the leading comments from detachedPos - const pos = lastOrUndefined(detachedCommentsInfo).detachedCommentEndPos; - if (detachedCommentsInfo.length - 1) { - detachedCommentsInfo.pop(); + const pos = last(detachedCommentsInfo!).detachedCommentEndPos; + if (detachedCommentsInfo!.length - 1) { + detachedCommentsInfo!.pop(); } else { detachedCommentsInfo = undefined; diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 5307c1de7b470..90572217d4354 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -59,7 +59,7 @@ namespace ts { return result; } - export function createMapFromTemplate(template?: MapLike): Map { + export function createMapFromTemplate(template: MapLike): Map { const map: Map = new MapCtr(); // Copies keys/values from template. Note that for..in will not throw if @@ -107,7 +107,7 @@ namespace ts { private data = createDictionaryObject(); public size = 0; - get(key: string): T { + get(key: string): T | undefined { return this.data[key]; } @@ -138,15 +138,15 @@ namespace ts { this.size = 0; } - keys() { + keys(): Iterator { return new MapIterator(this.data, (_data, key) => key); } - values() { + values(): Iterator { return new MapIterator(this.data, (data, key) => data[key]); } - entries() { + entries(): Iterator<[string, T]> { return new MapIterator(this.data, (data, key) => [key, data[key]] as [string, T]); } @@ -158,14 +158,14 @@ namespace ts { }; } - export function toPath(fileName: string, basePath: string, getCanonicalFileName: (path: string) => string): Path { + export function toPath(fileName: string, basePath: string | undefined, getCanonicalFileName: (path: string) => string): Path { const nonCanonicalizedPath = isRootedDiskPath(fileName) ? normalizePath(fileName) : getNormalizedAbsolutePath(fileName, basePath); return getCanonicalFileName(nonCanonicalizedPath); } - export function length(array: ReadonlyArray) { + export function length(array: ReadonlyArray | undefined): number { return array ? array.length : 0; } @@ -220,9 +220,9 @@ namespace ts { * If no such value is found, it applies the callback until the parent pointer is undefined or the callback returns "quit" * At that point findAncestor returns undefined. */ - export function findAncestor(node: Node, callback: (element: Node) => element is T): T | undefined; - export function findAncestor(node: Node, callback: (element: Node) => boolean | "quit"): Node | undefined; - export function findAncestor(node: Node, callback: (element: Node) => boolean | "quit"): Node { + export function findAncestor(node: Node | undefined, callback: (element: Node) => element is T): T | undefined; + export function findAncestor(node: Node | undefined, callback: (element: Node) => boolean | "quit"): Node | undefined; + export function findAncestor(node: Node, callback: (element: Node) => boolean | "quit"): Node | undefined { while (node) { const result = callback(node); if (result === "quit") { @@ -340,10 +340,10 @@ namespace ts { return result; } } - Debug.fail(); + return Debug.fail(); } - export function contains(array: ReadonlyArray, value: T, equalityComparer: EqualityComparer = equateValues): boolean { + export function contains(array: ReadonlyArray | undefined, value: T, equalityComparer: EqualityComparer = equateValues): boolean { if (array) { for (const v of array) { if (equalityComparer(v, value)) { @@ -388,7 +388,11 @@ namespace ts { export function filter(array: T[], f: (x: T) => boolean): T[]; export function filter(array: ReadonlyArray, f: (x: T) => x is U): ReadonlyArray; export function filter(array: ReadonlyArray, f: (x: T) => boolean): ReadonlyArray; - export function filter(array: T[], f: (x: T) => boolean): T[] { + export function filter(array: T[] | undefined, f: (x: T) => x is U): U[] | undefined; + export function filter(array: T[] | undefined, f: (x: T) => boolean): T[] | undefined; + export function filter(array: ReadonlyArray | undefined, f: (x: T) => x is U): ReadonlyArray | undefined; + export function filter(array: ReadonlyArray | undefined, f: (x: T) => boolean): ReadonlyArray | undefined; + export function filter(array: ReadonlyArray | undefined, f: (x: T) => boolean): ReadonlyArray | undefined { if (array) { const len = array.length; let i = 0; @@ -424,8 +428,10 @@ namespace ts { array.length = 0; } - export function map(array: ReadonlyArray, f: (x: T, i: number) => U): U[] { - let result: U[]; + export function map(array: ReadonlyArray, f: (x: T, i: number) => U): U[]; + export function map(array: ReadonlyArray | undefined, f: (x: T, i: number) => U): U[] | undefined; + export function map(array: ReadonlyArray | undefined, f: (x: T, i: number) => U): U[] | undefined { + let result: U[] | undefined; if (array) { result = []; for (let i = 0; i < array.length; i++) { @@ -448,7 +454,9 @@ namespace ts { // Maps from T to T and avoids allocation if all elements map to themselves export function sameMap(array: T[], f: (x: T, i: number) => T): T[]; export function sameMap(array: ReadonlyArray, f: (x: T, i: number) => T): ReadonlyArray; - export function sameMap(array: T[], f: (x: T, i: number) => T): T[] { + export function sameMap(array: T[] | undefined, f: (x: T, i: number) => T): T[] | undefined; + export function sameMap(array: ReadonlyArray | undefined, f: (x: T, i: number) => T): ReadonlyArray | undefined; + export function sameMap(array: ReadonlyArray | undefined, f: (x: T, i: number) => T): ReadonlyArray | undefined { if (array) { for (let i = 0; i < array.length; i++) { const item = array[i]; @@ -471,8 +479,10 @@ namespace ts { * * @param array The array to flatten. */ - export function flatten(array: ReadonlyArray>): T[] { - let result: T[]; + export function flatten(array: ReadonlyArray | undefined>): T[]; + export function flatten(array: ReadonlyArray | undefined> | undefined): T[] | undefined; + export function flatten(array: ReadonlyArray | undefined> | undefined): T[] | undefined { + let result: T[] | undefined; if (array) { result = []; for (const v of array) { @@ -496,8 +506,10 @@ namespace ts { * @param array The array to map. * @param mapfn The callback used to map the result into one or more values. */ + export function flatMap(array: ReadonlyArray, mapfn: (x: T, i: number) => U | ReadonlyArray | undefined): U[]; + export function flatMap(array: ReadonlyArray | undefined, mapfn: (x: T, i: number) => U | ReadonlyArray | undefined): U[] | undefined; export function flatMap(array: ReadonlyArray | undefined, mapfn: (x: T, i: number) => U | ReadonlyArray | undefined): U[] | undefined { - let result: U[]; + let result: U[] | undefined; if (array) { result = []; for (let i = 0; i < array.length; i++) { @@ -553,7 +565,7 @@ namespace ts { export function sameFlatMap(array: T[], mapfn: (x: T, i: number) => T | ReadonlyArray): T[]; export function sameFlatMap(array: ReadonlyArray, mapfn: (x: T, i: number) => T | ReadonlyArray): ReadonlyArray; export function sameFlatMap(array: T[], mapfn: (x: T, i: number) => T | T[]): T[] { - let result: T[]; + let result: T[] | undefined; if (array) { for (let i = 0; i < array.length; i++) { const item = array[i]; @@ -636,13 +648,15 @@ namespace ts { * @param keyfn A callback used to select the key for an element. * @param mapfn A callback used to map a contiguous chunk of values to a single value. */ - export function spanMap(array: ReadonlyArray, keyfn: (x: T, i: number) => K, mapfn: (chunk: T[], key: K, start: number, end: number) => U): U[] { - let result: U[]; + export function spanMap(array: ReadonlyArray, keyfn: (x: T, i: number) => K, mapfn: (chunk: T[], key: K, start: number, end: number) => U): U[]; + export function spanMap(array: ReadonlyArray | undefined, keyfn: (x: T, i: number) => K, mapfn: (chunk: T[], key: K, start: number, end: number) => U): U[] | undefined; + export function spanMap(array: ReadonlyArray | undefined, keyfn: (x: T, i: number) => K, mapfn: (chunk: T[], key: K, start: number, end: number) => U): U[] | undefined { + let result: U[] | undefined; if (array) { result = []; const len = array.length; - let previousKey: K; - let key: K; + let previousKey: K | undefined; + let key: K | undefined; let start = 0; let pos = 0; while (start < len) { @@ -660,7 +674,7 @@ namespace ts { } if (start < pos) { - const v = mapfn(array.slice(start, pos), previousKey, start, pos); + const v = mapfn(array.slice(start, pos), previousKey!, start, pos); if (v) { result.push(v); } @@ -676,7 +690,9 @@ namespace ts { return result; } - export function mapEntries(map: ReadonlyMap, f: (key: string, value: T) => [string, U]): Map { + export function mapEntries(map: ReadonlyMap, f: (key: string, value: T) => [string, U]): Map; + export function mapEntries(map: ReadonlyMap | undefined, f: (key: string, value: T) => [string, U]): Map | undefined; + export function mapEntries(map: ReadonlyMap | undefined, f: (key: string, value: T) => [string, U]): Map | undefined { if (!map) { return undefined; } @@ -688,8 +704,9 @@ namespace ts { }); return result; } - - export function some(array: ReadonlyArray, predicate?: (value: T) => boolean): boolean { + export function some(array: ReadonlyArray | undefined): array is ReadonlyArray; + export function some(array: ReadonlyArray | undefined, predicate: (value: T) => boolean): boolean; + export function some(array: ReadonlyArray | undefined, predicate?: (value: T) => boolean): boolean { if (array) { if (predicate) { for (const v of array) { @@ -724,6 +741,8 @@ namespace ts { export function concatenate(array1: T[], array2: T[]): T[]; export function concatenate(array1: ReadonlyArray, array2: ReadonlyArray): ReadonlyArray; + export function concatenate(array1: T[] | undefined, array2: T[] | undefined): T[]; + export function concatenate(array1: ReadonlyArray | undefined, array2: ReadonlyArray | undefined): ReadonlyArray; export function concatenate(array1: T[], array2: T[]): T[] { if (!some(array2)) return array1; if (!some(array1)) return array2; @@ -766,7 +785,9 @@ namespace ts { * @param comparer An optional `Comparer` used to sort entries before comparison, though the * result will remain in the original order in `array`. */ - export function deduplicate(array: ReadonlyArray, equalityComparer: EqualityComparer, comparer?: Comparer): T[] { + export function deduplicate(array: ReadonlyArray, equalityComparer?: EqualityComparer, comparer?: Comparer): T[]; + export function deduplicate(array: ReadonlyArray | undefined, equalityComparer?: EqualityComparer, comparer?: Comparer): T[] | undefined; + export function deduplicate(array: ReadonlyArray | undefined, equalityComparer: EqualityComparer, comparer?: Comparer): T[] | undefined { return !array ? undefined : array.length === 0 ? [] : array.length === 1 ? array.slice() : @@ -777,7 +798,9 @@ namespace ts { /** * Deduplicates an array that has already been sorted. */ - function deduplicateSorted(array: ReadonlyArray, comparer: EqualityComparer | Comparer) { + function deduplicateSorted(array: ReadonlyArray, comparer: EqualityComparer | Comparer): T[]; + function deduplicateSorted(array: ReadonlyArray | undefined, comparer: EqualityComparer | Comparer): T[] | undefined; + function deduplicateSorted(array: ReadonlyArray | undefined, comparer: EqualityComparer | Comparer): T[] | undefined { if (!array) return undefined; if (array.length === 0) return []; @@ -820,7 +843,7 @@ namespace ts { return deduplicateSorted(sort(array, comparer), equalityComparer || comparer); } - export function arrayIsEqualTo(array1: ReadonlyArray, array2: ReadonlyArray, equalityComparer: (a: T, b: T) => boolean = equateValues): boolean { + export function arrayIsEqualTo(array1: ReadonlyArray | undefined, array2: ReadonlyArray | undefined, equalityComparer: (a: T, b: T) => boolean = equateValues): boolean { if (!array1 || !array2) { return array1 === array2; } @@ -863,7 +886,7 @@ namespace ts { export function compact(array: T[]): T[]; export function compact(array: ReadonlyArray): ReadonlyArray; export function compact(array: T[]): T[] { - let result: T[]; + let result: T[] | undefined; if (array) { for (let i = 0; i < array.length; i++) { const v = array[i]; @@ -939,6 +962,9 @@ namespace ts { * @param value The value to append to the array. If `value` is `undefined`, nothing is * appended. */ + export function append(to: T[], value: T | undefined): T[]; + export function append(to: T[] | undefined, value: T): T[]; + export function append(to: T[] | undefined, value: T | undefined): T[] | undefined; export function append(to: T[] | undefined, value: T | undefined): T[] | undefined { if (value === undefined) return to; if (to === undefined) return [value]; @@ -964,6 +990,8 @@ namespace ts { * @param start The offset in `from` at which to start copying values. * @param end The offset in `from` at which to stop copying values (non-inclusive). */ + export function addRange(to: T[], from: ReadonlyArray | undefined, start?: number, end?: number): T[]; + export function addRange(to: T[] | undefined, from: ReadonlyArray | undefined, start?: number, end?: number): T[] | undefined; export function addRange(to: T[] | undefined, from: ReadonlyArray | undefined, start?: number, end?: number): T[] | undefined { if (from === undefined || from.length === 0) return to; if (to === undefined) return from.slice(start, end); @@ -1026,7 +1054,7 @@ namespace ts { /** * Returns a new sorted array. */ - export function sort(array: ReadonlyArray, comparer: Comparer) { + export function sort(array: ReadonlyArray, comparer: Comparer): T[] { return array.slice().sort(comparer); } @@ -1120,7 +1148,7 @@ namespace ts { /** * Returns the only element of an array if it contains only one element, `undefined` otherwise. */ - export function singleOrUndefined(array: ReadonlyArray): T | undefined { + export function singleOrUndefined(array: ReadonlyArray | undefined): T | undefined { return array && array.length === 1 ? array[0] : undefined; @@ -1132,7 +1160,9 @@ namespace ts { */ export function singleOrMany(array: T[]): T | T[]; export function singleOrMany(array: ReadonlyArray): T | ReadonlyArray; - export function singleOrMany(array: T[]): T | T[] { + export function singleOrMany(array: T[] | undefined): T | T[] | undefined; + export function singleOrMany(array: ReadonlyArray | undefined): T | ReadonlyArray | undefined; + export function singleOrMany(array: ReadonlyArray | undefined): T | ReadonlyArray | undefined { return array && array.length === 1 ? array[0] : array; @@ -1181,9 +1211,9 @@ namespace ts { return ~low; } - export function reduceLeft(array: ReadonlyArray, f: (memo: U, value: T, i: number) => U, initial: U, start?: number, count?: number): U; - export function reduceLeft(array: ReadonlyArray, f: (memo: T, value: T, i: number) => T): T; - export function reduceLeft(array: T[], f: (memo: T, value: T, i: number) => T, initial?: T, start?: number, count?: number): T { + export function reduceLeft(array: ReadonlyArray | undefined, f: (memo: U, value: T, i: number) => U, initial: U, start?: number, count?: number): U; + export function reduceLeft(array: ReadonlyArray, f: (memo: T, value: T, i: number) => T): T | undefined; + export function reduceLeft(array: T[], f: (memo: T, value: T, i: number) => T, initial?: T, start?: number, count?: number): T | undefined { if (array && array.length > 0) { const size = array.length; if (size > 0) { @@ -1195,7 +1225,7 @@ namespace ts { pos++; } else { - result = initial; + result = initial!; } while (pos <= end) { result = f(result, array[pos], pos); @@ -1306,11 +1336,11 @@ namespace ts { }); } - export function assign(t: T, ...args: T[]) { + export function assign(t: T, ...args: (T | undefined)[]) { for (const arg of args) { - for (const p in arg) { - if (hasProperty(arg, p)) { - t[p] = arg[p]; + for (const p in arg!) { + if (hasProperty(arg!, p)) { + t![p] = arg![p]; // TODO: GH#23368 } } } @@ -1323,7 +1353,7 @@ namespace ts { * @param left A map-like whose properties should be compared. * @param right A map-like whose properties should be compared. */ - export function equalOwnProperties(left: MapLike, right: MapLike, equalityComparer: EqualityComparer = equateValues) { + export function equalOwnProperties(left: MapLike | undefined, right: MapLike | undefined, equalityComparer: EqualityComparer = equateValues) { if (left === right) return true; if (!left || !right) return false; for (const key in left) { @@ -1503,10 +1533,10 @@ namespace ts { if (value !== undefined && test(value)) return value; if (value && typeof (value as any).kind === "number") { - Debug.fail(`Invalid cast. The supplied ${Debug.showSyntaxKind(value as any as Node)} did not pass the test '${Debug.getFunctionName(test)}'.`); + return Debug.fail(`Invalid cast. The supplied ${Debug.showSyntaxKind(value as any as Node)} did not pass the test '${Debug.getFunctionName(test)}'.`); } else { - Debug.fail(`Invalid cast. The supplied value did not pass the test '${Debug.getFunctionName(test)}'.`); + return Debug.fail(`Invalid cast. The supplied value did not pass the test '${Debug.getFunctionName(test)}'.`); } } @@ -1535,7 +1565,7 @@ namespace ts { return () => { if (callback) { value = callback(); - callback = undefined; + callback = undefined!; } return value; }; @@ -1607,19 +1637,17 @@ namespace ts { } } - export function formatStringFromArgs(text: string, args: ArrayLike, baseIndex?: number): string { - baseIndex = baseIndex || 0; - - return text.replace(/{(\d+)}/g, (_match, index?: string) => Debug.assertDefined(args[+index + baseIndex])); + export function formatStringFromArgs(text: string, args: ArrayLike, baseIndex = 0): string { + return text.replace(/{(\d+)}/g, (_match, index: string) => Debug.assertDefined(args[+index + baseIndex])); } - export let localizedDiagnosticMessages: MapLike; + export let localizedDiagnosticMessages: MapLike | undefined; export function getLocaleSpecificMessage(message: DiagnosticMessage) { return localizedDiagnosticMessages && localizedDiagnosticMessages[message.key] || message.message; } - export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage, ...args: (string | number)[]): DiagnosticWithLocation; + export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage, ...args: (string | number | undefined)[]): DiagnosticWithLocation; export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage): DiagnosticWithLocation { Debug.assertGreaterThanOrEqual(start, 0); Debug.assertGreaterThanOrEqual(length, 0); @@ -1658,7 +1686,7 @@ namespace ts { return text; } - export function createCompilerDiagnostic(message: DiagnosticMessage, ...args: (string | number)[]): Diagnostic; + export function createCompilerDiagnostic(message: DiagnosticMessage, ...args: (string | number | undefined)[]): Diagnostic; export function createCompilerDiagnostic(message: DiagnosticMessage): Diagnostic { let text = getLocaleSpecificMessage(message); @@ -1690,8 +1718,8 @@ namespace ts { }; } - export function chainDiagnosticMessages(details: DiagnosticMessageChain, message: DiagnosticMessage, ...args: string[]): DiagnosticMessageChain; - export function chainDiagnosticMessages(details: DiagnosticMessageChain, message: DiagnosticMessage): DiagnosticMessageChain { + export function chainDiagnosticMessages(details: DiagnosticMessageChain | undefined, message: DiagnosticMessage, ...args: (string | undefined)[]): DiagnosticMessageChain; + export function chainDiagnosticMessages(details: DiagnosticMessageChain | undefined, message: DiagnosticMessage): DiagnosticMessageChain { let text = getLocaleSpecificMessage(message); if (arguments.length > 2) { @@ -1746,9 +1774,9 @@ namespace ts { return equateValues(a, b); } - function compareComparableValues(a: string, b: string): Comparison; - function compareComparableValues(a: number, b: number): Comparison; - function compareComparableValues(a: string | number, b: string | number) { + function compareComparableValues(a: string | undefined, b: string | undefined): Comparison; + function compareComparableValues(a: number | undefined, b: number | undefined): Comparison; + function compareComparableValues(a: string | number | undefined, b: string | number | undefined) { return a === b ? Comparison.EqualTo : a === undefined ? Comparison.LessThan : b === undefined ? Comparison.GreaterThan : @@ -1760,7 +1788,7 @@ namespace ts { * Compare two numeric values for their order relative to each other. * To compare strings, use any of the `compareStrings` functions. */ - export function compareValues(a: number, b: number) { + export function compareValues(a: number | undefined, b: number | undefined): Comparison { return compareComparableValues(a, b); } @@ -1799,7 +1827,7 @@ namespace ts { * Case-sensitive comparisons compare both strings one code-point at a time using the integer * value of each code-point. */ - export function compareStringsCaseSensitive(a: string, b: string) { + export function compareStringsCaseSensitive(a: string | undefined, b: string | undefined): Comparison { return compareComparableValues(a, b); } @@ -1902,7 +1930,7 @@ namespace ts { return uiLocale; } - export function setUILocale(value: string) { + export function setUILocale(value: string | undefined) { if (uiLocale !== value) { uiLocale = value; uiComparerCaseSensitive = undefined; @@ -1924,14 +1952,14 @@ namespace ts { return comparer(a, b); } - export function compareProperties(a: T, b: T, key: K, comparer: Comparer) { + export function compareProperties(a: T | undefined, b: T | undefined, key: K, comparer: Comparer): Comparison { return a === b ? Comparison.EqualTo : a === undefined ? Comparison.LessThan : b === undefined ? Comparison.GreaterThan : comparer(a[key], b[key]); } - function getDiagnosticFilePath(diagnostic: Diagnostic): string { + function getDiagnosticFilePath(diagnostic: Diagnostic): string | undefined { return diagnostic.file ? diagnostic.file.path : undefined; } @@ -1949,7 +1977,9 @@ namespace ts { return compareValues(a ? 1 : 0, b ? 1 : 0); } - function compareMessageText(text1: string | DiagnosticMessageChain, text2: string | DiagnosticMessageChain): Comparison { + function compareMessageText(t1: string | DiagnosticMessageChain, t2: string | DiagnosticMessageChain): Comparison { + let text1: string | DiagnosticMessageChain | undefined = t1; + let text2: string | DiagnosticMessageChain | undefined = t2; while (text1 && text2) { // We still have both chains. const string1 = isString(text1) ? text1 : text1.messageText; @@ -2019,7 +2049,7 @@ namespace ts { export type StrictOptionName = "noImplicitAny" | "noImplicitThis" | "strictNullChecks" | "strictFunctionTypes" | "strictPropertyInitialization" | "alwaysStrict"; export function getStrictOptionValue(compilerOptions: CompilerOptions, flag: StrictOptionName): boolean { - return compilerOptions[flag] === undefined ? compilerOptions.strict : compilerOptions[flag]; + return compilerOptions[flag] === undefined ? !!compilerOptions.strict : !!compilerOptions[flag]; } export function hasZeroOrOneAsteriskCharacter(str: string): boolean { @@ -2298,11 +2328,11 @@ namespace ts { * If the path is relative, the root component is `""`. * If the path is absolute, the root component includes the first path separator (`/`). */ - export function getNormalizedPathComponents(path: string, currentDirectory: string) { + export function getNormalizedPathComponents(path: string, currentDirectory: string | undefined) { return reducePathComponents(getPathComponents(path, currentDirectory)); } - export function getNormalizedAbsolutePath(fileName: string, currentDirectory: string) { + export function getNormalizedAbsolutePath(fileName: string, currentDirectory: string | undefined) { return getPathFromPathComponents(getNormalizedPathComponents(fileName, currentDirectory)); } @@ -2429,7 +2459,7 @@ namespace ts { /** * Combines paths. If a path is absolute, it replaces any previous path. */ - export function combinePaths(path: string, ...paths: string[]): string { + export function combinePaths(path: string, ...paths: (string | undefined)[]): string { if (path) path = normalizeSlashes(path); for (let relativePath of paths) { if (!relativePath) continue; @@ -2448,7 +2478,7 @@ namespace ts { * Combines and resolves paths. If a path is absolute, it replaces any previous path. Any * `.` and `..` path components are resolved. */ - export function resolvePath(path: string, ...paths: string[]): string { + export function resolvePath(path: string, ...paths: (string | undefined)[]): string { const combined = some(paths) ? combinePaths(path, ...paths) : normalizeSlashes(path); const normalized = getPathFromPathComponents(reducePathComponents(getPathComponents(combined))); return normalized && hasTrailingDirectorySeparator(combined) ? ensureTrailingDirectorySeparator(normalized) : normalized; @@ -2657,7 +2687,7 @@ namespace ts { exclude: excludeMatcher }; - export function getRegularExpressionForWildcard(specs: ReadonlyArray, basePath: string, usage: "files" | "directories" | "exclude"): string | undefined { + export function getRegularExpressionForWildcard(specs: ReadonlyArray | undefined, basePath: string, usage: "files" | "directories" | "exclude"): string | undefined { const patterns = getRegularExpressionsForWildcards(specs, basePath, usage); if (!patterns || !patterns.length) { return undefined; @@ -2669,7 +2699,7 @@ namespace ts { return `^(${pattern})${terminator}`; } - function getRegularExpressionsForWildcards(specs: ReadonlyArray, basePath: string, usage: "files" | "directories" | "exclude"): string[] | undefined { + function getRegularExpressionsForWildcards(specs: ReadonlyArray | undefined, basePath: string, usage: "files" | "directories" | "exclude"): string[] | undefined { if (specs === undefined || specs.length === 0) { return undefined; } @@ -2690,7 +2720,7 @@ namespace ts { let subpattern = ""; let hasWrittenComponent = false; const components = getNormalizedPathComponents(spec, basePath); - const lastComponent = lastOrUndefined(components); + const lastComponent = last(components); if (usage !== "exclude" && lastComponent === "**") { return undefined; } @@ -2773,15 +2803,15 @@ namespace ts { export interface FileMatcherPatterns { /** One pattern for each "include" spec. */ - includeFilePatterns: ReadonlyArray; + includeFilePatterns: ReadonlyArray | undefined; /** One pattern matching one of any of the "include" specs. */ - includeFilePattern: string; - includeDirectoryPattern: string; - excludePattern: string; + includeFilePattern: string | undefined; + includeDirectoryPattern: string | undefined; + excludePattern: string | undefined; basePaths: ReadonlyArray; } - export function getFileMatcherPatterns(path: string, excludes: ReadonlyArray, includes: ReadonlyArray, useCaseSensitiveFileNames: boolean, currentDirectory: string): FileMatcherPatterns { + export function getFileMatcherPatterns(path: string, excludes: ReadonlyArray | undefined, includes: ReadonlyArray | undefined, useCaseSensitiveFileNames: boolean, currentDirectory: string): FileMatcherPatterns { path = normalizePath(path); currentDirectory = normalizePath(currentDirectory); const absolutePath = combinePaths(currentDirectory, path); @@ -2795,7 +2825,7 @@ namespace ts { }; } - export function matchFiles(path: string, extensions: ReadonlyArray, excludes: ReadonlyArray, includes: ReadonlyArray, useCaseSensitiveFileNames: boolean, currentDirectory: string, depth: number | undefined, getFileSystemEntries: (path: string) => FileSystemEntries): string[] { + export function matchFiles(path: string, extensions: ReadonlyArray | undefined, excludes: ReadonlyArray | undefined, includes: ReadonlyArray | undefined, useCaseSensitiveFileNames: boolean, currentDirectory: string, depth: number | undefined, getFileSystemEntries: (path: string) => FileSystemEntries): string[] { path = normalizePath(path); currentDirectory = normalizePath(currentDirectory); @@ -2819,7 +2849,7 @@ namespace ts { function visitDirectory(path: string, absolutePath: string, depth: number | undefined) { const { files, directories } = getFileSystemEntries(path); - for (const current of sort(files, compareStringsCaseSensitive)) { + for (const current of sort(files, compareStringsCaseSensitive)) { const name = combinePaths(path, current); const absoluteName = combinePaths(absolutePath, current); if (extensions && !fileExtensionIsOneOf(name, extensions)) continue; @@ -2842,7 +2872,7 @@ namespace ts { } } - for (const current of sort(directories, compareStringsCaseSensitive)) { + for (const current of sort(directories, compareStringsCaseSensitive)) { const name = combinePaths(path, current); const absoluteName = combinePaths(absolutePath, current); if ((!includeDirectoryRegex || includeDirectoryRegex.test(absoluteName)) && @@ -2856,7 +2886,7 @@ namespace ts { /** * Computes the unique non-wildcard base paths amongst the provided include patterns. */ - function getBasePaths(path: string, includes: ReadonlyArray, useCaseSensitiveFileNames: boolean) { + function getBasePaths(path: string, includes: ReadonlyArray | undefined, useCaseSensitiveFileNames: boolean): string[] { // Storage for our results in the form of literal paths (e.g. the paths as written by the user). const basePaths: string[] = [path]; @@ -2946,19 +2976,19 @@ namespace ts { ...mapDefined(extraFileExtensions, x => x.scriptKind === ScriptKind.Deferred || needJsExtensions && isJavaScriptLike(x.scriptKind) ? x.extension : undefined) ]; - return deduplicate(extensions, equateStringsCaseSensitive, compareStringsCaseSensitive); + return deduplicate(extensions, equateStringsCaseSensitive, compareStringsCaseSensitive); } - function isJavaScriptLike(scriptKind: ScriptKind): boolean { + function isJavaScriptLike(scriptKind: ScriptKind | undefined): boolean { return scriptKind === ScriptKind.JS || scriptKind === ScriptKind.JSX; } - export function hasJavaScriptFileExtension(fileName: string) { - return forEach(supportedJavascriptExtensions, extension => fileExtensionIs(fileName, extension)); + export function hasJavaScriptFileExtension(fileName: string): boolean { + return some(supportedJavascriptExtensions, extension => fileExtensionIs(fileName, extension)); } - export function hasTypeScriptFileExtension(fileName: string) { - return forEach(supportedTypeScriptExtensions, extension => fileExtensionIs(fileName, extension)); + export function hasTypeScriptFileExtension(fileName: string): boolean { + return some(supportedTypeScriptExtensions, extension => fileExtensionIs(fileName, extension)); } export function isSupportedSourceFileName(fileName: string, compilerOptions?: CompilerOptions, extraFileExtensions?: ReadonlyArray) { @@ -3079,8 +3109,8 @@ namespace ts { function Symbol(this: Symbol, flags: SymbolFlags, name: __String) { this.flags = flags; this.escapedName = name; - this.declarations = undefined; - this.valueDeclaration = undefined; + this.declarations = undefined!; + this.valueDeclaration = undefined!; this.id = undefined; this.mergeId = undefined; this.parent = undefined; @@ -3103,7 +3133,7 @@ namespace ts { this.flags = NodeFlags.None; this.modifierFlagsCache = ModifierFlags.None; this.transformFlags = TransformFlags.None; - this.parent = undefined; + this.parent = undefined!; this.original = undefined; } @@ -3189,7 +3219,7 @@ namespace ts { } export function assertDefined(value: T | null | undefined, message?: string): T { - assert(value !== undefined && value !== null, message); + if (value === undefined || value === null) return fail(message); return value; } @@ -3224,7 +3254,7 @@ namespace ts { } function showFlags(flags: number, flagsEnum: { [flag: number]: string }): string { - const out = []; + const out: string[] = []; for (let pow = 0; pow <= 30; pow++) { const n = 1 << pow; if (flags & n) { @@ -3375,10 +3405,7 @@ namespace ts { */ export function extensionFromPath(path: string): Extension { const ext = tryGetExtensionFromPath(path); - if (ext !== undefined) { - return ext; - } - Debug.fail(`File ${path} has unknown extension.`); + return ext !== undefined ? ext : Debug.fail(`File ${path} has unknown extension.`); } export function isAnySupportedFileExtension(path: string): boolean { diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index f4d1d85456db1..5e53605decf11 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -15,7 +15,7 @@ namespace ts { export function forEachEmittedFile( host: EmitHost, action: (emitFileNames: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle) => T, sourceFilesOrTargetSourceFile?: ReadonlyArray | SourceFile, - emitOnlyDtsFiles?: boolean) { + emitOnlyDtsFiles = false) { const sourceFiles = isArray(sourceFilesOrTargetSourceFile) ? sourceFilesOrTargetSourceFile : getSourceFilesToEmit(host, sourceFilesOrTargetSourceFile); const options = host.getCompilerOptions(); if (options.outFile || options.out) { @@ -38,14 +38,14 @@ namespace ts { } /*@internal*/ - export function getOutputPathsFor(sourceFile: SourceFile | Bundle, host: EmitHost, forceDtsPaths: boolean) { + export function getOutputPathsFor(sourceFile: SourceFile | Bundle, host: EmitHost, forceDtsPaths: boolean): EmitFileNames { const options = host.getCompilerOptions(); if (sourceFile.kind === SyntaxKind.Bundle) { - const jsFilePath = options.outFile || options.out; + const jsFilePath = options.outFile || options.out!; const sourceMapFilePath = getSourceMapFilePath(jsFilePath, options); const declarationFilePath = (forceDtsPaths || options.declaration) ? removeFileExtension(jsFilePath) + Extension.Dts : undefined; const declarationMapPath = getAreDeclarationMapsEnabled(options) ? declarationFilePath + ".map" : undefined; - const bundleInfoPath = options.references && jsFilePath && (removeFileExtension(jsFilePath) + infoExtension); + const bundleInfoPath = options.references && jsFilePath ? (removeFileExtension(jsFilePath) + infoExtension) : undefined; return { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, bundleInfoPath }; } else { @@ -97,8 +97,8 @@ namespace ts { // targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile, emitOnlyDtsFiles?: boolean, transformers?: TransformerFactory[], declarationTransformers?: TransformerFactory[]): EmitResult { const compilerOptions = host.getCompilerOptions(); - const sourceMapDataList: SourceMapData[] = (compilerOptions.sourceMap || compilerOptions.inlineSourceMap || getAreDeclarationMapsEnabled(compilerOptions)) ? [] : undefined; - const emittedFilesList: string[] = compilerOptions.listEmittedFiles ? [] : undefined; + const sourceMapDataList: SourceMapData[] | undefined = (compilerOptions.sourceMap || compilerOptions.inlineSourceMap || getAreDeclarationMapsEnabled(compilerOptions)) ? [] : undefined; + const emittedFilesList: string[] | undefined = compilerOptions.listEmittedFiles ? [] : undefined; const emitterDiagnostics = createDiagnosticCollection(); const newLine = host.getNewLine(); const writer = createTextWriter(newLine); @@ -124,7 +124,7 @@ namespace ts { emitSkipped, diagnostics: emitterDiagnostics.getDiagnostics(), emittedFiles: emittedFilesList, - sourceMaps: sourceMapDataList + sourceMaps: sourceMapDataList, }; function emitSourceFileOrBundle({ jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, bundleInfoPath }: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle) { @@ -147,7 +147,7 @@ namespace ts { } } - function emitJsFileOrBundle(sourceFileOrBundle: SourceFile | Bundle, jsFilePath: string, sourceMapFilePath: string, bundleInfoPath: string | undefined) { + function emitJsFileOrBundle(sourceFileOrBundle: SourceFile | Bundle, jsFilePath: string, sourceMapFilePath: string | undefined, bundleInfoPath: string | undefined) { // Make sure not to write js file and source map file if any of them cannot be written if (host.isEmitBlocked(jsFilePath) || compilerOptions.noEmit || compilerOptions.emitDeclarationOnly) { emitSkipped = true; @@ -157,7 +157,7 @@ namespace ts { return; } // Transform the source files - const transform = transformNodes(resolver, host, compilerOptions, [sourceFileOrBundle], transformers, /*allowDtsFiles*/ false); + const transform = transformNodes(resolver, host, compilerOptions, [sourceFileOrBundle], transformers!, /*allowDtsFiles*/ false); // Create a printer to print the nodes const printer = createPrinter({ ...compilerOptions, noEmitHelpers: compilerOptions.noEmitHelpers } as PrinterOptions, { @@ -194,7 +194,7 @@ namespace ts { const inputListOrBundle = (compilerOptions.outFile || compilerOptions.out) ? [createBundle(nonJsFiles, !isSourceFile(sourceFileOrBundle) ? sourceFileOrBundle.prepends : undefined)] : nonJsFiles; const declarationTransform = transformNodes(resolver, host, compilerOptions, inputListOrBundle, concatenate([transformDeclarations], declarationTransformers), /*allowDtsFiles*/ false); if (length(declarationTransform.diagnostics)) { - for (const diagnostic of declarationTransform.diagnostics) { + for (const diagnostic of declarationTransform.diagnostics!) { emitterDiagnostics.add(diagnostic); } } @@ -224,14 +224,14 @@ namespace ts { function printSourceFileOrBundle(jsFilePath: string, sourceMapFilePath: string | undefined, sourceFileOrBundle: SourceFile | Bundle, bundleInfoPath: string | undefined, printer: Printer, mapRecorder: SourceMapWriter) { const bundle = sourceFileOrBundle.kind === SyntaxKind.Bundle ? sourceFileOrBundle : undefined; const sourceFile = sourceFileOrBundle.kind === SyntaxKind.SourceFile ? sourceFileOrBundle : undefined; - const sourceFiles = bundle ? bundle.sourceFiles : [sourceFile]; + const sourceFiles = bundle ? bundle.sourceFiles : [sourceFile!]; mapRecorder.initialize(jsFilePath, sourceMapFilePath || "", sourceFileOrBundle, sourceMapDataList); if (bundle) { printer.writeBundle(bundle, writer, bundleInfo); } else { - printer.writeFile(sourceFile, writer); + printer.writeFile(sourceFile!, writer); } writer.writeLine(); @@ -247,7 +247,7 @@ namespace ts { } // Write the output file - writeFile(host, emitterDiagnostics, jsFilePath, writer.getText(), compilerOptions.emitBOM, sourceFiles); + writeFile(host, emitterDiagnostics, jsFilePath, writer.getText(), !!compilerOptions.emitBOM, sourceFiles); // Write bundled offset information if applicable if (bundleInfoPath) { @@ -302,7 +302,7 @@ namespace ts { emitLeadingCommentsOfPosition, } = comments; - let currentSourceFile: SourceFile | undefined; + let currentSourceFile!: SourceFile; let nodeIdToGeneratedName: string[]; // Map of generated names for specific nodes. let autoGeneratedIdToGeneratedName: string[]; // Map of generated names for temp and loop variables. let generatedNames: Map; // Set of names generated by the NameGenerator. @@ -478,8 +478,8 @@ namespace ts { } function setWriter(output: EmitTextWriter | undefined) { - writer = output; - comments.setWriter(output); + writer = output!; // TODO: GH#18217 + comments.setWriter(output!); } function reset() { @@ -544,8 +544,7 @@ namespace ts { } function pipelineEmitWithNotification(hint: EmitHint, node: Node) { - Debug.assertDefined(onEmitNode); - onEmitNode(hint, node, getNextPipelinePhase(PipelinePhase.Notification, hint)); + Debug.assertDefined(onEmitNode)(hint, node, getNextPipelinePhase(PipelinePhase.Notification, hint)); } function pipelineEmitWithComments(hint: EmitHint, node: Node) { @@ -560,9 +559,8 @@ namespace ts { } function pipelineEmitWithSourceMap(hint: EmitHint, node: Node) { - Debug.assertDefined(onEmitSourceMapOfNode); Debug.assert(hint !== EmitHint.SourceFile && hint !== EmitHint.IdentifierName); - onEmitSourceMapOfNode(hint, node, pipelineEmitWithHint); + Debug.assertDefined(onEmitSourceMapOfNode)(hint, node, pipelineEmitWithHint); } function pipelineEmitWithHint(hint: EmitHint, node: Node): void { @@ -1503,7 +1501,7 @@ namespace ts { // check if numeric literal is a decimal literal that was originally written with a dot const text = getLiteralTextOfNode(expression); return !expression.numericLiteralFlags - && !stringContains(text, tokenToString(SyntaxKind.DotToken)); + && !stringContains(text, tokenToString(SyntaxKind.DotToken)!); } else if (isPropertyAccessExpression(expression) || isElementAccessExpression(expression)) { // check if constant enum value is integer @@ -1841,7 +1839,7 @@ namespace ts { emitEmbeddedStatement(node, node.statement); } - function emitForBinding(node: VariableDeclarationList | Expression) { + function emitForBinding(node: VariableDeclarationList | Expression | undefined) { if (node !== undefined) { if (node.kind === SyntaxKind.VariableDeclarationList) { emit(node); @@ -1973,7 +1971,7 @@ namespace ts { writeKeyword("function"); emit(node.asteriskToken); writeSpace(); - emitIdentifierName(node.name); + emitIdentifierName(node.name!); // TODO: GH#18217 emitSignatureAndBody(node, emitSignatureHead); } @@ -2052,7 +2050,7 @@ namespace ts { return false; } - let previousStatement: Statement; + let previousStatement: Statement | undefined; for (const statement of body.statements) { if (shouldWriteSeparatingLineTerminator(previousStatement, statement, ListFormat.PreserveLines)) { return false; @@ -2189,7 +2187,7 @@ namespace ts { while (body.kind === SyntaxKind.ModuleDeclaration) { writePunctuation("."); emit((body).name); - body = (body).body; + body = (body).body!; } writeSpace(); @@ -2406,7 +2404,7 @@ namespace ts { function emitJsxAttribute(node: JsxAttribute) { emit(node.name); - emitNodeWithPrefix("=", writePunctuation, node.initializer, emit); + emitNodeWithPrefix("=", writePunctuation, node.initializer!, emit); // TODO: GH#18217 } function emitJsxSpreadAttribute(node: JsxSpreadAttribute) { @@ -2562,7 +2560,7 @@ namespace ts { } function emitSyntheticTripleSlashReferencesIfNeeded(node: Bundle) { - emitTripleSlashDirectives(node.hasNoDefaultLib, node.syntheticFileReferences || [], node.syntheticTypeReferences || []); + emitTripleSlashDirectives(!!node.hasNoDefaultLib, node.syntheticFileReferences || [], node.syntheticTypeReferences || []); } function emitTripleSlashDirectivesIfNeeded(node: SourceFile) { @@ -2693,7 +2691,7 @@ namespace ts { write = savedWrite; } - function emitModifiers(node: Node, modifiers: NodeArray) { + function emitModifiers(node: Node, modifiers: NodeArray | undefined) { if (modifiers && modifiers.length) { emitList(node, modifiers, ListFormat.Modifiers); writeSpace(); @@ -2758,15 +2756,15 @@ namespace ts { } } - function emitDecorators(parentNode: Node, decorators: NodeArray) { + function emitDecorators(parentNode: Node, decorators: NodeArray | undefined) { emitList(parentNode, decorators, ListFormat.Decorators); } - function emitTypeArguments(parentNode: Node, typeArguments: NodeArray) { + function emitTypeArguments(parentNode: Node, typeArguments: NodeArray | undefined) { emitList(parentNode, typeArguments, ListFormat.TypeArguments); } - function emitTypeParameters(parentNode: SignatureDeclaration | InterfaceDeclaration | TypeAliasDeclaration | ClassDeclaration | ClassExpression, typeParameters: NodeArray) { + function emitTypeParameters(parentNode: SignatureDeclaration | InterfaceDeclaration | TypeAliasDeclaration | ClassDeclaration | ClassExpression, typeParameters: NodeArray | undefined) { if (isFunctionLike(parentNode) && parentNode.typeArguments) { // Quick info uses type arguments in place of type parameters on instantiated signatures return emitTypeArguments(parentNode, parentNode.typeArguments); } @@ -2807,12 +2805,12 @@ namespace ts { emitList(parentNode, parameters, ListFormat.IndexSignatureParameters); } - function emitList(parentNode: TextRange, children: NodeArray, format: ListFormat, start?: number, count?: number) { + function emitList(parentNode: TextRange, children: NodeArray | undefined, format: ListFormat, start?: number, count?: number) { emitNodeList(emit, parentNode, children, format, start, count); } - function emitExpressionList(parentNode: TextRange, children: NodeArray, format: ListFormat, start?: number, count?: number) { - emitNodeList(emitExpression, parentNode, children, format, start, count); + function emitExpressionList(parentNode: TextRange, children: NodeArray | undefined, format: ListFormat, start?: number, count?: number) { + emitNodeList(emitExpression as (node: Node) => void, parentNode, children, format, start, count); // TODO: GH#18217 } function writeDelimiter(format: ListFormat) { @@ -2833,13 +2831,13 @@ namespace ts { } } - function emitNodeList(emit: (node: Node) => void, parentNode: TextRange, children: NodeArray, format: ListFormat, start = 0, count = children ? children.length - start : 0) { + function emitNodeList(emit: (node: Node) => void, parentNode: TextRange, children: NodeArray | undefined, format: ListFormat, start = 0, count = children ? children.length - start : 0) { const isUndefined = children === undefined; if (isUndefined && format & ListFormat.OptionalIfUndefined) { return; } - const isEmpty = isUndefined || start >= children.length || count === 0; + const isEmpty = children === undefined || start >= children.length || count === 0; if (isEmpty && format & ListFormat.OptionalIfEmpty) { if (onBeforeEmitNodeArray) { onBeforeEmitNodeArray(children); @@ -2853,7 +2851,8 @@ namespace ts { if (format & ListFormat.BracketsMask) { writePunctuation(getOpeningBracket(format)); if (isEmpty && !isUndefined) { - emitTrailingCommentsOfPosition(children.pos, /*prefixSpace*/ true); // Emit comments within empty bracketed lists + // TODO: GH#18217 + emitTrailingCommentsOfPosition(children!.pos, /*prefixSpace*/ true); // Emit comments within empty bracketed lists } } @@ -2874,7 +2873,7 @@ namespace ts { // Write the opening line terminator or leading whitespace. const mayEmitInterveningComments = (format & ListFormat.NoInterveningComments) === 0; let shouldEmitInterveningComments = mayEmitInterveningComments; - if (shouldWriteLeadingLineTerminator(parentNode, children, format)) { + if (shouldWriteLeadingLineTerminator(parentNode, children!, format)) { // TODO: GH#18217 writeLine(); shouldEmitInterveningComments = false; } @@ -2888,10 +2887,10 @@ namespace ts { } // Emit each child. - let previousSibling: Node; - let shouldDecreaseIndentAfterEmit: boolean; + let previousSibling: Node | undefined; + let shouldDecreaseIndentAfterEmit = false; for (let i = 0; i < count; i++) { - const child = children[start + i]; + const child = children![start + i]; // Write the delimiter if this is not the first node. if (previousSibling) { @@ -2945,7 +2944,7 @@ namespace ts { } // Write a trailing comma, if requested. - const hasTrailingComma = (format & ListFormat.AllowTrailingComma) && children.hasTrailingComma; + const hasTrailingComma = (format & ListFormat.AllowTrailingComma) && children!.hasTrailingComma; if (format & ListFormat.CommaDelimited && hasTrailingComma) { writePunctuation(","); } @@ -2967,7 +2966,7 @@ namespace ts { } // Write the closing line terminator or closing whitespace. - if (shouldWriteClosingLineTerminator(parentNode, children, format)) { + if (shouldWriteClosingLineTerminator(parentNode, children!, format)) { writeLine(); } else if (format & ListFormat.SpaceBetweenBraces) { @@ -2981,7 +2980,8 @@ namespace ts { if (format & ListFormat.BracketsMask) { if (isEmpty && !isUndefined) { - emitLeadingCommentsOfPosition(children.end); // Emit leading comments within empty lists + // TODO: GH#18217 + emitLeadingCommentsOfPosition(children!.end); // Emit leading comments within empty lists } writePunctuation(getClosingBracket(format)); } @@ -3077,16 +3077,18 @@ namespace ts { if (onBeforeEmitToken) { onBeforeEmitToken(node); } - writer(tokenToString(node.kind)); + writer(tokenToString(node.kind)!); if (onAfterEmitToken) { onAfterEmitToken(node); } } - function writeTokenText(token: SyntaxKind, writer: (s: string) => void, pos?: number) { - const tokenString = tokenToString(token); + function writeTokenText(token: SyntaxKind, writer: (s: string) => void): void; + function writeTokenText(token: SyntaxKind, writer: (s: string) => void, pos: number): number; + function writeTokenText(token: SyntaxKind, writer: (s: string) => void, pos?: number): number { + const tokenString = tokenToString(token)!; writer(tokenString); - return pos < 0 ? pos : pos + tokenString.length; + return pos! < 0 ? pos! : pos! + tokenString.length; } function writeLineOrSpace(node: Node) { @@ -3160,7 +3162,7 @@ namespace ts { } } - function shouldWriteSeparatingLineTerminator(previousNode: Node, nextNode: Node, format: ListFormat) { + function shouldWriteSeparatingLineTerminator(previousNode: Node | undefined, nextNode: Node, format: ListFormat) { if (format & ListFormat.MultiLine) { return true; } @@ -3205,7 +3207,7 @@ namespace ts { } } - function synthesizedNodeStartsOnNewLine(node: Node, format?: ListFormat) { + function synthesizedNodeStartsOnNewLine(node: Node, format: ListFormat) { if (nodeIsSynthesized(node)) { const startsOnNewLine = getStartsOnNewLine(node); if (startsOnNewLine === undefined) { @@ -3255,7 +3257,7 @@ namespace ts { return idText(node); } else if (node.kind === SyntaxKind.StringLiteral && (node).textSourceNode) { - return getTextOfNode((node).textSourceNode, includeTrivia); + return getTextOfNode((node).textSourceNode!, includeTrivia); } else if (isLiteralExpression(node) && (nodeIsSynthesized(node) || !node.parent)) { return node.text; @@ -3266,7 +3268,7 @@ namespace ts { function getLiteralTextOfNode(node: LiteralLikeNode): string { if (node.kind === SyntaxKind.StringLiteral && (node).textSourceNode) { - const textSourceNode = (node).textSourceNode; + const textSourceNode = (node).textSourceNode!; if (isIdentifier(textSourceNode)) { return getEmitFlags(node) & EmitFlags.NoAsciiEscaping ? `"${escapeString(getTextOfNode(textSourceNode))}"` : @@ -3299,8 +3301,8 @@ namespace ts { if (node && getEmitFlags(node) & EmitFlags.ReuseTempVariableScope) { return; } - tempFlags = tempFlagsStack.pop(); - reservedNames = reservedNamesStack.pop(); + tempFlags = tempFlagsStack.pop()!; + reservedNames = reservedNamesStack.pop()!; } function reserveNameInNestedScopes(name: string) { @@ -3430,7 +3432,7 @@ namespace ts { else { // Auto, Loop, and Unique names are cached based on their unique // autoGenerateId. - const autoGenerateId = name.autoGenerateId; + const autoGenerateId = name.autoGenerateId!; return autoGeneratedIdToGeneratedName[autoGenerateId] || (autoGeneratedIdToGeneratedName[autoGenerateId] = makeName(name)); } } @@ -3461,7 +3463,7 @@ namespace ts { * Returns a value indicating whether a name is unique within a container. */ function isUniqueLocalName(name: string, container: Node): boolean { - for (let node = container; isNodeDescendantOf(node, container); node = node.nextContainer) { + for (let node = container; isNodeDescendantOf(node, container); node = node.nextContainer!) { if (node.locals) { const local = node.locals.get(escapeLeadingUnderscores(name)); // We conservatively include alias symbols to cover cases where they're emitted as locals @@ -3563,7 +3565,7 @@ namespace ts { * Generates a unique name for an ImportDeclaration or ExportDeclaration. */ function generateNameForImportOrExportDeclaration(node: ImportDeclaration | ExportDeclaration) { - const expr = getExternalModuleName(node); + const expr = getExternalModuleName(node)!; // TODO: GH#18217 const baseName = isStringLiteral(expr) ? makeIdentifierFromModuleName(expr.text) : "module"; return makeUniqueName(baseName); @@ -3599,8 +3601,8 @@ namespace ts { return makeUniqueName( getTextOfNode(node), isUniqueName, - !!(flags & GeneratedIdentifierFlags.Optimistic), - !!(flags & GeneratedIdentifierFlags.ReservedInNestedScopes) + !!(flags! & GeneratedIdentifierFlags.Optimistic), + !!(flags! & GeneratedIdentifierFlags.ReservedInNestedScopes) ); case SyntaxKind.ModuleDeclaration: case SyntaxKind.EnumDeclaration: @@ -3641,7 +3643,7 @@ namespace ts { ); } - Debug.fail("Unsupported GeneratedIdentifierKind."); + return Debug.fail("Unsupported GeneratedIdentifierKind."); } /** @@ -3657,7 +3659,7 @@ namespace ts { // if "node" is a different generated name (having a different // "autoGenerateId"), use it and stop traversing. if (isIdentifier(node) - && !!(node.autoGenerateFlags & GeneratedIdentifierFlags.Node) + && !!(node.autoGenerateFlags! & GeneratedIdentifierFlags.Node) && node.autoGenerateId !== autoGenerateId) { break; } diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 489bc72db621f..6085cc550c46c 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -39,13 +39,13 @@ namespace ts { * Creates a shallow, memberwise clone of a node with no source map location. */ /* @internal */ - export function getSynthesizedClone(node: T | undefined): T | undefined { + export function getSynthesizedClone(node: T): T { // We don't use "clone" from core.ts here, as we need to preserve the prototype chain of // the original node. We also need to exclude specific properties and only include own- // properties (to skip members already defined on the shared prototype). if (node === undefined) { - return undefined; + return node; } const clone = createSynthesizedNode(node.kind); @@ -116,7 +116,7 @@ namespace ts { export function createIdentifier(text: string): Identifier; /* @internal */ - export function createIdentifier(text: string, typeArguments: ReadonlyArray): Identifier; // tslint:disable-line unified-signatures + export function createIdentifier(text: string, typeArguments: ReadonlyArray | undefined): Identifier; // tslint:disable-line unified-signatures export function createIdentifier(text: string, typeArguments?: ReadonlyArray): Identifier { const node = createSynthesizedNode(SyntaxKind.Identifier); node.escapedText = escapeLeadingUnderscores(text); @@ -142,9 +142,9 @@ namespace ts { /** Create a unique temporary variable. */ export function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined): Identifier; - /* @internal */ export function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined, reservedInNestedScopes: boolean): Identifier; // tslint:disable-line unified-signatures - export function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined, reservedInNestedScopes?: boolean): Identifier { - const name = createIdentifier(""); + /* @internal */ export function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined, reservedInNestedScopes: boolean): GeneratedIdentifier; // tslint:disable-line unified-signatures + export function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined, reservedInNestedScopes?: boolean): GeneratedIdentifier { + const name = createIdentifier("") as GeneratedIdentifier; name.autoGenerateFlags = GeneratedIdentifierFlags.Auto; name.autoGenerateId = nextAutoGenerateId; nextAutoGenerateId++; @@ -175,9 +175,11 @@ namespace ts { return name; } + /* @internal */ export function createOptimisticUniqueName(text: string): GeneratedIdentifier; /** Create a unique name based on the supplied text. */ - export function createOptimisticUniqueName(text: string): Identifier { - const name = createIdentifier(text); + export function createOptimisticUniqueName(text: string): Identifier; + export function createOptimisticUniqueName(text: string): GeneratedIdentifier { + const name = createIdentifier(text) as GeneratedIdentifier; name.autoGenerateFlags = GeneratedIdentifierFlags.Unique | GeneratedIdentifierFlags.Optimistic; name.autoGenerateId = nextAutoGenerateId; nextAutoGenerateId++; @@ -196,7 +198,7 @@ namespace ts { /* @internal */ export function getGeneratedNameForNode(node: Node, flags: GeneratedIdentifierFlags): Identifier; // tslint:disable-line unified-signatures export function getGeneratedNameForNode(node: Node, flags?: GeneratedIdentifierFlags): Identifier { const name = createIdentifier(isIdentifier(node) ? idText(node) : ""); - name.autoGenerateFlags = GeneratedIdentifierFlags.Node | flags; + name.autoGenerateFlags = GeneratedIdentifierFlags.Node | flags!; name.autoGenerateId = nextAutoGenerateId; name.original = node; nextAutoGenerateId++; @@ -713,7 +715,7 @@ namespace ts { : node; } - export function createTypeLiteralNode(members: ReadonlyArray) { + export function createTypeLiteralNode(members: ReadonlyArray | undefined) { const node = createSynthesizedNode(SyntaxKind.TypeLiteral) as TypeLiteralNode; node.members = createNodeArray(members); return node; @@ -846,7 +848,7 @@ namespace ts { export function createTypeOperatorNode(operatorOrType: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | TypeNode, type?: TypeNode) { const node = createSynthesizedNode(SyntaxKind.TypeOperator) as TypeOperatorNode; node.operator = typeof operatorOrType === "number" ? operatorOrType : SyntaxKind.KeyOfKeyword; - node.type = parenthesizeElementTypeMember(typeof operatorOrType === "number" ? type : operatorOrType); + node.type = parenthesizeElementTypeMember(typeof operatorOrType === "number" ? type! : operatorOrType); return node; } @@ -970,10 +972,10 @@ namespace ts { : node; } - export function createPropertyAccess(expression: Expression, name: string | Identifier) { + export function createPropertyAccess(expression: Expression, name: string | Identifier | undefined) { const node = createSynthesizedNode(SyntaxKind.PropertyAccessExpression); node.expression = parenthesizeForAccess(expression); - node.name = asName(name); + node.name = asName(name)!; // TODO: GH#18217 setEmitFlags(node, EmitFlags.NoIndentation); return node; } @@ -1001,7 +1003,7 @@ namespace ts { : node; } - export function createCall(expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray) { + export function createCall(expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray | undefined) { const node = createSynthesizedNode(SyntaxKind.CallExpression); node.expression = parenthesizeForAccess(expression); node.typeArguments = asNodeArray(typeArguments); @@ -1034,15 +1036,15 @@ namespace ts { } export function createTaggedTemplate(tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; - export function createTaggedTemplate(tag: Expression, typeArguments: ReadonlyArray, template: TemplateLiteral): TaggedTemplateExpression; + export function createTaggedTemplate(tag: Expression, typeArguments: ReadonlyArray | undefined, template: TemplateLiteral): TaggedTemplateExpression; /** @internal */ - export function createTaggedTemplate(tag: Expression, typeArgumentsOrTemplate: ReadonlyArray | TemplateLiteral, template?: TemplateLiteral): TaggedTemplateExpression; - export function createTaggedTemplate(tag: Expression, typeArgumentsOrTemplate: ReadonlyArray | TemplateLiteral, template?: TemplateLiteral) { + export function createTaggedTemplate(tag: Expression, typeArgumentsOrTemplate: ReadonlyArray | TemplateLiteral | undefined, template?: TemplateLiteral): TaggedTemplateExpression; + export function createTaggedTemplate(tag: Expression, typeArgumentsOrTemplate: ReadonlyArray | TemplateLiteral | undefined, template?: TemplateLiteral) { const node = createSynthesizedNode(SyntaxKind.TaggedTemplateExpression); node.tag = parenthesizeForAccess(tag); if (template) { node.typeArguments = asNodeArray(typeArgumentsOrTemplate as ReadonlyArray); - node.template = template!; + node.template = template; } else { node.typeArguments = undefined; @@ -1052,8 +1054,8 @@ namespace ts { } export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; - export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: ReadonlyArray, template: TemplateLiteral): TaggedTemplateExpression; - export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArgumentsOrTemplate: ReadonlyArray | TemplateLiteral, template?: TemplateLiteral) { + export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: ReadonlyArray | undefined, template: TemplateLiteral): TaggedTemplateExpression; + export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArgumentsOrTemplate: ReadonlyArray | TemplateLiteral | undefined, template?: TemplateLiteral) { return node.tag !== tag || (template ? node.typeArguments !== typeArgumentsOrTemplate || node.template !== template @@ -1093,7 +1095,7 @@ namespace ts { asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: ReadonlyArray | undefined, - parameters: ReadonlyArray, + parameters: ReadonlyArray | undefined, type: TypeNode | undefined, body: Block) { const node = createSynthesizedNode(SyntaxKind.FunctionExpression); @@ -1288,7 +1290,7 @@ namespace ts { node.condition = parenthesizeForConditionalHead(condition); node.questionToken = whenFalse ? questionTokenOrWhenTrue : createToken(SyntaxKind.QuestionToken); node.whenTrue = parenthesizeSubexpressionOfConditionalExpression(whenFalse ? whenTrueOrWhenFalse : questionTokenOrWhenTrue); - node.colonToken = whenFalse ? colonToken : createToken(SyntaxKind.ColonToken); + node.colonToken = whenFalse ? colonToken! : createToken(SyntaxKind.ColonToken); node.whenFalse = parenthesizeSubexpressionOfConditionalExpression(whenFalse ? whenFalse : whenTrueOrWhenFalse); return node; } @@ -1360,8 +1362,8 @@ namespace ts { } export function createYield(expression?: Expression): YieldExpression; - export function createYield(asteriskToken: AsteriskToken, expression: Expression): YieldExpression; - export function createYield(asteriskTokenOrExpression?: AsteriskToken | Expression, expression?: Expression) { + export function createYield(asteriskToken: AsteriskToken | undefined, expression: Expression): YieldExpression; + export function createYield(asteriskTokenOrExpression?: AsteriskToken | undefined | Expression, expression?: Expression) { const node = createSynthesizedNode(SyntaxKind.YieldExpression); node.asteriskToken = asteriskTokenOrExpression && asteriskTokenOrExpression.kind === SyntaxKind.AsteriskToken ? asteriskTokenOrExpression : undefined; node.expression = asteriskTokenOrExpression && asteriskTokenOrExpression.kind !== SyntaxKind.AsteriskToken ? asteriskTokenOrExpression : expression; @@ -1391,7 +1393,7 @@ namespace ts { modifiers: ReadonlyArray | undefined, name: string | Identifier | undefined, typeParameters: ReadonlyArray | undefined, - heritageClauses: ReadonlyArray, + heritageClauses: ReadonlyArray | undefined, members: ReadonlyArray) { const node = createSynthesizedNode(SyntaxKind.ClassExpression); node.decorators = undefined; @@ -1408,7 +1410,7 @@ namespace ts { modifiers: ReadonlyArray | undefined, name: Identifier | undefined, typeParameters: ReadonlyArray | undefined, - heritageClauses: ReadonlyArray, + heritageClauses: ReadonlyArray | undefined, members: ReadonlyArray) { return node.modifiers !== modifiers || node.name !== name @@ -1423,14 +1425,14 @@ namespace ts { return createSynthesizedNode(SyntaxKind.OmittedExpression); } - export function createExpressionWithTypeArguments(typeArguments: ReadonlyArray, expression: Expression) { + export function createExpressionWithTypeArguments(typeArguments: ReadonlyArray | undefined, expression: Expression) { const node = createSynthesizedNode(SyntaxKind.ExpressionWithTypeArguments); node.expression = parenthesizeForAccess(expression); node.typeArguments = asNodeArray(typeArguments); return node; } - export function updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, typeArguments: ReadonlyArray, expression: Expression) { + export function updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, typeArguments: ReadonlyArray | undefined, expression: Expression) { return node.typeArguments !== typeArguments || node.expression !== expression ? updateNode(createExpressionWithTypeArguments(typeArguments, expression), node) @@ -1625,7 +1627,7 @@ namespace ts { : node; } - export function createForOf(awaitModifier: AwaitKeywordToken, initializer: ForInitializer, expression: Expression, statement: Statement) { + export function createForOf(awaitModifier: AwaitKeywordToken | undefined, initializer: ForInitializer, expression: Expression, statement: Statement) { const node = createSynthesizedNode(SyntaxKind.ForOfStatement); node.awaitModifier = awaitModifier; node.initializer = initializer; @@ -1634,7 +1636,7 @@ namespace ts { return node; } - export function updateForOf(node: ForOfStatement, awaitModifier: AwaitKeywordToken, initializer: ForInitializer, expression: Expression, statement: Statement) { + export function updateForOf(node: ForOfStatement, awaitModifier: AwaitKeywordToken | undefined, initializer: ForInitializer, expression: Expression, statement: Statement) { return node.awaitModifier !== awaitModifier || node.initializer !== initializer || node.expression !== expression @@ -1769,7 +1771,7 @@ namespace ts { : node; } - export function createVariableDeclarationList(declarations: ReadonlyArray, flags?: NodeFlags) { + export function createVariableDeclarationList(declarations: ReadonlyArray, flags = NodeFlags.None) { const node = createSynthesizedNode(SyntaxKind.VariableDeclarationList); node.flags |= flags & NodeFlags.BlockScoped; node.declarations = createNodeArray(declarations); @@ -1830,7 +1832,7 @@ namespace ts { modifiers: ReadonlyArray | undefined, name: string | Identifier | undefined, typeParameters: ReadonlyArray | undefined, - heritageClauses: ReadonlyArray, + heritageClauses: ReadonlyArray | undefined, members: ReadonlyArray) { const node = createSynthesizedNode(SyntaxKind.ClassDeclaration); node.decorators = asNodeArray(decorators); @@ -1848,7 +1850,7 @@ namespace ts { modifiers: ReadonlyArray | undefined, name: Identifier | undefined, typeParameters: ReadonlyArray | undefined, - heritageClauses: ReadonlyArray, + heritageClauses: ReadonlyArray | undefined, members: ReadonlyArray) { return node.decorators !== decorators || node.modifiers !== modifiers @@ -1953,7 +1955,7 @@ namespace ts { : node; } - export function createModuleDeclaration(decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, name: ModuleName, body: ModuleBody | undefined, flags?: NodeFlags) { + export function createModuleDeclaration(decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, name: ModuleName, body: ModuleBody | undefined, flags = NodeFlags.None) { const node = createSynthesizedNode(SyntaxKind.ModuleDeclaration); node.flags |= flags & (NodeFlags.Namespace | NodeFlags.NestedNamespace | NodeFlags.GlobalAugmentation); node.decorators = asNodeArray(decorators); @@ -2044,7 +2046,7 @@ namespace ts { decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, importClause: ImportClause | undefined, - moduleSpecifier: Expression | undefined) { + moduleSpecifier: Expression) { return node.decorators !== decorators || node.modifiers !== modifiers || node.importClause !== importClause @@ -2105,7 +2107,7 @@ namespace ts { : node; } - export function createExportAssignment(decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, isExportEquals: boolean, expression: Expression) { + export function createExportAssignment(decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, isExportEquals: boolean | undefined, expression: Expression) { const node = createSynthesizedNode(SyntaxKind.ExportAssignment); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); @@ -2402,7 +2404,7 @@ namespace ts { export function createSpreadAssignment(expression: Expression) { const node = createSynthesizedNode(SyntaxKind.SpreadAssignment); - node.expression = expression !== undefined ? parenthesizeExpressionForList(expression) : undefined; + node.expression = expression !== undefined ? parenthesizeExpressionForList(expression) : undefined!; // TODO: GH#18217 return node; } @@ -2512,7 +2514,7 @@ namespace ts { /* @internal */ export function createEndOfDeclarationMarker(original: Node) { const node = createSynthesizedNode(SyntaxKind.EndOfDeclarationMarker); - node.emitNode = {}; + node.emitNode = {} as EmitNode; node.original = original; return node; } @@ -2524,7 +2526,7 @@ namespace ts { /* @internal */ export function createMergeDeclarationMarker(original: Node) { const node = createSynthesizedNode(SyntaxKind.MergeDeclarationMarker); - node.emitNode = {}; + node.emitNode = {} as EmitNode; node.original = original; return node; } @@ -2701,12 +2703,7 @@ namespace ts { // Utilities - function asName(name: string | Identifier): Identifier; - function asName(name: string | BindingName): BindingName; - function asName(name: string | PropertyName): PropertyName; - function asName(name: string | EntityName): EntityName; - function asName(name: string | Identifier | ThisTypeNode): Identifier | ThisTypeNode; - function asName(name: string | Identifier | BindingName | PropertyName | QualifiedName | ThisTypeNode) { + function asName(name: string | T): T | Identifier { return isString(name) ? createIdentifier(name) : name; } @@ -2714,6 +2711,8 @@ namespace ts { return isString(value) || typeof value === "number" ? createLiteral(value) : value; } + function asNodeArray(array: ReadonlyArray): NodeArray; + function asNodeArray(array: ReadonlyArray | undefined): NodeArray | undefined; function asNodeArray(array: ReadonlyArray | undefined): NodeArray | undefined { return array ? createNodeArray(array) : undefined; } @@ -2748,21 +2747,21 @@ namespace ts { * various transient transformation properties. */ /* @internal */ - export function getOrCreateEmitNode(node: Node) { + export function getOrCreateEmitNode(node: Node): EmitNode { if (!node.emitNode) { if (isParseTreeNode(node)) { // To avoid holding onto transformation artifacts, we keep track of any // parse tree node we are annotating. This allows us to clean them up after // all transformations have completed. if (node.kind === SyntaxKind.SourceFile) { - return node.emitNode = { annotatedNodes: [node] }; + return node.emitNode = { annotatedNodes: [node] } as EmitNode; } const sourceFile = getSourceFileOfNode(node); - getOrCreateEmitNode(sourceFile).annotatedNodes.push(node); + getOrCreateEmitNode(sourceFile).annotatedNodes!.push(node); } - node.emitNode = {}; + node.emitNode = {} as EmitNode; } return node.emitNode; @@ -2878,7 +2877,7 @@ namespace ts { return emitNode && emitNode.leadingComments; } - export function setSyntheticLeadingComments(node: T, comments: SynthesizedComment[]) { + export function setSyntheticLeadingComments(node: T, comments: SynthesizedComment[] | undefined) { getOrCreateEmitNode(node).leadingComments = comments; return node; } @@ -2892,7 +2891,7 @@ namespace ts { return emitNode && emitNode.trailingComments; } - export function setSyntheticTrailingComments(node: T, comments: SynthesizedComment[]) { + export function setSyntheticTrailingComments(node: T, comments: SynthesizedComment[] | undefined) { getOrCreateEmitNode(node).trailingComments = comments; return node; } @@ -2913,7 +2912,7 @@ namespace ts { /** * Gets the constant value to emit for an expression. */ - export function getConstantValue(node: PropertyAccessExpression | ElementAccessExpression) { + export function getConstantValue(node: PropertyAccessExpression | ElementAccessExpression): string | number | undefined { const emitNode = node.emitNode; return emitNode && emitNode.constantValue; } @@ -3015,7 +3014,7 @@ namespace ts { return node; } - function mergeEmitNode(sourceEmitNode: EmitNode, destEmitNode: EmitNode) { + function mergeEmitNode(sourceEmitNode: EmitNode, destEmitNode: EmitNode | undefined) { const { flags, leadingComments, @@ -3027,21 +3026,21 @@ namespace ts { helpers, startsOnNewLine, } = sourceEmitNode; - if (!destEmitNode) destEmitNode = {}; + if (!destEmitNode) destEmitNode = {} as EmitNode; // We are using `.slice()` here in case `destEmitNode.leadingComments` is pushed to later. if (leadingComments) destEmitNode.leadingComments = addRange(leadingComments.slice(), destEmitNode.leadingComments); if (trailingComments) destEmitNode.trailingComments = addRange(trailingComments.slice(), destEmitNode.trailingComments); if (flags) destEmitNode.flags = flags; if (commentRange) destEmitNode.commentRange = commentRange; if (sourceMapRange) destEmitNode.sourceMapRange = sourceMapRange; - if (tokenSourceMapRanges) destEmitNode.tokenSourceMapRanges = mergeTokenSourceMapRanges(tokenSourceMapRanges, destEmitNode.tokenSourceMapRanges); + if (tokenSourceMapRanges) destEmitNode.tokenSourceMapRanges = mergeTokenSourceMapRanges(tokenSourceMapRanges, destEmitNode.tokenSourceMapRanges!); if (constantValue !== undefined) destEmitNode.constantValue = constantValue; if (helpers) destEmitNode.helpers = addRange(destEmitNode.helpers, helpers); if (startsOnNewLine !== undefined) destEmitNode.startsOnNewLine = startsOnNewLine; return destEmitNode; } - function mergeTokenSourceMapRanges(sourceRanges: TextRange[], destRanges: TextRange[]) { + function mergeTokenSourceMapRanges(sourceRanges: (TextRange | undefined)[], destRanges: (TextRange | undefined)[]) { if (!destRanges) destRanges = []; for (const key in sourceRanges) { destRanges[key] = sourceRanges[key]; @@ -3178,7 +3177,7 @@ namespace ts { } } - function createJsxFactoryExpression(jsxFactoryEntity: EntityName, reactNamespace: string, parent: JsxOpeningLikeElement | JsxOpeningFragment): Expression { + function createJsxFactoryExpression(jsxFactoryEntity: EntityName | undefined, reactNamespace: string, parent: JsxOpeningLikeElement | JsxOpeningFragment): Expression { return jsxFactoryEntity ? createJsxFactoryExpressionFromEntityName(jsxFactoryEntity, parent) : createPropertyAccess( @@ -3187,7 +3186,7 @@ namespace ts { ); } - export function createExpressionForJsxElement(jsxFactoryEntity: EntityName, reactNamespace: string, tagName: Expression, props: Expression, children: ReadonlyArray, parentElement: JsxOpeningLikeElement, location: TextRange): LeftHandSideExpression { + export function createExpressionForJsxElement(jsxFactoryEntity: EntityName | undefined, reactNamespace: string, tagName: Expression, props: Expression, children: ReadonlyArray, parentElement: JsxOpeningLikeElement, location: TextRange): LeftHandSideExpression { const argumentsList = [tagName]; if (props) { argumentsList.push(props); @@ -3219,7 +3218,7 @@ namespace ts { ); } - export function createExpressionForJsxFragment(jsxFactoryEntity: EntityName, reactNamespace: string, children: ReadonlyArray, parentElement: JsxOpeningFragment, location: TextRange): LeftHandSideExpression { + export function createExpressionForJsxFragment(jsxFactoryEntity: EntityName | undefined, reactNamespace: string, children: ReadonlyArray, parentElement: JsxOpeningFragment, location: TextRange): LeftHandSideExpression { const tagName = createPropertyAccess( createReactNamespace(reactNamespace, parentElement), "Fragment" @@ -3347,7 +3346,7 @@ namespace ts { export function createForOfBindingStatement(node: ForInitializer, boundValue: Expression): Statement { if (isVariableDeclarationList(node)) { - const firstDeclaration = firstOrUndefined(node.declarations); + const firstDeclaration = first(node.declarations); const updatedDeclaration = updateVariableDeclaration( firstDeclaration, firstDeclaration.name, @@ -3377,7 +3376,7 @@ namespace ts { } } - export function restoreEnclosingLabel(node: Statement, outermostLabeledStatement: LabeledStatement, afterRestoreLabelCallback?: (node: LabeledStatement) => void): Statement { + export function restoreEnclosingLabel(node: Statement, outermostLabeledStatement: LabeledStatement | undefined, afterRestoreLabelCallback?: (node: LabeledStatement) => void): Statement { if (!outermostLabeledStatement) { return node; } @@ -3421,7 +3420,7 @@ namespace ts { } } - export function createCallBinding(expression: Expression, recordTempVariable: (temp: Identifier) => void, languageVersion?: ScriptTarget, cacheIdentifiers?: boolean): CallBinding { + export function createCallBinding(expression: Expression, recordTempVariable: (temp: Identifier) => void, languageVersion?: ScriptTarget, cacheIdentifiers = false): CallBinding { const callee = skipOuterExpressions(expression, OuterExpressionKinds.All); let thisArg: Expression; let target: LeftHandSideExpression; @@ -3431,7 +3430,7 @@ namespace ts { } else if (callee.kind === SyntaxKind.SuperKeyword) { thisArg = createThis(); - target = languageVersion < ScriptTarget.ES2015 + target = languageVersion! < ScriptTarget.ES2015 ? setTextRange(createIdentifier("_super"), callee) : callee; } @@ -3505,7 +3504,7 @@ namespace ts { // stack size exceeded" errors. return expressions.length > 10 ? createCommaList(expressions) - : reduceLeft(expressions, createComma); + : reduceLeft(expressions, createComma)!; } export function createExpressionFromEntityName(node: EntityName | Expression): Expression { @@ -3531,11 +3530,11 @@ namespace ts { } } - export function createExpressionForObjectLiteralElementLike(node: ObjectLiteralExpression, property: ObjectLiteralElementLike, receiver: Expression): Expression { + export function createExpressionForObjectLiteralElementLike(node: ObjectLiteralExpression, property: ObjectLiteralElementLike, receiver: Expression): Expression | undefined { switch (property.kind) { case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: - return createExpressionForAccessorDeclaration(node.properties, property, receiver, node.multiLine); + return createExpressionForAccessorDeclaration(node.properties, property, receiver, !!node.multiLine); case SyntaxKind.PropertyAssignment: return createExpressionForPropertyAssignment(property, receiver); case SyntaxKind.ShorthandPropertyAssignment: @@ -3557,7 +3556,7 @@ namespace ts { /*typeParameters*/ undefined, getAccessor.parameters, /*type*/ undefined, - getAccessor.body + getAccessor.body! // TODO: GH#18217 ); setTextRange(getterFunction, getAccessor); setOriginalNode(getterFunction, getAccessor); @@ -3573,7 +3572,7 @@ namespace ts { /*typeParameters*/ undefined, setAccessor.parameters, /*type*/ undefined, - setAccessor.body + setAccessor.body! // TODO: GH#18217 ); setTextRange(setterFunction, setAccessor); setOriginalNode(setterFunction, setAccessor); @@ -3648,7 +3647,7 @@ namespace ts { /*typeParameters*/ undefined, method.parameters, /*type*/ undefined, - method.body + method.body! // TODO: GH#18217 ), /*location*/ method ), @@ -3738,7 +3737,7 @@ namespace ts { return getName(node, allowComments, allowSourceMaps); } - function getName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean, emitFlags?: EmitFlags) { + function getName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean, emitFlags: EmitFlags = 0) { const nodeName = getNameOfDeclaration(node); if (nodeName && isIdentifier(nodeName) && !isGeneratedIdentifier(nodeName)) { const name = getMutableClone(nodeName); @@ -3780,7 +3779,7 @@ namespace ts { export function getNamespaceMemberName(ns: Identifier, name: Identifier, allowComments?: boolean, allowSourceMaps?: boolean): PropertyAccessExpression { const qualifiedName = createPropertyAccess(ns, nodeIsSynthesized(name) ? name : getSynthesizedClone(name)); setTextRange(qualifiedName, name); - let emitFlags: EmitFlags; + let emitFlags: EmitFlags = 0; if (!allowSourceMaps) emitFlags |= EmitFlags.NoSourceMap; if (!allowComments) emitFlags |= EmitFlags.NoComments; if (emitFlags) setEmitFlags(qualifiedName, emitFlags); @@ -3792,7 +3791,7 @@ namespace ts { } export function convertFunctionDeclarationToExpression(node: FunctionDeclaration) { - Debug.assert(!!node.body); + if (!node.body) return Debug.fail(); const updated = createFunctionExpression( node.modifiers, node.asteriskToken, @@ -3867,9 +3866,11 @@ namespace ts { * This function needs to be called whenever we transform the statement * list of a source file, namespace, or function-like body. */ - export function addCustomPrologue(target: Statement[], source: ReadonlyArray, statementOffset: number, visitor?: (node: Node) => VisitResult): number { + export function addCustomPrologue(target: Statement[], source: ReadonlyArray, statementOffset: number, visitor?: (node: Node) => VisitResult): number; + export function addCustomPrologue(target: Statement[], source: ReadonlyArray, statementOffset: number | undefined, visitor?: (node: Node) => VisitResult): number | undefined; + export function addCustomPrologue(target: Statement[], source: ReadonlyArray, statementOffset: number | undefined, visitor?: (node: Node) => VisitResult): number | undefined { const numStatements = source.length; - while (statementOffset < numStatements) { + while (statementOffset !== undefined && statementOffset < numStatements) { const statement = source[statementOffset]; if (getEmitFlags(statement) & EmitFlags.CustomPrologue) { append(target, visitor ? visitNode(statement, visitor, isStatement) : statement); @@ -3951,7 +3952,7 @@ namespace ts { * @param isLeftSideOfBinary A value indicating whether the operand is the left side of the * BinaryExpression. */ - function binaryOperandNeedsParentheses(binaryOperator: SyntaxKind, operand: Expression, isLeftSideOfBinary: boolean, leftOperand: Expression) { + function binaryOperandNeedsParentheses(binaryOperator: SyntaxKind, operand: Expression, isLeftSideOfBinary: boolean, leftOperand: Expression | undefined) { // If the operand has lower precedence, then it needs to be parenthesized to preserve the // intent of the expression. For example, if the operand is `a + b` and the operator is // `*`, then we need to parenthesize the operand to preserve the intended order of @@ -4196,7 +4197,7 @@ namespace ts { } export function parenthesizeListElements(elements: NodeArray) { - let result: Expression[]; + let result: Expression[] | undefined; for (let i = 0; i < elements.length; i++) { const element = parenthesizeExpressionForList(elements[i]); if (result !== undefined || element !== elements[i]) { @@ -4273,7 +4274,7 @@ namespace ts { return createNodeArray(sameMap(members, parenthesizeElementTypeMember)); } - export function parenthesizeTypeParameters(typeParameters: ReadonlyArray) { + export function parenthesizeTypeParameters(typeParameters: ReadonlyArray | undefined) { if (some(typeParameters)) { const params: TypeNode[] = []; for (let i = 0; i < typeParameters.length; ++i) { @@ -4475,7 +4476,7 @@ namespace ts { /** * Get the name of that target module from an import or export declaration */ - export function getLocalNameForExternalImport(node: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration, sourceFile: SourceFile): Identifier { + export function getLocalNameForExternalImport(node: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration, sourceFile: SourceFile): Identifier | undefined { const namespaceDeclaration = getNamespaceDeclarationNode(node); if (namespaceDeclaration && !isDefaultImport(node)) { const name = namespaceDeclaration.name; @@ -4499,7 +4500,7 @@ namespace ts { * Otherwise, a new StringLiteral node representing the module name will be returned. */ export function getExternalModuleNameLiteral(importNode: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration, sourceFile: SourceFile, host: EmitHost, resolver: EmitResolver, compilerOptions: CompilerOptions) { - const moduleName = getExternalModuleName(importNode); + const moduleName = getExternalModuleName(importNode)!; // TODO: GH#18217 if (moduleName.kind === SyntaxKind.StringLiteral) { return tryGetModuleNameFromDeclaration(importNode, host, resolver, compilerOptions) || tryRenameExternalModule(moduleName, sourceFile) @@ -4525,7 +4526,7 @@ namespace ts { * 2. --out or --outFile is used, making the name relative to the rootDir * Otherwise, a new StringLiteral node representing the module name will be returned. */ - export function tryGetModuleNameFromFile(file: SourceFile, host: EmitHost, options: CompilerOptions): StringLiteral { + export function tryGetModuleNameFromFile(file: SourceFile | undefined, host: EmitHost, options: CompilerOptions): StringLiteral | undefined { if (!file) { return undefined; } @@ -4561,8 +4562,9 @@ namespace ts { // `1` in `({ a: b = 1 } = ...)` // `1` in `({ a: {b} = 1 } = ...)` // `1` in `({ a: [b] = 1 } = ...)` - return isAssignmentExpression(bindingElement.initializer, /*excludeCompoundAssignment*/ true) - ? bindingElement.initializer.right + const initializer = bindingElement.initializer; + return isAssignmentExpression(initializer, /*excludeCompoundAssignment*/ true) + ? initializer.right : undefined; } @@ -4587,7 +4589,7 @@ namespace ts { /** * Gets the name of an BindingOrAssignmentElement. */ - export function getTargetOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): BindingOrAssignmentElementTarget { + export function getTargetOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): BindingOrAssignmentElementTarget | undefined { if (isDeclarationBindingElement(bindingElement)) { // `a` in `let { a } = ...` // `a` in `let { a = 1 } = ...` @@ -4662,7 +4664,7 @@ namespace ts { /** * Determines whether an BindingOrAssignmentElement is a rest element. */ - export function getRestIndicatorOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): BindingOrAssignmentElementRestIndicator { + export function getRestIndicatorOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): BindingOrAssignmentElementRestIndicator | undefined { switch (bindingElement.kind) { case SyntaxKind.Parameter: case SyntaxKind.BindingElement: diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index 510fc096297a7..beaeb7dd05615 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -2,12 +2,12 @@ namespace ts { /* @internal */ export function trace(host: ModuleResolutionHost, message: DiagnosticMessage, ...args: any[]): void; export function trace(host: ModuleResolutionHost): void { - host.trace(formatMessage.apply(undefined, arguments)); + host.trace!(formatMessage.apply(undefined, arguments)); } /* @internal */ export function isTraceEnabled(compilerOptions: CompilerOptions, host: ModuleResolutionHost): boolean { - return compilerOptions.traceResolution && host.trace !== undefined; + return !!compilerOptions.traceResolution && host.trace !== undefined; } /** Array that is only intended to be pushed to, never read. */ @@ -16,11 +16,11 @@ namespace ts { push(value: T): void; } - function withPackageId(packageId: PackageId | undefined, r: PathAndExtension | undefined): Resolved { + function withPackageId(packageId: PackageId | undefined, r: PathAndExtension | undefined): Resolved | undefined { return r && { path: r.path, extension: r.ext, packageId }; } - function noPackageId(r: PathAndExtension | undefined): Resolved { + function noPackageId(r: PathAndExtension | undefined): Resolved | undefined { return withPackageId(/*packageId*/ undefined, r); } @@ -51,7 +51,7 @@ namespace ts { interface PathAndPackageId { readonly fileName: string; - readonly packageId: PackageId; + readonly packageId: PackageId | undefined; } /** Used with `Extensions.DtsOnly` to extract the path from TypeScript results. */ function resolvedTypeScriptOnly(resolved: Resolved | undefined): PathAndPackageId | undefined { @@ -141,7 +141,7 @@ namespace ts { return options.typeRoots; } - let currentDirectory: string; + let currentDirectory: string | undefined; if (options.configFilePath) { currentDirectory = getDirectoryPath(options.configFilePath); } @@ -164,10 +164,10 @@ namespace ts { // And if it doesn't exist, tough. } - let typeRoots: string[]; + let typeRoots: string[] | undefined; forEachAncestorDirectory(normalizePath(currentDirectory), directory => { const atTypes = combinePaths(directory, nodeModulesAtTypes); - if (host.directoryExists(atTypes)) { + if (host.directoryExists!(atTypes)) { (typeRoots || (typeRoots = [])).push(atTypes); } return undefined; @@ -254,7 +254,6 @@ namespace ts { } function secondaryLookup(): PathAndPackageId | undefined { - let resolvedFile: PathAndPackageId; const initialLocationForSecondaryLookup = containingFile && getDirectoryPath(containingFile); if (initialLocationForSecondaryLookup !== undefined) { @@ -263,7 +262,7 @@ namespace ts { trace(host, Diagnostics.Looking_up_in_node_modules_folder_initial_location_0, initialLocationForSecondaryLookup); } const result = loadModuleFromNodeModules(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, failedLookupLocations, moduleResolutionState, /*cache*/ undefined); - resolvedFile = resolvedTypeScriptOnly(result && result.value); + const resolvedFile = resolvedTypeScriptOnly(result && result.value); if (!resolvedFile && traceEnabled) { trace(host, Diagnostics.Type_reference_directive_0_was_not_resolved, typeReferenceDirectiveName); } @@ -334,7 +333,7 @@ namespace ts { } export interface PerModuleNameCache { - get(directory: string): ResolvedModuleWithFailedLookupLocations; + get(directory: string): ResolvedModuleWithFailedLookupLocations | undefined; set(directory: string, result: ResolvedModuleWithFailedLookupLocations): void; } @@ -366,9 +365,9 @@ namespace ts { return perFolderCache; } - function getOrCreateCacheForModuleName(nonRelativeModuleName: string) { + function getOrCreateCacheForModuleName(nonRelativeModuleName: string): PerModuleNameCache { if (isExternalModuleNameRelative(nonRelativeModuleName)) { - return undefined; + return undefined!; // TODO: GH#18217 } let perModuleNameCache = moduleNameToDirectoryMap.get(nonRelativeModuleName); if (!perModuleNameCache) { @@ -383,7 +382,7 @@ namespace ts { return { get, set }; - function get(directory: string): ResolvedModuleWithFailedLookupLocations { + function get(directory: string): ResolvedModuleWithFailedLookupLocations | undefined { return directoryPathMap.get(toPath(directory, currentDirectory, getCanonicalFileName)); } @@ -427,7 +426,7 @@ namespace ts { } } - function getCommonPrefix(directory: Path, resolution: string) { + function getCommonPrefix(directory: Path, resolution: string | undefined) { if (resolution === undefined) { return undefined; } @@ -492,13 +491,13 @@ namespace ts { result = classicNameResolver(moduleName, containingFile, compilerOptions, host, cache); break; default: - Debug.fail(`Unexpected moduleResolution: ${moduleResolution}`); + return Debug.fail(`Unexpected moduleResolution: ${moduleResolution}`); } if (perFolderCache) { perFolderCache.set(moduleName, result); // put result in per-module name cache - const perModuleNameCache = cache.getOrCreateCacheForModuleName(moduleName); + const perModuleNameCache = cache!.getOrCreateCacheForModuleName(moduleName); if (perModuleNameCache) { perModuleNameCache.set(containingDirectory, result); } @@ -611,8 +610,8 @@ namespace ts { const candidate = normalizePath(combinePaths(containingDirectory, moduleName)); - let matchedRootDir: string; - let matchedNormalizedPrefix: string; + let matchedRootDir: string | undefined; + let matchedNormalizedPrefix: string | undefined; for (const rootDir of state.compilerOptions.rootDirs) { // rootDirs are expected to be absolute // in case of tsconfig.json this will happen automatically - compiler will expand relative names @@ -698,9 +697,9 @@ namespace ts { if (state.traceEnabled) { trace(state.host, Diagnostics.Module_name_0_matched_pattern_1, moduleName, matchedPatternText); } - return forEach(state.compilerOptions.paths[matchedPatternText], subst => { + return forEach(state.compilerOptions.paths![matchedPatternText], subst => { const path = matchedStar ? subst.replace("*", matchedStar) : subst; - const candidate = normalizePath(combinePaths(state.compilerOptions.baseUrl, path)); + const candidate = normalizePath(combinePaths(state.compilerOptions.baseUrl!, path)); if (state.traceEnabled) { trace(state.host, Diagnostics.Trying_substitution_0_candidate_module_location_Colon_1, subst, path); } @@ -781,7 +780,7 @@ namespace ts { let originalPath: string | undefined; if (!compilerOptions.preserveSymlinks && resolvedValue) { originalPath = resolvedValue.path; - const path = realPath(resolved.value.path, host, traceEnabled); + const path = realPath(resolvedValue.path, host, traceEnabled); if (path === originalPath) { originalPath = undefined; } @@ -899,7 +898,7 @@ namespace ts { return !host.directoryExists || host.directoryExists(directoryName); } - function loadModuleFromFileNoPackageId(extensions: Extensions, candidate: string, failedLookupLocations: Push, onlyRecordFailures: boolean, state: ModuleResolutionState): Resolved { + function loadModuleFromFileNoPackageId(extensions: Extensions, candidate: string, failedLookupLocations: Push, onlyRecordFailures: boolean, state: ModuleResolutionState): Resolved | undefined { return noPackageId(loadModuleFromFile(extensions, candidate, failedLookupLocations, onlyRecordFailures, state)); } @@ -910,7 +909,7 @@ namespace ts { function loadModuleFromFile(extensions: Extensions, candidate: string, failedLookupLocations: Push, onlyRecordFailures: boolean, state: ModuleResolutionState): PathAndExtension | undefined { if (extensions === Extensions.Json) { const extensionLess = tryRemoveExtension(candidate, Extension.Json); - return extensionLess && tryAddingExtensions(extensionLess, extensions, failedLookupLocations, onlyRecordFailures, state); + return extensionLess === undefined ? undefined : tryAddingExtensions(extensionLess, extensions, failedLookupLocations, onlyRecordFailures, state); } // First, try adding an extension. An import of "foo" could be matched by a file "foo.ts", or "foo.js" by "foo.js.ts" @@ -954,7 +953,7 @@ namespace ts { function tryExtension(ext: Extension): PathAndExtension | undefined { const path = tryFile(candidate + ext, failedLookupLocations, onlyRecordFailures, state); - return path && { path, ext }; + return path === undefined ? undefined : { path, ext }; } } @@ -1025,7 +1024,7 @@ namespace ts { if (!endsWith(subModuleName, Extension.Dts)) { subModuleName = addExtensionAndIndex(subModuleName); } - const packageId: PackageId = typeof packageJsonContent.name === "string" && typeof packageJsonContent.version === "string" + const packageId: PackageId | undefined = typeof packageJsonContent.name === "string" && typeof packageJsonContent.version === "string" ? { name: packageJsonContent.name, subModuleName, version: packageJsonContent.version } : undefined; if (traceEnabled) { @@ -1141,7 +1140,7 @@ namespace ts { return idx === -1 ? { packageName: moduleName, rest: "" } : { packageName: moduleName.slice(0, idx), rest: moduleName.slice(idx + 1) }; } - function loadModuleFromNodeModules(extensions: Extensions, moduleName: string, directory: string, failedLookupLocations: Push, state: ModuleResolutionState, cache: NonRelativeModuleNameResolutionCache): SearchResult { + function loadModuleFromNodeModules(extensions: Extensions, moduleName: string, directory: string, failedLookupLocations: Push, state: ModuleResolutionState, cache: NonRelativeModuleNameResolutionCache | undefined): SearchResult { return loadModuleFromNodeModulesWorker(extensions, moduleName, directory, failedLookupLocations, state, /*typesOnly*/ false, cache); } function loadModuleFromNodeModulesAtTypes(moduleName: string, directory: string, failedLookupLocations: Push, state: ModuleResolutionState): SearchResult { @@ -1149,7 +1148,7 @@ namespace ts { return loadModuleFromNodeModulesWorker(Extensions.DtsOnly, moduleName, directory, failedLookupLocations, state, /*typesOnly*/ true, /*cache*/ undefined); } - function loadModuleFromNodeModulesWorker(extensions: Extensions, moduleName: string, directory: string, failedLookupLocations: Push, state: ModuleResolutionState, typesOnly: boolean, cache: NonRelativeModuleNameResolutionCache): SearchResult { + function loadModuleFromNodeModulesWorker(extensions: Extensions, moduleName: string, directory: string, failedLookupLocations: Push, state: ModuleResolutionState, typesOnly: boolean, cache: NonRelativeModuleNameResolutionCache | undefined): SearchResult { const perModuleNameCache = cache && cache.getOrCreateCacheForModuleName(moduleName); return forEachAncestorDirectory(normalizeSlashes(directory), ancestorDirectory => { if (getBaseFileName(ancestorDirectory) !== "node_modules") { @@ -1289,7 +1288,7 @@ namespace ts { * This is the minumum code needed to expose that functionality; the rest is in LSHost. */ /* @internal */ - export function loadModuleFromGlobalCache(moduleName: string, projectName: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, globalCache: string): ResolvedModuleWithFailedLookupLocations { + export function loadModuleFromGlobalCache(moduleName: string, projectName: string | undefined, compilerOptions: CompilerOptions, host: ModuleResolutionHost, globalCache: string): ResolvedModuleWithFailedLookupLocations { const traceEnabled = isTraceEnabled(compilerOptions, host); if (traceEnabled) { trace(host, Diagnostics.Auto_discovery_for_typings_is_enabled_in_project_0_Running_extra_resolution_pass_for_module_1_using_cache_location_2, projectName, moduleName, globalCache); diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 975331e715366..cd89248144bb0 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -10,10 +10,10 @@ namespace ts { } // tslint:disable variable-name - let NodeConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; - let TokenConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; - let IdentifierConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; - let SourceFileConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; + let NodeConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node; + let TokenConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node; + let IdentifierConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node; + let SourceFileConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node; // tslint:enable variable-name export function createNode(kind: SyntaxKind, pos?: number, end?: number): Node { @@ -31,11 +31,11 @@ namespace ts { } } - function visitNode(cbNode: (node: Node) => T, node: Node): T | undefined { + function visitNode(cbNode: (node: Node) => T, node: Node | undefined): T | undefined { return node && cbNode(node); } - function visitNodes(cbNode: (node: Node) => T, cbNodes: (node: NodeArray) => T | undefined, nodes: NodeArray): T | undefined { + function visitNodes(cbNode: (node: Node) => T, cbNodes: ((node: NodeArray) => T | undefined) | undefined, nodes: NodeArray | undefined): T | undefined { if (nodes) { if (cbNodes) { return cbNodes(nodes); @@ -481,7 +481,7 @@ namespace ts { return visitNodes(cbNode, cbNodes, (node).typeParameters); case SyntaxKind.JSDocTypedefTag: if ((node as JSDocTypedefTag).typeExpression && - (node as JSDocTypedefTag).typeExpression.kind === SyntaxKind.JSDocTypeExpression) { + (node as JSDocTypedefTag).typeExpression!.kind === SyntaxKind.JSDocTypeExpression) { return visitNode(cbNode, (node).typeExpression) || visitNode(cbNode, (node).fullName); } @@ -500,7 +500,7 @@ namespace ts { visitNode(cbNode, (node).type); case SyntaxKind.JSDocTypeLiteral: if ((node as JSDocTypeLiteral).jsDocPropertyTags) { - for (const tag of (node as JSDocTypeLiteral).jsDocPropertyTags) { + for (const tag of (node as JSDocTypeLiteral).jsDocPropertyTags!) { visitNode(cbNode, tag); } } @@ -524,7 +524,7 @@ namespace ts { return result; } - export function parseIsolatedEntityName(text: string, languageVersion: ScriptTarget): EntityName { + export function parseIsolatedEntityName(text: string, languageVersion: ScriptTarget): EntityName | undefined { return Parser.parseIsolatedEntityName(text, languageVersion); } @@ -551,7 +551,7 @@ namespace ts { // from this SourceFile that are being held onto may change as a result (including // becoming detached from any SourceFile). It is recommended that this SourceFile not // be used once 'update' is called on it. - export function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile { + export function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks = false): SourceFile { const newSourceFile = IncrementalParser.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks); // Because new source file node is created, it may not have the flag PossiblyContainDynamicImport. This is the case if there is no new edit to add dynamic import. // We will manually port the flag to the new source file. @@ -596,7 +596,7 @@ namespace ts { let sourceFile: SourceFile; let parseDiagnostics: DiagnosticWithLocation[]; - let syntaxCursor: IncrementalParser.SyntaxCursor; + let syntaxCursor: IncrementalParser.SyntaxCursor | undefined; let currentToken: SyntaxKind; let sourceText: string; @@ -683,7 +683,7 @@ namespace ts { // attached to the EOF token. let parseErrorBeforeNextFinishedNode = false; - export function parseSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, syntaxCursor: IncrementalParser.SyntaxCursor, setParentNodes?: boolean, scriptKind?: ScriptKind): SourceFile { + export function parseSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, syntaxCursor: IncrementalParser.SyntaxCursor | undefined, setParentNodes = false, scriptKind?: ScriptKind): SourceFile { scriptKind = ensureScriptKind(fileName, scriptKind); if (scriptKind === ScriptKind.JSON) { const result = parseJsonText(fileName, sourceText, languageVersion, syntaxCursor, setParentNodes); @@ -702,7 +702,7 @@ namespace ts { return result; } - export function parseIsolatedEntityName(content: string, languageVersion: ScriptTarget): EntityName { + export function parseIsolatedEntityName(content: string, languageVersion: ScriptTarget): EntityName | undefined { // Choice of `isDeclarationFile` should be arbitrary initializeState(content, languageVersion, /*syntaxCursor*/ undefined, ScriptKind.JS); // Prime the scanner. @@ -775,7 +775,7 @@ namespace ts { return scriptKind === ScriptKind.TSX || scriptKind === ScriptKind.JSX || scriptKind === ScriptKind.JS || scriptKind === ScriptKind.JSON ? LanguageVariant.JSX : LanguageVariant.Standard; } - function initializeState(_sourceText: string, languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor, scriptKind: ScriptKind) { + function initializeState(_sourceText: string, languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor | undefined, scriptKind: ScriptKind) { NodeConstructor = objectAllocator.getNodeConstructor(); TokenConstructor = objectAllocator.getTokenConstructor(); IdentifierConstructor = objectAllocator.getIdentifierConstructor(); @@ -817,11 +817,11 @@ namespace ts { scanner.setOnError(undefined); // Clear any data. We don't want to accidentally hold onto it for too long. - parseDiagnostics = undefined; - sourceFile = undefined; - identifiers = undefined; + parseDiagnostics = undefined!; + sourceFile = undefined!; + identifiers = undefined!; syntaxCursor = undefined; - sourceText = undefined; + sourceText = undefined!; } function parseSourceFileWorker(fileName: string, languageVersion: ScriptTarget, setParentNodes: boolean, scriptKind: ScriptKind): SourceFile { @@ -865,7 +865,7 @@ namespace ts { const comments = getJSDocCommentRanges(node, sourceFile.text); if (comments) { for (const comment of comments) { - node.jsDoc = append(node.jsDoc, JSDocParser.parseJSDocComment(node, comment.pos, comment.end - comment.pos)); + node.jsDoc = append(node.jsDoc, JSDocParser.parseJSDocComment(node, comment.pos, comment.end - comment.pos)); } } @@ -893,7 +893,7 @@ namespace ts { parent = n; forEachChild(n, visitNode); if (hasJSDocNodes(n)) { - for (const jsDoc of n.jsDoc) { + for (const jsDoc of n.jsDoc!) { jsDoc.parent = n; parent = jsDoc; forEachChild(jsDoc, visitNode); @@ -1205,7 +1205,7 @@ namespace ts { } function parseOptionalToken(t: TKind): Token; - function parseOptionalToken(t: SyntaxKind): Node { + function parseOptionalToken(t: SyntaxKind): Node | undefined { if (token() === t) { return parseTokenNode(); } @@ -1250,7 +1250,7 @@ namespace ts { function createNode(kind: SyntaxKind, pos?: number): Node { nodeCount++; - const p = pos >= 0 ? pos : scanner.getStartPos(); + const p = pos! >= 0 ? pos! : scanner.getStartPos(); return isNodeKind(kind) || kind === SyntaxKind.Unknown ? new NodeConstructor(kind, p, p) : kind === SyntaxKind.Identifier ? new IdentifierConstructor(kind, p, p) : new TokenConstructor(kind, p, p); @@ -1527,7 +1527,7 @@ namespace ts { return true; } - Debug.fail("Non-exhaustive case in 'isListElement'."); + return Debug.fail("Non-exhaustive case in 'isListElement'."); } function isValidHeritageClauseObjectLiteral() { @@ -1629,6 +1629,8 @@ namespace ts { return token() === SyntaxKind.GreaterThanToken || token() === SyntaxKind.SlashToken; case ParsingContext.JsxChildren: return token() === SyntaxKind.LessThanToken && lookAhead(nextTokenIsSlash); + default: + return false; } } @@ -1703,7 +1705,7 @@ namespace ts { return parseElement(); } - function currentNode(parsingContext: ParsingContext): Node { + function currentNode(parsingContext: ParsingContext): Node | undefined { // If there is an outstanding parse error that we've encountered, but not attached to // some node, then we cannot get a node from the old source tree. This is because we // want to mark the next node we encounter as being unusable. @@ -2019,6 +2021,7 @@ namespace ts { case ParsingContext.ImportOrExportSpecifiers: return Diagnostics.Identifier_expected; case ParsingContext.JsxAttributes: return Diagnostics.Identifier_expected; case ParsingContext.JsxChildren: return Diagnostics.Identifier_expected; + default: return undefined!; // TODO: GH#18217 `default: Debug.assertNever(context);` } } @@ -2173,7 +2176,7 @@ namespace ts { do { list.push(parseTemplateSpan()); } - while (lastOrUndefined(list).literal.kind === SyntaxKind.TemplateMiddle); + while (last(list).literal.kind === SyntaxKind.TemplateMiddle); template.templateSpans = createNodeArray(list, listPos); @@ -2396,7 +2399,7 @@ namespace ts { } } - function parseParameterType(): TypeNode { + function parseParameterType(): TypeNode | undefined { if (parseOptional(SyntaxKind.ColonToken)) { return parseType(); } @@ -2456,7 +2459,7 @@ namespace ts { if (!(flags & SignatureFlags.JSDoc)) { signature.typeParameters = parseTypeParameters(); } - signature.parameters = parseParameterList(flags); + signature.parameters = parseParameterList(flags)!; // TODO: GH#18217 if (shouldParseReturnType(returnToken, !!(flags & SignatureFlags.Type))) { signature.type = parseTypeOrTypePredicate(); return signature.type !== undefined; @@ -2638,7 +2641,7 @@ namespace ts { if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) { return true; } - let idToken: boolean; + let idToken = false; // Eat up all modifiers, but hold on to the last one in case it is actually an identifier while (isModifierKind(token())) { idToken = true; @@ -2742,7 +2745,7 @@ namespace ts { const node = createNode(SyntaxKind.MappedType); parseExpected(SyntaxKind.OpenBraceToken); if (token() === SyntaxKind.ReadonlyKeyword || token() === SyntaxKind.PlusToken || token() === SyntaxKind.MinusToken) { - node.readonlyToken = parseTokenNode(); + node.readonlyToken = parseTokenNode(); if (node.readonlyToken.kind !== SyntaxKind.ReadonlyKeyword) { parseExpectedToken(SyntaxKind.ReadonlyKeyword); } @@ -2751,7 +2754,7 @@ namespace ts { node.typeParameter = parseMappedTypeParameter(); parseExpected(SyntaxKind.CloseBracketToken); if (token() === SyntaxKind.QuestionToken || token() === SyntaxKind.PlusToken || token() === SyntaxKind.MinusToken) { - node.questionToken = parseTokenNode(); + node.questionToken = parseTokenNode(); if (node.questionToken.kind !== SyntaxKind.QuestionToken) { parseExpectedToken(SyntaxKind.QuestionToken); } @@ -2773,13 +2776,13 @@ namespace ts { parseExpected(SyntaxKind.OpenParenToken); node.type = parseType(); if (!node.type) { - return undefined; + return undefined!; // TODO: GH#18217 } parseExpected(SyntaxKind.CloseParenToken); return finishNode(node); } - function parseFunctionOrConstructorType(kind: SyntaxKind): FunctionOrConstructorTypeNode { + function parseFunctionOrConstructorType(kind: SyntaxKind): FunctionOrConstructorTypeNode | undefined { const node = createNodeWithJSDoc(kind); if (kind === SyntaxKind.ConstructorType) { parseExpected(SyntaxKind.NewKeyword); @@ -2800,7 +2803,7 @@ namespace ts { function parseLiteralTypeNode(negative?: boolean): LiteralTypeNode { const node = createNode(SyntaxKind.LiteralType) as LiteralTypeNode; - let unaryMinusExpression: PrefixUnaryExpression; + let unaryMinusExpression!: PrefixUnaryExpression; if (negative) { unaryMinusExpression = createNode(SyntaxKind.PrefixUnaryExpression) as PrefixUnaryExpression; unaryMinusExpression.operator = SyntaxKind.MinusToken; @@ -3129,10 +3132,10 @@ namespace ts { function parseTypeWorker(noConditionalTypes?: boolean): TypeNode { if (isStartOfFunctionType()) { - return parseFunctionOrConstructorType(SyntaxKind.FunctionType); + return parseFunctionOrConstructorType(SyntaxKind.FunctionType)!; // TODO: GH#18217 } if (token() === SyntaxKind.NewKeyword) { - return parseFunctionOrConstructorType(SyntaxKind.ConstructorType); + return parseFunctionOrConstructorType(SyntaxKind.ConstructorType)!; } const type = parseUnionTypeOrHigher(); if (!noConditionalTypes && !scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind.ExtendsKeyword)) { @@ -3149,7 +3152,7 @@ namespace ts { return type; } - function parseTypeAnnotation(): TypeNode { + function parseTypeAnnotation(): TypeNode | undefined { return parseOptional(SyntaxKind.ColonToken) ? parseType() : undefined; } @@ -3373,7 +3376,7 @@ namespace ts { } } - function parseSimpleArrowFunctionExpression(identifier: Identifier, asyncModifier?: NodeArray): ArrowFunction { + function parseSimpleArrowFunctionExpression(identifier: Identifier, asyncModifier?: NodeArray | undefined): ArrowFunction { Debug.assert(token() === SyntaxKind.EqualsGreaterThanToken, "parseSimpleArrowFunctionExpression should only have been called if we had a =>"); let node: ArrowFunction; @@ -3572,7 +3575,7 @@ namespace ts { } } - function parsePossibleParenthesizedArrowFunctionExpressionHead(): ArrowFunction { + function parsePossibleParenthesizedArrowFunctionExpressionHead(): ArrowFunction | undefined { return parseParenthesizedArrowFunctionExpressionHead(/*allowAmbiguity*/ false); } @@ -3609,7 +3612,7 @@ namespace ts { return Tristate.False; } - function parseParenthesizedArrowFunctionExpressionHead(allowAmbiguity: boolean): ArrowFunction { + function parseParenthesizedArrowFunctionExpressionHead(allowAmbiguity: boolean): ArrowFunction | undefined { const node = createNodeWithJSDoc(SyntaxKind.ArrowFunction); node.modifiers = parseModifiersForArrowFunction(); const isAsync = hasModifier(node, ModifierFlags.Async) ? SignatureFlags.Await : SignatureFlags.None; @@ -4208,7 +4211,7 @@ namespace ts { badNode.end = invalidElement.end; badNode.left = result; badNode.right = invalidElement; - badNode.operatorToken = createMissingNode(SyntaxKind.CommaToken, /*reportAtCurrentPosition*/ false, /*diagnosticMessage*/ undefined); + badNode.operatorToken = createMissingNode(SyntaxKind.CommaToken, /*reportAtCurrentPosition*/ false, /*diagnosticMessage*/ undefined!); // TODO: GH#18217 badNode.operatorToken.pos = badNode.operatorToken.end = badNode.right.pos; return badNode; } @@ -4902,7 +4905,7 @@ namespace ts { const awaitToken = parseOptionalToken(SyntaxKind.AwaitKeyword); parseExpected(SyntaxKind.OpenParenToken); - let initializer: VariableDeclarationList | Expression; + let initializer!: VariableDeclarationList | Expression; if (token() !== SyntaxKind.SemicolonToken) { if (token() === SyntaxKind.VarKeyword || token() === SyntaxKind.LetKeyword || token() === SyntaxKind.ConstKeyword) { initializer = parseVariableDeclarationList(/*inForStatementInitializer*/ true); @@ -5345,7 +5348,7 @@ namespace ts { node.decorators = parseDecorators(); node.modifiers = parseModifiers(); if (some(node.modifiers, isDeclareModifier)) { - for (const m of node.modifiers) { + for (const m of node.modifiers!) { m.flags |= NodeFlags.Ambient; } return doInsideOfContext(NodeFlags.Ambient, () => parseDeclarationWorker(node)); @@ -5398,6 +5401,7 @@ namespace ts { missing.modifiers = node.modifiers; return finishNode(missing); } + return undefined!; // TODO: GH#18217 } } @@ -5406,7 +5410,7 @@ namespace ts { return !scanner.hasPrecedingLineBreak() && (isIdentifier() || token() === SyntaxKind.StringLiteral); } - function parseFunctionBlockOrSemicolon(flags: SignatureFlags, diagnosticMessage?: DiagnosticMessage): Block { + function parseFunctionBlockOrSemicolon(flags: SignatureFlags, diagnosticMessage?: DiagnosticMessage): Block | undefined { if (token() !== SyntaxKind.OpenBraceToken && canParseSemicolon()) { parseSemicolon(); return; @@ -5484,7 +5488,7 @@ namespace ts { node.name = parseIdentifierOrPattern(); if (allowExclamation && node.name.kind === SyntaxKind.Identifier && token() === SyntaxKind.ExclamationToken && !scanner.hasPrecedingLineBreak()) { - node.exclamationToken = parseTokenNode(); + node.exclamationToken = parseTokenNode>(); } node.type = parseTypeAnnotation(); if (!isInOrOfKeyword(token())) { @@ -5580,7 +5584,7 @@ namespace ts { function parsePropertyDeclaration(node: PropertyDeclaration): PropertyDeclaration { node.kind = SyntaxKind.PropertyDeclaration; if (!node.questionToken && token() === SyntaxKind.ExclamationToken && !scanner.hasPrecedingLineBreak()) { - node.exclamationToken = parseTokenNode(); + node.exclamationToken = parseTokenNode>(); } node.type = parseTypeAnnotation(); @@ -5622,7 +5626,7 @@ namespace ts { } function isClassMemberStart(): boolean { - let idToken: SyntaxKind; + let idToken: SyntaxKind | undefined; if (token() === SyntaxKind.AtToken) { return true; @@ -5714,7 +5718,7 @@ namespace ts { * In such situations, 'permitInvalidConstAsModifier' should be set to true. */ function parseModifiers(permitInvalidConstAsModifier?: boolean): NodeArray | undefined { - let list: Modifier[]; + let list: Modifier[] | undefined; const listPos = getNodePos(); while (true) { const modifierStart = scanner.getStartPos(); @@ -5739,8 +5743,8 @@ namespace ts { return list && createNodeArray(list, listPos); } - function parseModifiersForArrowFunction(): NodeArray { - let modifiers: NodeArray; + function parseModifiersForArrowFunction(): NodeArray | undefined { + let modifiers: NodeArray | undefined; if (token() === SyntaxKind.AsyncKeyword) { const modifierStart = scanner.getStartPos(); const modifierKind = token(); @@ -5796,7 +5800,7 @@ namespace ts { } // 'isClassMemberStart' should have hinted not to attempt parsing. - Debug.fail("Should not have attempted to parse class member declaration."); + return Debug.fail("Should not have attempted to parse class member declaration."); } function parseClassExpression(): ClassExpression { @@ -5853,17 +5857,14 @@ namespace ts { return undefined; } - function parseHeritageClause(): HeritageClause | undefined { + function parseHeritageClause(): HeritageClause { const tok = token(); - if (tok === SyntaxKind.ExtendsKeyword || tok === SyntaxKind.ImplementsKeyword) { - const node = createNode(SyntaxKind.HeritageClause); - node.token = tok; - nextToken(); - node.types = parseDelimitedList(ParsingContext.HeritageClauseElement, parseExpressionWithTypeArguments); - return finishNode(node); - } - - return undefined; + Debug.assert(tok === SyntaxKind.ExtendsKeyword || tok === SyntaxKind.ImplementsKeyword); // isListElement() should ensure this. + const node = createNode(SyntaxKind.HeritageClause); + node.token = tok as SyntaxKind.ExtendsKeyword | SyntaxKind.ImplementsKeyword; + nextToken(); + node.types = parseDelimitedList(ParsingContext.HeritageClauseElement, parseExpressionWithTypeArguments); + return finishNode(node); } function parseExpressionWithTypeArguments(): ExpressionWithTypeArguments { @@ -6022,7 +6023,7 @@ namespace ts { parseExpected(SyntaxKind.ImportKeyword); const afterImportPos = scanner.getStartPos(); - let identifier: Identifier; + let identifier: Identifier | undefined; if (isIdentifier()) { identifier = parseIdentifier(); if (token() !== SyntaxKind.CommaToken && token() !== SyntaxKind.FromKeyword) { @@ -6056,7 +6057,7 @@ namespace ts { return finishNode(node); } - function parseImportClause(identifier: Identifier, fullStart: number) { + function parseImportClause(identifier: Identifier | undefined, fullStart: number) { // ImportClause: // ImportedDefaultBinding // NameSpaceImport @@ -6233,7 +6234,7 @@ namespace ts { undefined; } - function walkTreeForExternalModuleIndicators(node: Node): Node { + function walkTreeForExternalModuleIndicators(node: Node): Node | undefined { return isImportMeta(node) ? node : forEachChild(node, walkTreeForExternalModuleIndicators); } @@ -6275,7 +6276,7 @@ namespace ts { } export namespace JSDocParser { - export function parseJSDocTypeExpressionForTests(content: string, start: number, length: number): { jsDocTypeExpression: JSDocTypeExpression, diagnostics: Diagnostic[] } | undefined { + export function parseJSDocTypeExpressionForTests(content: string, start: number | undefined, length: number | undefined): { jsDocTypeExpression: JSDocTypeExpression, diagnostics: Diagnostic[] } | undefined { initializeState(content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS); sourceFile = createSourceFile("file.js", ScriptTarget.Latest, ScriptKind.JS, /*isDeclarationFile*/ false); scanner.setText(content, start, length); @@ -6301,7 +6302,7 @@ namespace ts { return finishNode(result); } - export function parseIsolatedJSDocComment(content: string, start: number, length: number): { jsDoc: JSDoc, diagnostics: Diagnostic[] } | undefined { + export function parseIsolatedJSDocComment(content: string, start: number | undefined, length: number | undefined): { jsDoc: JSDoc, diagnostics: Diagnostic[] } | undefined { initializeState(content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS); sourceFile = { languageVariant: LanguageVariant.Standard, text: content }; // tslint:disable-line no-object-literal-type-assertion const jsDoc = parseJSDocCommentWorker(start, length); @@ -6311,7 +6312,7 @@ namespace ts { return jsDoc ? { jsDoc, diagnostics } : undefined; } - export function parseJSDocComment(parent: HasJSDoc, start: number, length: number): JSDoc { + export function parseJSDocComment(parent: HasJSDoc, start: number, length: number): JSDoc | undefined { const saveToken = currentToken; const saveParseDiagnosticsLength = parseDiagnostics.length; const saveParseErrorBeforeNextFinishedNode = parseErrorBeforeNextFinishedNode; @@ -6346,9 +6347,8 @@ namespace ts { CallbackParameter = 1 << 2, } - export function parseJSDocCommentWorker(start: number, length: number): JSDoc { + export function parseJSDocCommentWorker(start = 0, length: number | undefined): JSDoc | undefined { const content = sourceText; - start = start || 0; const end = length === undefined ? content.length : start + length; length = end - start; @@ -6360,7 +6360,7 @@ namespace ts { let tagsPos: number; let tagsEnd: number; const comments: string[] = []; - let result: JSDoc; + let result: JSDoc | undefined; // Check for /** (JSDoc opening part) if (!isJSDocLikeText(content, start)) { @@ -6518,7 +6518,7 @@ namespace ts { return; } - let tag: JSDocTag; + let tag: JSDocTag | undefined; if (tagName) { switch (tagName.escapedText) { case "augments": @@ -6638,7 +6638,7 @@ namespace ts { return finishNode(result); } - function addTag(tag: JSDocTag): void { + function addTag(tag: JSDocTag | undefined): void { if (!tag) { return; } @@ -6722,13 +6722,13 @@ namespace ts { return finishNode(result); } - function parseNestedTypeLiteral(typeExpression: JSDocTypeExpression, name: EntityName, target: PropertyLikeParse) { + function parseNestedTypeLiteral(typeExpression: JSDocTypeExpression | undefined, name: EntityName, target: PropertyLikeParse) { if (typeExpression && isObjectOrObjectArrayTypeReference(typeExpression.type)) { const typeLiteralExpression = createNode(SyntaxKind.JSDocTypeExpression, scanner.getTokenPos()); let child: JSDocPropertyLikeTag | JSDocTypeTag | false; let jsdocTypeLiteral: JSDocTypeLiteral; const start = scanner.getStartPos(); - let children: JSDocPropertyLikeTag[]; + let children: JSDocPropertyLikeTag[] | undefined; while (child = tryParse(() => parseChildParameterOrPropertyTag(target, name))) { if (child.kind === SyntaxKind.JSDocParameterTag || child.kind === SyntaxKind.JSDocPropertyTag) { children = append(children, child); @@ -6795,7 +6795,7 @@ namespace ts { while (parseOptional(SyntaxKind.DotToken)) { const prop: PropertyAccessEntityNameExpression = createNode(SyntaxKind.PropertyAccessExpression, node.pos) as PropertyAccessEntityNameExpression; prop.expression = node; - prop.name = parseJSDocIdentifierName(); + prop.name = parseJSDocIdentifierName()!; // TODO: GH#18217 node = finishNode(prop); } return node; @@ -6821,11 +6821,11 @@ namespace ts { typedefTag.comment = parseTagComments(indent); typedefTag.typeExpression = typeExpression; - let end: number; + let end: number | undefined; if (!typeExpression || isObjectOrObjectArrayTypeReference(typeExpression.type)) { let child: JSDocTypeTag | JSDocPropertyTag | false; - let jsdocTypeLiteral: JSDocTypeLiteral; - let childTypeTag: JSDocTypeTag; + let jsdocTypeLiteral: JSDocTypeLiteral | undefined; + let childTypeTag: JSDocTypeTag | undefined; const start = scanner.getStartPos(); while (child = tryParse(() => parseChildPropertyTag())) { if (!jsdocTypeLiteral) { @@ -6949,7 +6949,7 @@ namespace ts { const child = tryParseChildTag(target); if (child && child.kind === SyntaxKind.JSDocParameterTag && target !== PropertyLikeParse.CallbackParameter && - (ts.isIdentifier(child.name) || !escapedTextsEqual(name, child.name.left))) { + (ts.isIdentifier(child.name) || !escapedTextsEqual(name!, child.name.left))) { // TODO: GH#18217 return false; } return child; @@ -7219,7 +7219,7 @@ namespace ts { forEachChild(node, visitNode, visitArray); if (hasJSDocNodes(node)) { - for (const jsDocComment of node.jsDoc) { + for (const jsDocComment of node.jsDoc!) { visitNode(jsDocComment); } } @@ -7331,7 +7331,7 @@ namespace ts { pos = child.end; }; if (hasJSDocNodes(node)) { - for (const jsDocComment of node.jsDoc) { + for (const jsDocComment of node.jsDoc!) { visitNode(jsDocComment); } } @@ -7374,7 +7374,7 @@ namespace ts { adjustIntersectingElement(child, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta); forEachChild(child, visitNode, visitArray); if (hasJSDocNodes(child)) { - for (const jsDocComment of child.jsDoc) { + for (const jsDocComment of child.jsDoc!) { visitNode(jsDocComment); } } @@ -7450,7 +7450,7 @@ namespace ts { function findNearestNodeStartingBeforeOrAtPosition(sourceFile: SourceFile, position: number): Node { let bestResult: Node = sourceFile; - let lastNodeEntirelyBeforePosition: Node; + let lastNodeEntirelyBeforePosition: Node | undefined; forEachChild(sourceFile, visit); @@ -7551,10 +7551,10 @@ namespace ts { } interface IncrementalElement extends TextRange { - parent?: Node; + parent: Node; intersectsChange: boolean; length?: number; - _children: Node[]; + _children: Node[] | undefined; } export interface IncrementalNode extends Node, IncrementalElement { @@ -7620,9 +7620,9 @@ namespace ts { // return it, we can easily return its next sibling in the list. function findHighestListElementThatStartsAtPosition(position: number) { // Clear out any cached state about the last node we found. - currentArray = undefined; + currentArray = undefined!; currentArrayIndex = InvalidPosition.Value; - current = undefined; + current = undefined!; // Recurse into the source file to find the highest node at this position. forEachChild(sourceFile, visitNode, visitArray); @@ -7720,17 +7720,17 @@ namespace ts { context.pragmas = createMap() as PragmaMap; for (const pragma of pragmas) { - if (context.pragmas.has(pragma.name)) { - const currentValue = context.pragmas.get(pragma.name); + if (context.pragmas.has(pragma!.name)) { // TODO: GH#18217 + const currentValue = context.pragmas.get(pragma!.name); if (currentValue instanceof Array) { - currentValue.push(pragma.args); + currentValue.push(pragma!.args); } else { - context.pragmas.set(pragma.name, [currentValue, pragma.args]); + context.pragmas.set(pragma!.name, [currentValue, pragma!.args]); } continue; } - context.pragmas.set(pragma.name, pragma.args); + context.pragmas.set(pragma!.name, pragma!.args); } } @@ -7744,7 +7744,7 @@ namespace ts { context.typeReferenceDirectives = []; context.amdDependencies = []; context.hasNoDefaultLib = false; - context.pragmas.forEach((entryOrList, key) => { + context.pragmas!.forEach((entryOrList, key) => { // TODO: GH#18217 // TODO: The below should be strongly type-guarded and not need casts/explicit annotations, since entryOrList is related to // key and key is constrained to a union; but it's not (see GH#21483 for at least partial fix) :( switch (key) { @@ -7752,17 +7752,18 @@ namespace ts { const referencedFiles = context.referencedFiles; const typeReferenceDirectives = context.typeReferenceDirectives; forEach(toArray(entryOrList), (arg: PragmaPsuedoMap["reference"]) => { - if (arg.arguments["no-default-lib"]) { + // TODO: GH#18217 + if (arg!.arguments["no-default-lib"]) { context.hasNoDefaultLib = true; } - else if (arg.arguments.types) { - typeReferenceDirectives.push({ pos: arg.arguments.types.pos, end: arg.arguments.types.end, fileName: arg.arguments.types.value }); + else if (arg!.arguments.types) { + typeReferenceDirectives.push({ pos: arg!.arguments.types!.pos, end: arg!.arguments.types!.end, fileName: arg!.arguments.types!.value }); } - else if (arg.arguments.path) { - referencedFiles.push({ pos: arg.arguments.path.pos, end: arg.arguments.path.end, fileName: arg.arguments.path.value }); + else if (arg!.arguments.path) { + referencedFiles.push({ pos: arg!.arguments.path!.pos, end: arg!.arguments.path!.end, fileName: arg!.arguments.path!.value }); } else { - reportDiagnostic(arg.range.pos, arg.range.end - arg.range.pos, Diagnostics.Invalid_reference_directive_syntax); + reportDiagnostic(arg!.range.pos, arg!.range.end - arg!.range.pos, Diagnostics.Invalid_reference_directive_syntax); } }); break; @@ -7770,8 +7771,7 @@ namespace ts { case "amd-dependency": { context.amdDependencies = map( toArray(entryOrList), - ({ arguments: { name, path } }: PragmaPsuedoMap["amd-dependency"]) => ({ name, path }) - ); + (x: PragmaPsuedoMap["amd-dependency"]) => ({ name: x!.arguments.name!, path: x!.arguments.path })); // TODO: GH#18217 break; } case "amd-module": { @@ -7779,13 +7779,13 @@ namespace ts { for (const entry of entryOrList) { if (context.moduleName) { // TODO: It's probably fine to issue this diagnostic on all instances of the pragma - reportDiagnostic(entry.range.pos, entry.range.end - entry.range.pos, Diagnostics.An_AMD_module_cannot_have_multiple_name_assignments); + reportDiagnostic(entry!.range.pos, entry!.range.end - entry!.range.pos, Diagnostics.An_AMD_module_cannot_have_multiple_name_assignments); } - context.moduleName = (entry as PragmaPsuedoMap["amd-module"]).arguments.name; + context.moduleName = (entry as PragmaPsuedoMap["amd-module"])!.arguments.name; } } else { - context.moduleName = (entryOrList as PragmaPsuedoMap["amd-module"]).arguments.name; + context.moduleName = (entryOrList as PragmaPsuedoMap["amd-module"])!.arguments.name; } break; } @@ -7793,11 +7793,11 @@ namespace ts { case "ts-check": { // _last_ of either nocheck or check in a file is the "winner" forEach(toArray(entryOrList), entry => { - if (!context.checkJsDirective || entry.range.pos > context.checkJsDirective.pos) { + if (!context.checkJsDirective || entry!.range.pos > context.checkJsDirective.pos) { // TODO: GH#18217 context.checkJsDirective = { enabled: key === "ts-check", - end: entry.range.end, - pos: entry.range.pos + end: entry!.range.end, + pos: entry!.range.pos }; } }); @@ -7810,9 +7810,9 @@ namespace ts { } const namedArgRegExCache = createMap(); - function getNamedArgRegEx(name: string) { + function getNamedArgRegEx(name: string): RegExp { if (namedArgRegExCache.has(name)) { - return namedArgRegExCache.get(name); + return namedArgRegExCache.get(name)!; } const result = new RegExp(`(\\s${name}\\s*=\\s*)('|")(.+?)\\2`, "im"); namedArgRegExCache.set(name, result); @@ -7826,7 +7826,7 @@ namespace ts { if (tripleSlash) { const name = tripleSlash[1].toLowerCase() as keyof PragmaPsuedoMap; // Technically unsafe cast, but we do it so the below check to make it safe typechecks const pragma = commentPragmas[name] as PragmaDefinition; - if (!pragma || !(pragma.kind & PragmaKindFlags.TripleSlashXML)) { + if (!pragma || !(pragma.kind! & PragmaKindFlags.TripleSlashXML)) { return; } if (pragma.args) { @@ -7866,7 +7866,7 @@ namespace ts { if (range.kind === SyntaxKind.MultiLineCommentTrivia) { const multiLinePragmaRegEx = /\s*@(\S+)\s*(.*)\s*$/gim; // Defined inline since it uses the "g" flag, which keeps a persistent index (for iterating) - let multiLineMatch: RegExpExecArray; + let multiLineMatch: RegExpExecArray | null; while (multiLineMatch = multiLinePragmaRegEx.exec(text)) { addPragmaForMatch(pragmas, range, PragmaKindFlags.MultiLine, multiLineMatch); } @@ -7877,7 +7877,7 @@ namespace ts { if (!match) return; const name = match[1].toLowerCase() as keyof PragmaPsuedoMap; // Technically unsafe cast, but we do it so they below check to make it safe typechecks const pragma = commentPragmas[name] as PragmaDefinition; - if (!pragma || !(pragma.kind & kind)) { + if (!pragma || !(pragma.kind! & kind)) { return; } const args = match[2]; // Split on spaces and match up positionally with definition diff --git a/src/compiler/performance.ts b/src/compiler/performance.ts index 104148ed4abeb..64709a12ba908 100644 --- a/src/compiler/performance.ts +++ b/src/compiler/performance.ts @@ -2,7 +2,7 @@ namespace ts { declare const performance: { now?(): number } | undefined; /** Gets a timestamp with (at least) ms resolution */ - export const timestamp = typeof performance !== "undefined" && performance.now ? () => performance.now() : Date.now ? Date.now : () => +(new Date()); + export const timestamp = typeof performance !== "undefined" && performance.now ? () => performance.now!() : Date.now ? Date.now : () => +(new Date()); } /*@internal*/ diff --git a/src/compiler/program.ts b/src/compiler/program.ts old mode 100644 new mode 100755 index c453080f3bf9b..af404ba57ad38 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -16,7 +16,7 @@ namespace ts { /* @internal */ export function computeCommonSourceDirectoryOfFilenames(fileNames: string[], currentDirectory: string, getCanonicalFileName: GetCanonicalFileName): string { - let commonPathComponents: string[]; + let commonPathComponents: string[] | undefined; const failed = forEach(fileNames, sourceFile => { // Each file contributes into common source file path const sourcePathComponents = getNormalizedPathComponents(sourceFile, currentDirectory); @@ -75,8 +75,8 @@ namespace ts { return sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(); } - function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile { - let text: string; + function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile | undefined { + let text: string | undefined; try { performance.mark("beforeIORead"); text = sys.readFile(fileName, options.charset); @@ -119,8 +119,8 @@ namespace ts { outputFingerprints = createMap(); } - const hash = sys.createHash(data); - const mtimeBefore = sys.getModifiedTime(fileName); + const hash = sys.createHash!(data); // TODO: GH#18217 + const mtimeBefore = sys.getModifiedTime!(fileName); // TODO: GH#18217 if (mtimeBefore) { const fingerprint = outputFingerprints.get(fileName); @@ -135,7 +135,7 @@ namespace ts { sys.writeFile(fileName, data, writeByteOrderMark); - const mtimeAfter = sys.getModifiedTime(fileName); + const mtimeAfter = sys.getModifiedTime!(fileName); // TODO: GH#18217 outputFingerprints.set(fileName, { hash, @@ -171,7 +171,7 @@ namespace ts { } const newLine = getNewLineCharacter(options); - const realpath = sys.realpath && ((path: string) => sys.realpath(path)); + const realpath = sys.realpath && ((path: string) => sys.realpath!(path)); return { getSourceFile, @@ -228,7 +228,7 @@ namespace ts { const errorMessage = `${diagnosticCategoryName(diagnostic)} TS${diagnostic.code}: ${flattenDiagnosticMessageText(diagnostic.messageText, host.getNewLine())}${host.getNewLine()}`; if (diagnostic.file) { - const { line, character } = getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start); + const { line, character } = getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start!); // TODO: GH#18217 const fileName = diagnostic.file.fileName; const relativeFileName = convertToRelativePath(fileName, host.getCurrentDirectory(), fileName => host.getCanonicalFileName(fileName)); return `${relativeFileName}(${line + 1},${character + 1}): ` + errorMessage; @@ -276,8 +276,8 @@ namespace ts { let context = ""; if (diagnostic.file) { const { start, length, file } = diagnostic; - const { line: firstLine, character: firstLineChar } = getLineAndCharacterOfPosition(file, start); - const { line: lastLine, character: lastLineChar } = getLineAndCharacterOfPosition(file, start + length); + const { line: firstLine, character: firstLineChar } = getLineAndCharacterOfPosition(file, start!); // TODO: GH#18217 + const { line: lastLine, character: lastLineChar } = getLineAndCharacterOfPosition(file, start! + length!); const lastLineInFile = getLineAndCharacterOfPosition(file, file.text.length).line; const relativeFileName = host ? convertToRelativePath(file.fileName, host.getCurrentDirectory(), fileName => host.getCanonicalFileName(fileName)) : file.fileName; @@ -349,7 +349,7 @@ namespace ts { return output + host.getNewLine(); } - export function flattenDiagnosticMessageText(messageText: string | DiagnosticMessageChain, newLine: string): string { + export function flattenDiagnosticMessageText(messageText: string | DiagnosticMessageChain | undefined, newLine: string): string { if (isString(messageText)) { return messageText; } @@ -384,7 +384,7 @@ namespace ts { for (const name of names) { let result: T; if (cache.has(name)) { - result = cache.get(name); + result = cache.get(name)!; } else { cache.set(name, result = loader(name, containingFile)); @@ -407,7 +407,7 @@ namespace ts { program: Program | undefined, rootFileNames: string[], newOptions: CompilerOptions, - getSourceVersion: (path: Path) => string, + getSourceVersion: (path: Path) => string | undefined, fileExists: (fileName: string) => boolean, hasInvalidatedResolution: HasInvalidatedResolution, hasChangedAutomaticTypeDirectiveNames: boolean, @@ -461,7 +461,7 @@ namespace ts { /** * Determined if source file needs to be re-created even if its text hasn't changed */ - function shouldProgramCreateNewSourceFiles(program: Program, newOptions: CompilerOptions) { + function shouldProgramCreateNewSourceFiles(program: Program | undefined, newOptions: CompilerOptions) { // If any of these options change, we can't reuse old source file even if version match // The change in options like these could result in change in syntax tree change const oldOptions = program && program.getCompilerOptions(); @@ -505,9 +505,9 @@ namespace ts { export function createProgram(createProgramOptions: CreateProgramOptions): Program; export function createProgram(rootNames: ReadonlyArray, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray): Program; export function createProgram(rootNamesOrOptions: ReadonlyArray | CreateProgramOptions, _options?: CompilerOptions, _host?: CompilerHost, _oldProgram?: Program, _configFileParsingDiagnostics?: ReadonlyArray): Program { - const createProgramOptions = isArray(rootNamesOrOptions) ? createCreateProgramOptions(rootNamesOrOptions, _options, _host, _oldProgram, _configFileParsingDiagnostics) : rootNamesOrOptions; + const createProgramOptions = isArray(rootNamesOrOptions) ? createCreateProgramOptions(rootNamesOrOptions, _options!, _host, _oldProgram, _configFileParsingDiagnostics) : rootNamesOrOptions; // TODO: GH#18217 const { rootNames, options, configFileParsingDiagnostics, projectReferences } = createProgramOptions; - let { host, oldProgram } = createProgramOptions; + let { oldProgram } = createProgramOptions; let program: Program; let files: SourceFile[] = []; @@ -542,7 +542,7 @@ namespace ts { performance.mark("beforeProgram"); - host = host || createCompilerHost(options); + const host = createProgramOptions.host || createCompilerHost(options); const configParsingHost = parseConfigHostFromCompilerHost(host); let skipDefaultLib = options.noLib; @@ -554,14 +554,14 @@ namespace ts { // Map storing if there is emit blocking diagnostics for given input const hasEmitBlockingDiagnostics = createMap(); - let _compilerOptionsObjectLiteralSyntax: ObjectLiteralExpression; - let _referencesArrayLiteralSyntax: ArrayLiteralExpression; + let _compilerOptionsObjectLiteralSyntax: ObjectLiteralExpression | null | undefined; + let _referencesArrayLiteralSyntax: ArrayLiteralExpression | null | undefined; - let moduleResolutionCache: ModuleResolutionCache; + let moduleResolutionCache: ModuleResolutionCache | undefined; let resolveModuleNamesWorker: (moduleNames: string[], containingFile: string, reusedNames?: string[]) => ResolvedModuleFull[]; const hasInvalidatedResolution = host.hasInvalidatedResolution || returnFalse; if (host.resolveModuleNames) { - resolveModuleNamesWorker = (moduleNames, containingFile, reusedNames) => host.resolveModuleNames(Debug.assertEachDefined(moduleNames), containingFile, reusedNames).map(resolved => { + resolveModuleNamesWorker = (moduleNames, containingFile, reusedNames) => host.resolveModuleNames!(Debug.assertEachDefined(moduleNames), containingFile, reusedNames).map(resolved => { // An older host may have omitted extension, in which case we should infer it from the file extension of resolvedFileName. if (!resolved || (resolved as ResolvedModuleFull).extension !== undefined) { return resolved as ResolvedModuleFull; @@ -573,17 +573,17 @@ namespace ts { } else { moduleResolutionCache = createModuleResolutionCache(currentDirectory, x => host.getCanonicalFileName(x)); - const loader = (moduleName: string, containingFile: string) => resolveModuleName(moduleName, containingFile, options, host, moduleResolutionCache).resolvedModule; - resolveModuleNamesWorker = (moduleNames, containingFile) => loadWithLocalCache(Debug.assertEachDefined(moduleNames), containingFile, loader); + const loader = (moduleName: string, containingFile: string) => resolveModuleName(moduleName, containingFile, options, host, moduleResolutionCache).resolvedModule!; // TODO: GH#18217 + resolveModuleNamesWorker = (moduleNames, containingFile) => loadWithLocalCache(Debug.assertEachDefined(moduleNames), containingFile, loader); } let resolveTypeReferenceDirectiveNamesWorker: (typeDirectiveNames: string[], containingFile: string) => ResolvedTypeReferenceDirective[]; if (host.resolveTypeReferenceDirectives) { - resolveTypeReferenceDirectiveNamesWorker = (typeDirectiveNames, containingFile) => host.resolveTypeReferenceDirectives(Debug.assertEachDefined(typeDirectiveNames), containingFile); + resolveTypeReferenceDirectiveNamesWorker = (typeDirectiveNames, containingFile) => host.resolveTypeReferenceDirectives!(Debug.assertEachDefined(typeDirectiveNames), containingFile); } else { - const loader = (typesRef: string, containingFile: string) => resolveTypeReferenceDirective(typesRef, containingFile, options, host).resolvedTypeReferenceDirective; - resolveTypeReferenceDirectiveNamesWorker = (typeReferenceDirectiveNames, containingFile) => loadWithLocalCache(Debug.assertEachDefined(typeReferenceDirectiveNames), containingFile, loader); + const loader = (typesRef: string, containingFile: string) => resolveTypeReferenceDirective(typesRef, containingFile, options, host).resolvedTypeReferenceDirective!; // TODO: GH#18217 + resolveTypeReferenceDirectiveNamesWorker = (typeReferenceDirectiveNames, containingFile) => loadWithLocalCache(Debug.assertEachDefined(typeReferenceDirectiveNames), containingFile, loader); } // Map from a stringified PackageId to the source file with that id. @@ -595,7 +595,7 @@ namespace ts { let redirectTargetsSet = createMap(); const filesByName = createMap(); - let missingFilePaths: ReadonlyArray; + let missingFilePaths: ReadonlyArray | undefined; // stores 'filename -> file association' ignoring case // used to track cases when two file names differ only in casing const filesByNameIgnoreCase = host.useCaseSensitiveFileNames() ? createMap() : undefined; @@ -606,7 +606,7 @@ namespace ts { if (projectReferences) { for (const ref of projectReferences) { const parsedRef = parseProjectReferenceConfigFile(ref); - resolvedProjectReferences.push(parsedRef); + resolvedProjectReferences!.push(parsedRef); if (parsedRef) { if (parsedRef.commandLine.options.outFile) { const dtsOutfile = changeExtension(parsedRef.commandLine.options.outFile, ".d.ts"); @@ -677,7 +677,7 @@ namespace ts { getSourceFile, getSourceFileByPath, getSourceFiles: () => files, - getMissingFilePaths: () => missingFilePaths, + getMissingFilePaths: () => missingFilePaths!, // TODO: GH#18217 getCompilerOptions: () => options, getSyntacticDiagnostics, getOptionsDiagnostics, @@ -714,7 +714,7 @@ namespace ts { return program; - function getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string): ResolvedModuleWithFailedLookupLocations { + function getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string): ResolvedModuleWithFailedLookupLocations | undefined { return moduleResolutionCache && resolveModuleNameFromCache(moduleName, containingFile, moduleResolutionCache); } @@ -731,7 +731,7 @@ namespace ts { } else if (options.composite) { // Project compilations never infer their root from the input source paths - commonSourceDirectory = getDirectoryPath(normalizeSlashes(options.configFilePath)); + commonSourceDirectory = getDirectoryPath(normalizeSlashes(options.configFilePath!)); // TODO: GH#18217 checkSourceFilesBelongToPath(emittedFiles, commonSourceDirectory); } else { @@ -755,7 +755,7 @@ namespace ts { classifiableNames = createUnderscoreEscapedMap(); for (const sourceFile of files) { - copyEntries(sourceFile.classifiableNames, classifiableNames); + copyEntries(sourceFile.classifiableNames!, classifiableNames); } } @@ -766,7 +766,7 @@ namespace ts { program: Program | undefined; oldSourceFile: SourceFile | undefined; /** The collection of paths modified *since* the old program. */ - modifiedFilePaths: Path[]; + modifiedFilePaths: Path[] | undefined; } function resolveModuleNamesReusingOldState(moduleNames: string[], containingFile: string, file: SourceFile, oldProgramState: OldProgramState) { @@ -788,7 +788,7 @@ namespace ts { // it is safe to reuse resolutions from the earlier call. const result: ResolvedModuleFull[] = []; for (const moduleName of moduleNames) { - const resolvedModule = file.resolvedModules.get(moduleName); + const resolvedModule = file.resolvedModules.get(moduleName)!; result.push(resolvedModule); } return result; @@ -799,7 +799,7 @@ namespace ts { // With this information, we can infer some module resolutions without performing resolution. /** An ordered list of module names for which we cannot recover the resolution. */ - let unknownModuleNames: string[]; + let unknownModuleNames: string[] | undefined; /** * The indexing of elements in this list matches that of `moduleNames`. * @@ -809,8 +809,8 @@ namespace ts { * Needs to be reset to undefined before returning, * * ResolvedModuleFull instance: can be reused. */ - let result: ResolvedModuleFull[]; - let reusedNames: string[]; + let result: ResolvedModuleFull[] | undefined; + let reusedNames: string[] | undefined; /** A transient placeholder used to mark predicted resolution in the result list. */ const predictedToResolveToAmbientModuleMarker: ResolvedModuleFull = {}; @@ -818,7 +818,7 @@ namespace ts { const moduleName = moduleNames[i]; // If the source file is unchanged and doesnt have invalidated resolution, reuse the module resolutions if (file === oldSourceFile && !hasInvalidatedResolution(oldSourceFile.path)) { - const oldResolvedModule = oldSourceFile && oldSourceFile.resolvedModules.get(moduleName); + const oldResolvedModule = oldSourceFile && oldSourceFile.resolvedModules!.get(moduleName); if (oldResolvedModule) { if (isTraceEnabled(options, host)) { trace(host, Diagnostics.Reusing_resolution_of_module_0_to_file_1_from_old_program, moduleName, containingFile); @@ -869,7 +869,7 @@ namespace ts { // `result[i]` is either a `ResolvedModuleFull` or a marker. // If it is the former, we can leave it as is. if (result[i] === predictedToResolveToAmbientModuleMarker) { - result[i] = undefined; + result[i] = undefined!; // TODO: GH#18217 } } else { @@ -884,7 +884,7 @@ namespace ts { // If we change our policy of rechecking failed lookups on each program create, // we should adjust the value returned here. function moduleNameResolvesToAmbientModuleInNonModifiedFile(moduleName: string, oldProgramState: OldProgramState): boolean { - const resolutionToFile = getResolvedModule(oldProgramState.oldSourceFile, moduleName); + const resolutionToFile = getResolvedModule(oldProgramState.oldSourceFile!, moduleName); // TODO: GH#18217 const resolvedFile = resolutionToFile && oldProgramState.program && oldProgramState.program.getSourceFile(resolutionToFile.resolvedFileName); if (resolutionToFile && resolvedFile && !resolvedFile.externalModuleIndicator) { // In the old program, we resolved to an ambient module that was in the same @@ -927,7 +927,7 @@ namespace ts { return oldProgram.structureIsReused = StructureIsReused.Not; } - Debug.assert(!(oldProgram.structureIsReused & (StructureIsReused.Completely | StructureIsReused.SafeModules))); + Debug.assert(!(oldProgram.structureIsReused! & (StructureIsReused.Completely | StructureIsReused.SafeModules))); // there is an old program, check if we can reuse its structure const oldRootNames = oldProgram.getRootFileNames(); @@ -987,8 +987,8 @@ namespace ts { for (const oldSourceFile of oldSourceFiles) { let newSourceFile = host.getSourceFileByPath - ? host.getSourceFileByPath(oldSourceFile.fileName, oldSourceFile.path, options.target, /*onError*/ undefined, shouldCreateNewSourceFile) - : host.getSourceFile(oldSourceFile.fileName, options.target, /*onError*/ undefined, shouldCreateNewSourceFile); + ? host.getSourceFileByPath(oldSourceFile.fileName, oldSourceFile.path, options.target!, /*onError*/ undefined, shouldCreateNewSourceFile) + : host.getSourceFile(oldSourceFile.fileName, options.target!, /*onError*/ undefined, shouldCreateNewSourceFile); // TODO: GH#18217 if (!newSourceFile) { return oldProgram.structureIsReused = StructureIsReused.Not; @@ -1134,7 +1134,7 @@ namespace ts { for (let i = 0; i < newSourceFiles.length; i++) { filesByName.set(filePaths[i], newSourceFiles[i]); // Set the file as found during node modules search if it was found that way in old progra, - if (oldProgram.isSourceFileFromExternalLibrary(oldProgram.getSourceFileByPath(filePaths[i]))) { + if (oldProgram.isSourceFileFromExternalLibrary(oldProgram.getSourceFileByPath(filePaths[i])!)) { sourceFilesFoundSearchingNodeModules.set(filePaths[i], true); } } @@ -1185,7 +1185,7 @@ namespace ts { const nodes: InputFiles[] = []; for (let i = 0; i < projectReferences.length; i++) { const ref = projectReferences[i]; - const resolvedRefOpts = resolvedProjectReferences[i].commandLine; + const resolvedRefOpts = resolvedProjectReferences![i]!.commandLine; if (ref.prepend && resolvedRefOpts && resolvedRefOpts.options) { // Upstream project didn't have outFile set -- skip (error will have been issued earlier) if (!resolvedRefOpts.options.outFile) continue; @@ -1201,7 +1201,7 @@ namespace ts { } function isSourceFileFromExternalLibrary(file: SourceFile): boolean { - return sourceFilesFoundSearchingNodeModules.get(file.path); + return !!sourceFilesFoundSearchingNodeModules.get(file.path); } function isSourceFileDefaultLibrary(file: SourceFile): boolean { @@ -1220,7 +1220,7 @@ namespace ts { return equalityComparer(file.fileName, getDefaultLibraryFileName()); } else { - return forEach(options.lib, libFileName => equalityComparer(file.fileName, combinePaths(defaultLibraryPath, libFileName))); + return some(options.lib, libFileName => equalityComparer(file.fileName, combinePaths(defaultLibraryPath, libFileName))); } } @@ -1229,7 +1229,7 @@ namespace ts { } function dropDiagnosticsProducingTypeChecker() { - diagnosticsProducingTypeChecker = undefined; + diagnosticsProducingTypeChecker = undefined!; } function getTypeChecker() { @@ -1244,7 +1244,7 @@ namespace ts { return hasEmitBlockingDiagnostics.has(toPath(emitFileName)); } - function emitWorker(program: Program, sourceFile: SourceFile, writeFileCallback: WriteFileCallback, cancellationToken: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult { + function emitWorker(program: Program, sourceFile: SourceFile | undefined, writeFileCallback: WriteFileCallback | undefined, cancellationToken: CancellationToken | undefined, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult { let declarationDiagnostics: ReadonlyArray = []; if (!emitOnlyDtsFiles) { @@ -1294,7 +1294,7 @@ namespace ts { const emitResult = emitFiles( emitResolver, getEmitHost(writeFileCallback), - sourceFile, + sourceFile!, // TODO: GH#18217 emitOnlyDtsFiles, transformers, customTransformers && customTransformers.afterDeclarations @@ -1374,8 +1374,8 @@ namespace ts { // cancel when the user has made a change anyways. And, in that case, we (the // program instance) will get thrown away anyways. So trying to keep one of // these type checkers alive doesn't serve much purpose. - noDiagnosticsTypeChecker = undefined; - diagnosticsProducingTypeChecker = undefined; + noDiagnosticsTypeChecker = undefined!; + diagnosticsProducingTypeChecker = undefined!; } throw e; @@ -1386,7 +1386,7 @@ namespace ts { return getAndCacheDiagnostics(sourceFile, cancellationToken, cachedSemanticDiagnosticsForFile, getSemanticDiagnosticsForFileNoCache); } - function getSemanticDiagnosticsForFileNoCache(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] { + function getSemanticDiagnosticsForFileNoCache(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] | undefined { return runWithCancellationToken(() => { // If skipLibCheck is enabled, skip reporting errors if file is a declaration file. // If skipDefaultLibCheck is enabled, skip reporting errors if file contains a @@ -1429,7 +1429,7 @@ namespace ts { const { file, start } = diagnostic; if (file) { const lineStarts = getLineStarts(file); - let { line } = computeLineAndCharacterOfPosition(lineStarts, start); + let { line } = computeLineAndCharacterOfPosition(lineStarts, start!); // TODO: GH#18217 while (line > 0) { const previousLineText = file.text.slice(lineStarts[line - 1], lineStarts[line]); const result = ignoreDiagnosticCommentRegEx.exec(previousLineText); @@ -1646,7 +1646,7 @@ namespace ts { sourceFile: SourceFile | undefined, cancellationToken: CancellationToken, cache: DiagnosticCache, - getDiagnostics: (sourceFile: SourceFile, cancellationToken: CancellationToken) => T[], + getDiagnostics: (sourceFile: SourceFile, cancellationToken: CancellationToken) => T[] | undefined, ): ReadonlyArray { const cachedResult = sourceFile @@ -1656,7 +1656,7 @@ namespace ts { if (cachedResult) { return cachedResult; } - const result = getDiagnostics(sourceFile, cancellationToken) || emptyArray; + const result = getDiagnostics(sourceFile!, cancellationToken) || emptyArray; // TODO: GH#18217 if (sourceFile) { if (!cache.perFile) { cache.perFile = createMap(); @@ -1715,8 +1715,8 @@ namespace ts { // file.imports may not be undefined if there exists dynamic import let imports: StringLiteralLike[] | undefined; - let moduleAugmentations: (StringLiteral | Identifier)[]; - let ambientModules: string[]; + let moduleAugmentations: (StringLiteral | Identifier)[] | undefined; + let ambientModules: string[] | undefined; // If we are importing helpers, we need to add a synthetic reference to resolve the // helpers library. @@ -1867,7 +1867,7 @@ namespace ts { /** This has side effects through `findSourceFile`. */ function processSourceFile(fileName: string, isDefaultLib: boolean, packageId: PackageId | undefined, refFile?: SourceFile, refPos?: number, refEnd?: number): void { getSourceFileFromReferenceWorker(fileName, - fileName => findSourceFile(fileName, toPath(fileName), isDefaultLib, refFile, refPos, refEnd, packageId), + fileName => findSourceFile(fileName, toPath(fileName), isDefaultLib, refFile!, refPos!, refEnd!, packageId), // TODO: GH#18217 (diagnostic, ...args) => { fileProcessingDiagnostics.add(refFile !== undefined && refEnd !== undefined && refPos !== undefined ? createFileDiagnostic(refFile, refPos, refEnd - refPos, diagnostic, ...args) @@ -1893,12 +1893,12 @@ namespace ts { redirect.redirectInfo = { redirectTarget, unredirected }; Object.defineProperties(redirect, { id: { - get(this: SourceFile) { return this.redirectInfo.redirectTarget.id; }, - set(this: SourceFile, value: SourceFile["id"]) { this.redirectInfo.redirectTarget.id = value; }, + get(this: SourceFile) { return this.redirectInfo!.redirectTarget.id; }, + set(this: SourceFile, value: SourceFile["id"]) { this.redirectInfo!.redirectTarget.id = value; }, }, symbol: { - get(this: SourceFile) { return this.redirectInfo.redirectTarget.symbol; }, - set(this: SourceFile, value: SourceFile["symbol"]) { this.redirectInfo.redirectTarget.symbol = value; }, + get(this: SourceFile) { return this.redirectInfo!.redirectTarget.symbol; }, + set(this: SourceFile, value: SourceFile["symbol"]) { this.redirectInfo!.redirectTarget.symbol = value; }, }, }); return redirect; @@ -1953,7 +1953,7 @@ namespace ts { } // We haven't looked for this file, do so now and cache result - const file = host.getSourceFile(fileName, options.target, hostErrorMessage => { + const file = host.getSourceFile(fileName, options.target!, hostErrorMessage => { // TODO: GH#18217 if (refFile !== undefined && refPos !== undefined && refEnd !== undefined) { fileProcessingDiagnostics.add(createFileDiagnostic(refFile, refPos, refEnd - refPos, Diagnostics.Cannot_read_file_0_Colon_1, fileName, hostErrorMessage)); @@ -1969,7 +1969,7 @@ namespace ts { if (fileFromPackageId) { // Some other SourceFile already exists with this package name and version. // Instead of creating a duplicate, just redirect to the existing one. - const dupFile = createRedirectSourceFile(fileFromPackageId, file, fileName, path); + const dupFile = createRedirectSourceFile(fileFromPackageId, file!, fileName, path); // TODO: GH#18217 redirectTargetsSet.set(fileFromPackageId.path, true); filesByName.set(path, dupFile); sourceFileToPackageName.set(path, packageId.name); @@ -1995,12 +1995,12 @@ namespace ts { if (host.useCaseSensitiveFileNames()) { const pathLowerCase = path.toLowerCase(); // for case-sensitive file systems check if we've already seen some file with similar filename ignoring case - const existingFile = filesByNameIgnoreCase.get(pathLowerCase); + const existingFile = filesByNameIgnoreCase!.get(pathLowerCase); if (existingFile) { reportFileNamesDifferOnlyInCasingError(fileName, existingFile.fileName, refFile, refPos, refEnd); } else { - filesByNameIgnoreCase.set(pathLowerCase, file); + filesByNameIgnoreCase!.set(pathLowerCase, file); } } @@ -2080,7 +2080,7 @@ namespace ts { if (resolvedTypeReferenceDirective) { if (resolvedTypeReferenceDirective.primary) { // resolved from the primary path - processSourceFile(resolvedTypeReferenceDirective.resolvedFileName, /*isDefaultLib*/ false, resolvedTypeReferenceDirective.packageId, refFile, refPos, refEnd); + processSourceFile(resolvedTypeReferenceDirective.resolvedFileName!, /*isDefaultLib*/ false, resolvedTypeReferenceDirective.packageId, refFile, refPos, refEnd); // TODO: GH#18217 } else { // If we already resolved to this file, it must have been a secondary reference. Check file contents @@ -2088,9 +2088,9 @@ namespace ts { if (previousResolution) { // Don't bother reading the file again if it's the same file. if (resolvedTypeReferenceDirective.resolvedFileName !== previousResolution.resolvedFileName) { - const otherFileText = host.readFile(resolvedTypeReferenceDirective.resolvedFileName); - if (otherFileText !== getSourceFile(previousResolution.resolvedFileName).text) { - fileProcessingDiagnostics.add(createDiagnostic(refFile, refPos, refEnd, + const otherFileText = host.readFile(resolvedTypeReferenceDirective.resolvedFileName!); + if (otherFileText !== getSourceFile(previousResolution.resolvedFileName!)!.text) { + fileProcessingDiagnostics.add(createDiagnostic(refFile!, refPos!, refEnd!, // TODO: GH#18217 Diagnostics.Conflicting_definitions_for_0_found_at_1_and_2_Consider_installing_a_specific_version_of_this_library_to_resolve_the_conflict, typeReferenceDirective, resolvedTypeReferenceDirective.resolvedFileName, @@ -2103,12 +2103,12 @@ namespace ts { } else { // First resolution of this library - processSourceFile(resolvedTypeReferenceDirective.resolvedFileName, /*isDefaultLib*/ false, resolvedTypeReferenceDirective.packageId, refFile, refPos, refEnd); + processSourceFile(resolvedTypeReferenceDirective.resolvedFileName!, /*isDefaultLib*/ false, resolvedTypeReferenceDirective.packageId, refFile, refPos, refEnd); } } } else { - fileProcessingDiagnostics.add(createDiagnostic(refFile, refPos, refEnd, Diagnostics.Cannot_find_type_definition_file_for_0, typeReferenceDirective)); + fileProcessingDiagnostics.add(createDiagnostic(refFile!, refPos!, refEnd!, Diagnostics.Cannot_find_type_definition_file_for_0, typeReferenceDirective)); // TODO: GH#18217 } if (saveResolution) { @@ -2221,7 +2221,7 @@ namespace ts { function parseProjectReferenceConfigFile(ref: ProjectReference): { commandLine: ParsedCommandLine, sourceFile: SourceFile } | undefined { // The actual filename (i.e. add "/tsconfig.json" if necessary) - const refPath = resolveProjectReferencePath(host, ref); + const refPath = resolveProjectReferencePath(host, ref)!; // TODO: GH#18217 // An absolute path pointing to the containing directory of the config file const basePath = getNormalizedAbsolutePath(getDirectoryPath(refPath), host.getCurrentDirectory()); const sourceFile = host.getSourceFile(refPath, ScriptTarget.JSON) as JsonSourceFile; @@ -2234,14 +2234,14 @@ namespace ts { } function addProjectReferenceRedirects(referencedProject: ParsedCommandLine, target: Map) { - const rootDir = normalizePath(referencedProject.options.rootDir || getDirectoryPath(referencedProject.options.configFilePath)); + const rootDir = normalizePath(referencedProject.options.rootDir || getDirectoryPath(referencedProject.options.configFilePath!)); // TODO: GH#18217 target.set(rootDir, getDeclarationOutputDirectory(referencedProject)); } function getDeclarationOutputDirectory(proj: ParsedCommandLine) { return proj.options.declarationDir || proj.options.outDir || - getDirectoryPath(proj.options.configFilePath); + getDirectoryPath(proj.options.configFilePath!); // TODO: GH#18217 } function verifyCompilerOptions() { @@ -2289,7 +2289,7 @@ namespace ts { if (projectReferences) { for (let i = 0; i < projectReferences.length; i++) { const ref = projectReferences[i]; - const resolvedRefOpts = resolvedProjectReferences[i] && resolvedProjectReferences[i].commandLine.options; + const resolvedRefOpts = resolvedProjectReferences![i] && resolvedProjectReferences![i]!.commandLine.options; if (resolvedRefOpts === undefined) { createDiagnosticForReference(i, Diagnostics.File_0_does_not_exist, ref.path); continue; @@ -2409,7 +2409,7 @@ namespace ts { } else if (firstNonAmbientExternalModuleSourceFile && languageVersion < ScriptTarget.ES2015 && options.module === ModuleKind.None) { // We cannot use createDiagnosticFromNode because nodes do not have parents yet - const span = getErrorSpanForNode(firstNonAmbientExternalModuleSourceFile, firstNonAmbientExternalModuleSourceFile.externalModuleIndicator); + const span = getErrorSpanForNode(firstNonAmbientExternalModuleSourceFile, firstNonAmbientExternalModuleSourceFile.externalModuleIndicator!); programDiagnostics.add(createFileDiagnostic(firstNonAmbientExternalModuleSourceFile, span.start, span.length, Diagnostics.Cannot_use_imports_exports_or_module_augmentations_when_module_is_none)); } @@ -2419,7 +2419,7 @@ namespace ts { createDiagnosticForOptionName(Diagnostics.Only_amd_and_system_modules_are_supported_alongside_0, options.out ? "out" : "outFile", "module"); } else if (options.module === undefined && firstNonAmbientExternalModuleSourceFile) { - const span = getErrorSpanForNode(firstNonAmbientExternalModuleSourceFile, firstNonAmbientExternalModuleSourceFile.externalModuleIndicator); + const span = getErrorSpanForNode(firstNonAmbientExternalModuleSourceFile, firstNonAmbientExternalModuleSourceFile.externalModuleIndicator!); programDiagnostics.add(createFileDiagnostic(firstNonAmbientExternalModuleSourceFile, span.start, span.length, Diagnostics.Cannot_compile_modules_using_option_0_unless_the_module_flag_is_amd_or_system, options.out ? "out" : "outFile")); } } @@ -2493,12 +2493,12 @@ namespace ts { } // Verify that all the emit files are unique and don't overwrite input files - function verifyEmitFilePath(emitFileName: string, emitFilesSeen: Map) { + function verifyEmitFilePath(emitFileName: string | undefined, emitFilesSeen: Map) { if (emitFileName) { const emitFilePath = toPath(emitFileName); // Report error if the output overwrites input file if (filesByName.has(emitFilePath)) { - let chain: DiagnosticMessageChain; + let chain: DiagnosticMessageChain | undefined; if (!options.configFilePath) { // The program is from either an inferred project or an external project chain = chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Adding_a_tsconfig_json_file_will_help_organize_projects_that_contain_both_TypeScript_and_JavaScript_files_Learn_more_at_https_Colon_Slash_Slashaka_ms_Slashtsconfig); @@ -2526,9 +2526,9 @@ namespace ts { for (const pathProp of pathsSyntax) { if (isObjectLiteralExpression(pathProp.initializer)) { for (const keyProps of getPropertyAssignment(pathProp.initializer, key)) { - if (isArrayLiteralExpression(keyProps.initializer) && - keyProps.initializer.elements.length > valueIndex) { - programDiagnostics.add(createDiagnosticForNodeInSourceFile(options.configFile, keyProps.initializer.elements[valueIndex], message, arg0, arg1, arg2)); + const initializer = keyProps.initializer; + if (isArrayLiteralExpression(initializer) && initializer.elements.length > valueIndex) { + programDiagnostics.add(createDiagnosticForNodeInSourceFile(options.configFile!, initializer.elements[valueIndex], message, arg0, arg1, arg2)); needCompilerDiagnostic = false; } } @@ -2586,7 +2586,7 @@ namespace ts { programDiagnostics.add(createCompilerDiagnostic(message, arg0, arg1)); } - function createDiagnosticForOption(onKey: boolean, option1: string, option2: string, message: DiagnosticMessage, arg0: string | number, arg1?: string | number, arg2?: string | number) { + function createDiagnosticForOption(onKey: boolean, option1: string, option2: string | undefined, message: DiagnosticMessage, arg0: string | number, arg1?: string | number, arg2?: string | number) { const compilerOptionsObjectLiteralSyntax = getCompilerOptionsObjectLiteralSyntax(); const needCompilerDiagnostic = !compilerOptionsObjectLiteralSyntax || !createOptionDiagnosticInObjectLiteralSyntax(compilerOptionsObjectLiteralSyntax, onKey, option1, option2, message, arg0, arg1, arg2); @@ -2600,7 +2600,7 @@ namespace ts { if (_referencesArrayLiteralSyntax === undefined) { _referencesArrayLiteralSyntax = null; // tslint:disable-line:no-null-keyword if (options.configFile) { - const jsonObjectLiteral = getTsConfigObjectLiteralExpression(options.configFile); + const jsonObjectLiteral = getTsConfigObjectLiteralExpression(options.configFile)!; // TODO: GH#18217 for (const prop of getPropertyAssignment(jsonObjectLiteral, "references")) { if (isArrayLiteralExpression(prop.initializer)) { _referencesArrayLiteralSyntax = prop.initializer; @@ -2628,20 +2628,21 @@ namespace ts { return _compilerOptionsObjectLiteralSyntax; } - function createOptionDiagnosticInObjectLiteralSyntax(objectLiteral: ObjectLiteralExpression, onKey: boolean, key1: string, key2: string, message: DiagnosticMessage, arg0: string | number, arg1?: string | number, arg2?: string | number): boolean { + function createOptionDiagnosticInObjectLiteralSyntax(objectLiteral: ObjectLiteralExpression, onKey: boolean, key1: string, key2: string | undefined, message: DiagnosticMessage, arg0: string | number, arg1?: string | number, arg2?: string | number): boolean { const props = getPropertyAssignment(objectLiteral, key1, key2); for (const prop of props) { - programDiagnostics.add(createDiagnosticForNodeInSourceFile(options.configFile, onKey ? prop.name : prop.initializer, message, arg0, arg1, arg2)); + programDiagnostics.add(createDiagnosticForNodeInSourceFile(options.configFile!, onKey ? prop.name : prop.initializer, message, arg0, arg1, arg2)); } return !!props.length; } - function createOptionDiagnosticInArrayLiteralSyntax(arrayLiteral: ArrayLiteralExpression, index: number, message: DiagnosticMessage, arg0: string | number, arg1?: string | number, arg2?: string | number): boolean { + function createOptionDiagnosticInArrayLiteralSyntax(arrayLiteral: ArrayLiteralExpression, index: number, message: DiagnosticMessage, arg0: string | number | undefined, arg1?: string | number, arg2?: string | number): boolean { if (arrayLiteral.elements.length <= index) { // Out-of-bounds return false; } - programDiagnostics.add(createDiagnosticForNodeInSourceFile(options.configFile, arrayLiteral.elements[index], message, arg0, arg1, arg2)); + programDiagnostics.add(createDiagnosticForNodeInSourceFile(options.configFile!, arrayLiteral.elements[index], message, arg0, arg1, arg2)); + return false; // TODO: GH#18217 This function always returns `false`!` } function blockEmittingOfFile(emitFileName: string, diag: Diagnostic) { @@ -2649,7 +2650,7 @@ namespace ts { programDiagnostics.add(diag); } - function isEmittedFile(file: string) { + function isEmittedFile(file: string): boolean { if (options.noEmit) { return false; } diff --git a/src/compiler/resolutionCache.ts b/src/compiler/resolutionCache.ts index dea5463b2ffef..8b48aa5c0414e 100644 --- a/src/compiler/resolutionCache.ts +++ b/src/compiler/resolutionCache.ts @@ -3,10 +3,10 @@ namespace ts { /** This is the cache of module/typedirectives resolution that can be retained across program */ export interface ResolutionCache { startRecordingFilesWithChangedResolutions(): void; - finishRecordingFilesWithChangedResolutions(): Path[]; + finishRecordingFilesWithChangedResolutions(): Path[] | undefined; resolveModuleNames(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined): ResolvedModuleFull[]; - getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string): ResolvedModuleWithFailedLookupLocations; + getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string): ResolvedModuleWithFailedLookupLocations | undefined; resolveTypeReferenceDirectives(typeDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[]; invalidateResolutionOfFile(filePath: Path): void; @@ -76,13 +76,13 @@ namespace ts { type GetResolutionWithResolvedFileName = (resolution: T) => R | undefined; - export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootDirForResolution: string, logChangesWhenResolvingModule: boolean): ResolutionCache { + export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootDirForResolution: string | undefined, logChangesWhenResolvingModule: boolean): ResolutionCache { let filesWithChangedSetOfUnresolvedImports: Path[] | undefined; let filesWithInvalidatedResolutions: Map | undefined; let filesWithInvalidatedNonRelativeUnresolvedImports: Map> | undefined; let allFilesHaveInvalidatedResolution = false; - const getCurrentDirectory = memoize(() => resolutionHost.getCurrentDirectory()); + const getCurrentDirectory = memoize(() => resolutionHost.getCurrentDirectory!()); // TODO: GH#18217 const cachedDirectoryStructureHost = resolutionHost.getCachedDirectoryStructureHost(); // The resolvedModuleNames and resolvedTypeReferenceDirectives are the cache of resolutions per file. @@ -112,7 +112,7 @@ namespace ts { const directoryWatchesOfFailedLookups = createMap(); const rootDir = rootDirForResolution && removeTrailingDirectorySeparator(getNormalizedAbsolutePath(rootDirForResolution, getCurrentDirectory())); - const rootPath = rootDir && resolutionHost.toPath(rootDir); + const rootPath = (rootDir && resolutionHost.toPath(rootDir)) as Path; // TODO: GH#18217 // TypeRoot watches for the types that get added as part of getAutomaticTypeDirectiveNames const typeRootsWatches = createMap(); @@ -144,7 +144,7 @@ namespace ts { return resolution.resolvedTypeReferenceDirective; } - function isInDirectoryPath(dir: Path, file: Path) { + function isInDirectoryPath(dir: Path | undefined, file: Path) { if (dir === undefined || file.length <= dir.length) { return false; } @@ -173,14 +173,14 @@ namespace ts { return collected; } - function isFileWithInvalidatedNonRelativeUnresolvedImports(path: Path) { + function isFileWithInvalidatedNonRelativeUnresolvedImports(path: Path): boolean { if (!filesWithInvalidatedNonRelativeUnresolvedImports) { return false; } // Invalidated if file has unresolved imports const value = filesWithInvalidatedNonRelativeUnresolvedImports.get(path); - return value && !!value.length; + return !!value && !!value.length; } function createHasInvalidatedResolution(forceAllFilesAsInvalidated?: boolean): HasInvalidatedResolution { @@ -191,7 +191,7 @@ namespace ts { } const collected = filesWithInvalidatedResolutions; filesWithInvalidatedResolutions = undefined; - return path => (collected && collected.has(path)) || + return path => (!!collected && collected.has(path)) || isFileWithInvalidatedNonRelativeUnresolvedImports(path); } @@ -247,7 +247,7 @@ namespace ts { logChanges: boolean): R[] { const path = resolutionHost.toPath(containingFile); - const resolutionsInFile = cache.get(path) || cache.set(path, createMap()).get(path); + const resolutionsInFile = cache.get(path) || cache.set(path, createMap()).get(path)!; const dirPath = getDirectoryPath(path); let perDirectoryResolution = perDirectoryCache.get(dirPath); if (!perDirectoryResolution) { @@ -289,7 +289,7 @@ namespace ts { } Debug.assert(resolution !== undefined && !resolution.isInvalidated); seenNamesInFile.set(name, true); - resolvedModules.push(getResolutionWithResolvedFileName(resolution)); + resolvedModules.push(getResolutionWithResolvedFileName(resolution)!); // TODO: GH#18217 } // Stop watching and remove the unused name @@ -302,7 +302,7 @@ namespace ts { return resolvedModules; - function resolutionIsEqualTo(oldResolution: T, newResolution: T): boolean { + function resolutionIsEqualTo(oldResolution: T | undefined, newResolution: T | undefined): boolean { if (oldResolution === newResolution) { return true; } @@ -381,7 +381,7 @@ namespace ts { function getDirectoryToWatchFailedLookupLocation(failedLookupLocation: string, failedLookupLocationPath: Path): DirectoryOfFailedLookupWatch { if (isInDirectoryPath(rootPath, failedLookupLocationPath)) { - return { dir: rootDir, dirPath: rootPath }; + return { dir: rootDir!, dirPath: rootPath }; // TODO: GH#18217 } return getDirectoryToWatchFromFailedLookupLocationDirectory( @@ -457,7 +457,7 @@ namespace ts { } if (setAtRoot) { - setDirectoryWatcher(rootDir, rootPath); + setDirectoryWatcher(rootDir!, rootPath); // TODO: GH#18217 } } @@ -519,14 +519,14 @@ namespace ts { } function removeDirectoryWatcher(dirPath: string, subDirectory?: Path) { - const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath); + const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath)!; if (subDirectory) { - const existing = dirWatcher.subDirectoryMap.get(subDirectory); + const existing = dirWatcher.subDirectoryMap!.get(subDirectory)!; if (existing === 1) { - dirWatcher.subDirectoryMap.delete(subDirectory); + dirWatcher.subDirectoryMap!.delete(subDirectory); } else { - dirWatcher.subDirectoryMap.set(subDirectory, existing - 1); + dirWatcher.subDirectoryMap!.set(subDirectory, existing - 1); } } // Do not close the watcher yet since it might be needed by other failed lookup locations. @@ -589,10 +589,10 @@ namespace ts { seen.set(dirPath, seenInDir); } resolutions.forEach((resolution, name) => { - if (seenInDir.has(name)) { + if (seenInDir!.has(name)) { return; } - seenInDir.set(name, true); + seenInDir!.set(name, true); if (!resolution.isInvalidated && isInvalidatedResolution(resolution, getResolutionWithResolvedFileName)) { // Mark the file as needing re-evaluation of module resolution instead of using it blindly. resolution.isInvalidated = true; @@ -626,7 +626,7 @@ namespace ts { // Resolution is invalidated if the resulting file name is same as the deleted file path (resolution, getResolutionWithResolvedFileName) => { const result = getResolutionWithResolvedFileName(resolution); - return result && resolutionHost.toPath(result.resolvedFileName) === filePath; + return !!result && resolutionHost.toPath(result.resolvedFileName!) === filePath; // TODO: GH#18217 } ); } @@ -689,7 +689,7 @@ namespace ts { return rootPath; } const { dirPath, ignore } = getDirectoryToWatchFromFailedLookupLocationDirectory(typeRoot, typeRootPath); - return !ignore && directoryWatchesOfFailedLookups.has(dirPath) && dirPath; + return !ignore && directoryWatchesOfFailedLookups.has(dirPath) ? dirPath : undefined; } function createTypeRootsWatch(typeRootPath: Path, typeRoot: string): FileWatcher { diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 1f0c097d22aa5..8963285dc7ae3 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -37,8 +37,8 @@ namespace ts { getText(): string; // Sets the text for the scanner to scan. An optional subrange starting point and length // can be provided to have the scanner only scan a portion of the text. - setText(text: string, start?: number, length?: number): void; - setOnError(onError: ErrorCallback): void; + setText(text: string | undefined, start?: number, length?: number): void; + setOnError(onError: ErrorCallback | undefined): void; setScriptTarget(scriptTarget: ScriptTarget): void; setLanguageVariant(variant: LanguageVariant): void; setTextPos(textPos: number): void; @@ -266,14 +266,14 @@ namespace ts { return false; } - /* @internal */ export function isUnicodeIdentifierStart(code: number, languageVersion: ScriptTarget) { - return languageVersion >= ScriptTarget.ES5 ? + /* @internal */ export function isUnicodeIdentifierStart(code: number, languageVersion: ScriptTarget | undefined) { + return languageVersion! >= ScriptTarget.ES5 ? lookupInUnicodeMap(code, unicodeES5IdentifierStart) : lookupInUnicodeMap(code, unicodeES3IdentifierStart); } - function isUnicodeIdentifierPart(code: number, languageVersion: ScriptTarget) { - return languageVersion >= ScriptTarget.ES5 ? + function isUnicodeIdentifierPart(code: number, languageVersion: ScriptTarget | undefined) { + return languageVersion! >= ScriptTarget.ES5 ? lookupInUnicodeMap(code, unicodeES5IdentifierPart) : lookupInUnicodeMap(code, unicodeES3IdentifierPart); } @@ -601,7 +601,7 @@ namespace ts { } function scanShebangTrivia(text: string, pos: number) { - const shebang = shebangTriviaRegex.exec(text)[0]; + const shebang = shebangTriviaRegex.exec(text)![0]; pos = pos + shebang.length; return pos; } @@ -626,11 +626,11 @@ namespace ts { * @returns If "reduce" is true, the accumulated value. If "reduce" is false, the first truthy * return value of the callback. */ - function iterateCommentRanges(reduce: boolean, text: string, pos: number, trailing: boolean, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T, memo: U) => U, state: T, initial?: U): U { - let pendingPos: number; - let pendingEnd: number; - let pendingKind: CommentKind; - let pendingHasTrailingNewLine: boolean; + function iterateCommentRanges(reduce: boolean, text: string, pos: number, trailing: boolean, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T, memo: U | undefined) => U, state: T, initial?: U): U | undefined { + let pendingPos!: number; + let pendingEnd!: number; + let pendingKind!: CommentKind; + let pendingHasTrailingNewLine!: boolean; let hasPendingCommentRange = false; let collecting = trailing || pos === 0; let accumulator = initial; @@ -769,20 +769,20 @@ namespace ts { } } - export function isIdentifierStart(ch: number, languageVersion: ScriptTarget): boolean { + export function isIdentifierStart(ch: number, languageVersion: ScriptTarget | undefined): boolean { return ch >= CharacterCodes.A && ch <= CharacterCodes.Z || ch >= CharacterCodes.a && ch <= CharacterCodes.z || ch === CharacterCodes.$ || ch === CharacterCodes._ || ch > CharacterCodes.maxAsciiCharacter && isUnicodeIdentifierStart(ch, languageVersion); } - export function isIdentifierPart(ch: number, languageVersion: ScriptTarget): boolean { + export function isIdentifierPart(ch: number, languageVersion: ScriptTarget | undefined): boolean { return ch >= CharacterCodes.A && ch <= CharacterCodes.Z || ch >= CharacterCodes.a && ch <= CharacterCodes.z || ch >= CharacterCodes._0 && ch <= CharacterCodes._9 || ch === CharacterCodes.$ || ch === CharacterCodes._ || ch > CharacterCodes.maxAsciiCharacter && isUnicodeIdentifierPart(ch, languageVersion); } /* @internal */ - export function isIdentifierText(name: string, languageVersion: ScriptTarget): boolean { + export function isIdentifierText(name: string, languageVersion: ScriptTarget | undefined): boolean { if (!isIdentifierStart(name.charCodeAt(0), languageVersion)) { return false; } @@ -800,13 +800,16 @@ namespace ts { export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean, languageVariant = LanguageVariant.Standard, - text?: string, + textInitial?: string, onError?: ErrorCallback, start?: number, length?: number): Scanner { + let text = textInitial!; + // Current position (end position of text of current token) let pos: number; + // end of text let end: number; @@ -817,7 +820,7 @@ namespace ts { let tokenPos: number; let token: SyntaxKind; - let tokenValue: string; + let tokenValue!: string; let tokenFlags: TokenFlags; setText(text, start, length); @@ -907,8 +910,8 @@ namespace ts { function scanNumber(): string { const start = pos; const mainFragment = scanNumberFragment(); - let decimalFragment: string; - let scientificFragment: string; + let decimalFragment: string | undefined; + let scientificFragment: string | undefined; if (text.charCodeAt(pos) === CharacterCodes.dot) { pos++; decimalFragment = scanNumberFragment(); @@ -1285,7 +1288,7 @@ namespace ts { if (len >= 2 && len <= 11) { const ch = tokenValue.charCodeAt(0); if (ch >= CharacterCodes.a && ch <= CharacterCodes.z) { - token = textToToken.get(tokenValue); + token = textToToken.get(tokenValue)!; if (token !== undefined) { return token; } @@ -2045,13 +2048,13 @@ namespace ts { return text; } - function setText(newText: string, start: number, length: number) { + function setText(newText: string | undefined, start: number | undefined, length: number | undefined) { text = newText || ""; - end = length === undefined ? text.length : start + length; + end = length === undefined ? text.length : start! + length; setTextPos(start || 0); } - function setOnError(errorCallback: ErrorCallback) { + function setOnError(errorCallback: ErrorCallback | undefined) { onError = errorCallback; } @@ -2069,7 +2072,7 @@ namespace ts { startPos = textPos; tokenPos = textPos; token = SyntaxKind.Unknown; - tokenValue = undefined; + tokenValue = undefined!; tokenFlags = 0; } } diff --git a/src/compiler/sourcemap.ts b/src/compiler/sourcemap.ts index 6251f1963fad7..a274404f320c9 100644 --- a/src/compiler/sourcemap.ts +++ b/src/compiler/sourcemap.ts @@ -8,7 +8,7 @@ namespace ts { * @param sourceMapFilePath The path to the output source map file. * @param sourceFileOrBundle The input source file or bundle for the program. */ - initialize(filePath: string, sourceMapFilePath: string, sourceFileOrBundle: SourceFile | Bundle, sourceMapOutput?: SourceMapData[]): void; + initialize(filePath: string, sourceMapFilePath: string | undefined, sourceFileOrBundle: SourceFile | Bundle, sourceMapOutput?: SourceMapData[]): void; /** * Reset the SourceMapWriter to an empty state. @@ -90,13 +90,13 @@ namespace ts { let sourceMapSourceIndex: number; // Last recorded and encoded spans - let lastRecordedSourceMapSpan: SourceMapSpan; - let lastEncodedSourceMapSpan: SourceMapSpan; - let lastEncodedNameIndex: number; + let lastRecordedSourceMapSpan: SourceMapSpan | undefined; + let lastEncodedSourceMapSpan: SourceMapSpan | undefined; + let lastEncodedNameIndex: number | undefined; // Source map data let sourceMapData: SourceMapData; - let sourceMapDataList: SourceMapData[]; + let sourceMapDataList: SourceMapData[] | undefined; let disabled: boolean = !(compilerOptions.sourceMap || compilerOptions.inlineSourceMap); return { @@ -134,8 +134,8 @@ namespace ts { } sourceMapDataList = outputSourceMapDataList; - currentSource = undefined; - currentSourceText = undefined; + currentSource = undefined!; + currentSourceText = undefined!; // Current source map file and its index in the sources list sourceMapSourceIndex = -1; @@ -148,7 +148,7 @@ namespace ts { // Initialize source map data sourceMapData = { sourceMapFilePath, - jsSourceMappingURL: !compilerOptions.inlineSourceMap ? getBaseFileName(normalizeSlashes(sourceMapFilePath)) : undefined, + jsSourceMappingURL: !compilerOptions.inlineSourceMap ? getBaseFileName(normalizeSlashes(sourceMapFilePath)) : undefined!, // TODO: GH#18217 sourceMapFile: getBaseFileName(normalizeSlashes(filePath)), sourceMapSourceRoot: compilerOptions.sourceRoot || "", sourceMapSources: [], @@ -206,14 +206,14 @@ namespace ts { sourceMapDataList.push(sourceMapData); } - currentSource = undefined; - sourceMapDir = undefined; - sourceMapSourceIndex = undefined; + currentSource = undefined!; + sourceMapDir = undefined!; + sourceMapSourceIndex = undefined!; lastRecordedSourceMapSpan = undefined; - lastEncodedSourceMapSpan = undefined; + lastEncodedSourceMapSpan = undefined!; lastEncodedNameIndex = undefined; - sourceMapData = undefined; - sourceMapDataList = undefined; + sourceMapData = undefined!; + sourceMapDataList = undefined!; } // Encoding for sourcemap span @@ -222,9 +222,9 @@ namespace ts { return; } - let prevEncodedEmittedColumn = lastEncodedSourceMapSpan.emittedColumn; + let prevEncodedEmittedColumn = lastEncodedSourceMapSpan!.emittedColumn; // Line/Comma delimiters - if (lastEncodedSourceMapSpan.emittedLine === lastRecordedSourceMapSpan.emittedLine) { + if (lastEncodedSourceMapSpan!.emittedLine === lastRecordedSourceMapSpan.emittedLine) { // Emit comma to separate the entry if (sourceMapData.sourceMapMappings) { sourceMapData.sourceMapMappings += ","; @@ -232,7 +232,7 @@ namespace ts { } else { // Emit line delimiters - for (let encodedLine = lastEncodedSourceMapSpan.emittedLine; encodedLine < lastRecordedSourceMapSpan.emittedLine; encodedLine++) { + for (let encodedLine = lastEncodedSourceMapSpan!.emittedLine; encodedLine < lastRecordedSourceMapSpan.emittedLine; encodedLine++) { sourceMapData.sourceMapMappings += ";"; } prevEncodedEmittedColumn = 1; @@ -242,18 +242,18 @@ namespace ts { sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.emittedColumn - prevEncodedEmittedColumn); // 2. Relative sourceIndex - sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceIndex - lastEncodedSourceMapSpan.sourceIndex); + sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceIndex - lastEncodedSourceMapSpan!.sourceIndex); // 3. Relative sourceLine 0 based - sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceLine - lastEncodedSourceMapSpan.sourceLine); + sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceLine - lastEncodedSourceMapSpan!.sourceLine); // 4. Relative sourceColumn 0 based - sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceColumn - lastEncodedSourceMapSpan.sourceColumn); + sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceColumn - lastEncodedSourceMapSpan!.sourceColumn); // 5. Relative namePosition 0 based - if (lastRecordedSourceMapSpan.nameIndex >= 0) { + if (lastRecordedSourceMapSpan.nameIndex! >= 0) { Debug.assert(false, "We do not support name index right now, Make sure to update updateLastEncodedAndRecordedSpans when we start using this"); - sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.nameIndex - lastEncodedNameIndex); + sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.nameIndex! - lastEncodedNameIndex!); lastEncodedNameIndex = lastRecordedSourceMapSpan.nameIndex; } @@ -334,7 +334,7 @@ namespace ts { if (node) { const emitNode = node.emitNode; - const emitFlags = emitNode && emitNode.flags; + const emitFlags = emitNode && emitNode.flags || EmitFlags.None; const range = emitNode && emitNode.sourceMapRange; const { pos, end } = range || node; let source = range && range.source; @@ -386,7 +386,7 @@ namespace ts { } const emitNode = node && node.emitNode; - const emitFlags = emitNode && emitNode.flags; + const emitFlags = emitNode && emitNode.flags || EmitFlags.None; const range = emitNode && emitNode.tokenSourceMapRanges && emitNode.tokenSourceMapRanges[token]; tokenPos = skipSourceTrivia(range ? range.pos : tokenPos); @@ -437,7 +437,7 @@ namespace ts { sourceMapData.inputSourceFileNames.push(currentSource.fileName); if (compilerOptions.inlineSources) { - sourceMapData.sourceMapSourcesContent.push(currentSource.text); + sourceMapData.sourceMapSourcesContent!.push(currentSource.text); } } } @@ -447,7 +447,7 @@ namespace ts { */ function getText() { if (disabled) { - return; + return undefined!; // TODO: GH#18217 } encodeLastRecordedSourceMapSpan(); @@ -468,7 +468,7 @@ namespace ts { */ function getSourceMappingURL() { if (disabled) { - return; + return undefined!; // TODO: GH#18217 } if (compilerOptions.inlineSourceMap) { diff --git a/src/compiler/symbolWalker.ts b/src/compiler/symbolWalker.ts index fed5f15f79f0c..5d41fa15b122b 100644 --- a/src/compiler/symbolWalker.ts +++ b/src/compiler/symbolWalker.ts @@ -8,8 +8,8 @@ namespace ts { resolveStructuredTypeMembers: (type: ObjectType) => ResolvedType, getTypeOfSymbol: (sym: Symbol) => Type, getResolvedSymbol: (node: Node) => Symbol, - getIndexTypeOfStructuredType: (type: Type, kind: IndexKind) => Type, - getConstraintFromTypeParameter: (typeParameter: TypeParameter) => Type, + getIndexTypeOfStructuredType: (type: Type, kind: IndexKind) => Type | undefined, + getConstraintFromTypeParameter: (typeParameter: TypeParameter) => Type | undefined, getFirstIdentifier: (node: EntityNameOrEntityNameExpression) => Identifier) { return getSymbolWalker; @@ -41,7 +41,7 @@ namespace ts { }, }; - function visitType(type: Type): void { + function visitType(type: Type | undefined): void { if (!type) { return; } @@ -157,13 +157,13 @@ namespace ts { } } - function visitSymbol(symbol: Symbol): boolean { + function visitSymbol(symbol: Symbol | undefined): boolean { if (!symbol) { - return; + return false; } const symbolId = getSymbolId(symbol); if (visitedSymbols[symbolId]) { - return; + return false; } visitedSymbols[symbolId] = symbol; if (!accept(symbol)) { @@ -172,7 +172,7 @@ namespace ts { const t = getTypeOfSymbol(symbol); visitType(t); // Should handle members on classes and such if (symbol.flags & SymbolFlags.HasExports) { - symbol.exports.forEach(visitSymbol); + symbol.exports!.forEach(visitSymbol); } forEach(symbol.declarations, d => { // Type queries are too far resolved when we just visit the symbol's type @@ -185,6 +185,7 @@ namespace ts { visitSymbol(entity); } }); + return false; } } } diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 05620afadfca4..91e5a48dc05b3 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -50,11 +50,11 @@ namespace ts { /* @internal */ export function watchFileUsingPriorityPollingInterval(host: System, fileName: string, callback: FileWatcherCallback, watchPriority: PollingInterval): FileWatcher { - return host.watchFile(fileName, callback, pollingInterval(watchPriority)); + return host.watchFile!(fileName, callback, pollingInterval(watchPriority)); } /* @internal */ - export type HostWatchFile = (fileName: string, callback: FileWatcherCallback, pollingInterval: PollingInterval) => FileWatcher; + export type HostWatchFile = (fileName: string, callback: FileWatcherCallback, pollingInterval: PollingInterval | undefined) => FileWatcher; /* @internal */ export type HostWatchDirectory = (fileName: string, callback: DirectoryWatcherCallback, recursive?: boolean) => FileWatcher; @@ -119,7 +119,7 @@ namespace ts { return false; function setLevel(level: keyof Levels) { - levels[level] = customLevels[level] || levels[level]; + levels[level] = customLevels![level] || levels[level]; } } @@ -171,7 +171,7 @@ namespace ts { } function createPollingIntervalQueue(pollingInterval: PollingInterval): PollingIntervalQueue { - const queue = [] as PollingIntervalQueue; + const queue = [] as WatchedFile[] as PollingIntervalQueue; queue.pollingInterval = pollingInterval; queue.pollIndex = 0; queue.pollScheduled = false; @@ -203,7 +203,7 @@ namespace ts { } } - function pollQueue(queue: WatchedFile[], pollingInterval: PollingInterval, pollIndex: number, chunkSize: number) { + function pollQueue(queue: (WatchedFile | undefined)[], pollingInterval: PollingInterval, pollIndex: number, chunkSize: number) { // Max visit would be all elements of the queue let needsVisit = queue.length; let definedValueCopyToIndex = pollIndex; @@ -300,11 +300,11 @@ namespace ts { } function scheduleNextPoll(pollingInterval: PollingInterval) { - pollingIntervalQueue(pollingInterval).pollScheduled = host.setTimeout(pollingInterval === PollingInterval.Low ? pollLowPollingIntervalQueue : pollPollingIntervalQueue, pollingInterval, pollingIntervalQueue(pollingInterval)); + pollingIntervalQueue(pollingInterval).pollScheduled = host.setTimeout!(pollingInterval === PollingInterval.Low ? pollLowPollingIntervalQueue : pollPollingIntervalQueue, pollingInterval, pollingIntervalQueue(pollingInterval)); } function getModifiedTime(fileName: string) { - return host.getModifiedTime(fileName) || missingFileModifiedTime; + return host.getModifiedTime!(fileName) || missingFileModifiedTime; } } @@ -369,7 +369,7 @@ namespace ts { close: () => { watcher.close(); result.childWatches.forEach(closeFileWatcher); - result = undefined; + result = undefined!; }, dirName, childWatches: emptyArray @@ -423,6 +423,7 @@ namespace ts { } } + // TODO: GH#18217 Methods on System are often used as if they are certainly defined export interface System { args: string[]; newLine: string; @@ -480,7 +481,7 @@ namespace ts { declare const global: any; declare const __filename: string; - export function getNodeMajorVersion() { + export function getNodeMajorVersion(): number | undefined { if (typeof process === "undefined") { return undefined; } @@ -517,6 +518,7 @@ namespace ts { getEnvironmentVariable?(name: string): string; }; + // TODO: this is used as if it's certainly defined in many places. export let sys: System = (() => { // NodeJS detects "\uFEFF" at the start of the string and *replaces* it with the actual // byte order mark from the specified encoding. Using any other byte order mark does @@ -528,7 +530,7 @@ namespace ts { const _path = require("path"); const _os = require("os"); // crypto can be absent on reduced node installations - let _crypto: typeof import("crypto"); + let _crypto: typeof import("crypto") | undefined; try { _crypto = require("crypto"); } @@ -542,7 +544,7 @@ namespace ts { } = require("buffer").Buffer; const nodeVersion = getNodeMajorVersion(); - const isNode4OrLater = nodeVersion >= 4; + const isNode4OrLater = nodeVersion! >= 4; const platform: string = _os.platform(); const useCaseSensitiveFileNames = isFileSystemCaseSensitive(); @@ -632,12 +634,12 @@ namespace ts { } }, base64decode: Buffer.from ? input => { - return Buffer.from(input, "base64").toString("utf8"); + return Buffer.from!(input, "base64").toString("utf8"); } : input => { return new Buffer(input, "base64").toString("utf8"); }, base64encode: Buffer.from ? input => { - return Buffer.from(input).toString("base64"); + return Buffer.from!(input).toString("base64"); } : input => { return new Buffer(input).toString("base64"); } @@ -712,6 +714,7 @@ namespace ts { return watchDirectoryRecursively(directoryName, callback); } watchDirectory(directoryName, callback); + return undefined!; // TODO: GH#18217 }; } @@ -748,7 +751,7 @@ namespace ts { (_eventName: string, relativeFileName) => { // When files are deleted from disk, the triggered "rename" event would have a relativefileName of "undefined" const fileName = !isString(relativeFileName) - ? undefined + ? undefined! // TODO: GH#18217 : getNormalizedAbsolutePath(relativeFileName, dirName); // Some applications save a working file via rename operations const callbacks = fileWatcherCallbacks.get(toCanonicalName(fileName)); @@ -838,7 +841,7 @@ namespace ts { close: () => { // Close the watcher (either existing file system entry watcher or missing file system entry watcher) watcher.close(); - watcher = undefined; + watcher = undefined!; } }; @@ -970,7 +973,7 @@ namespace ts { data = byteOrderMarkIndicator + data; } - let fd: number; + let fd: number | undefined; try { fd = _fs.openSync(fileName, "w"); @@ -1028,6 +1031,7 @@ namespace ts { switch (entryKind) { case FileSystemEntryKind.File: return stat.isFile(); case FileSystemEntryKind.Directory: return stat.isDirectory(); + default: return false; } } catch (e) { @@ -1075,13 +1079,13 @@ namespace ts { } function createMD5HashUsingNativeCrypto(data: string): string { - const hash = _crypto.createHash("md5"); + const hash = _crypto!.createHash("md5"); hash.update(data); return hash.digest("hex"); } function createSHA256Hash(data: string): string { - const hash = _crypto.createHash("sha256"); + const hash = _crypto!.createHash("sha256"); hash.update(data); return hash.digest("hex"); } @@ -1134,7 +1138,7 @@ namespace ts { } } - let sys: System; + let sys: System | undefined; if (typeof ChakraHost !== "undefined") { sys = getChakraSystem(); } @@ -1148,13 +1152,13 @@ namespace ts { const originalWriteFile = sys.writeFile; sys.writeFile = (path, data, writeBom) => { const directoryPath = getDirectoryPath(normalizeSlashes(path)); - if (directoryPath && !sys.directoryExists(directoryPath)) { - recursiveCreateDirectory(directoryPath, sys); + if (directoryPath && !sys!.directoryExists(directoryPath)) { + recursiveCreateDirectory(directoryPath, sys!); } originalWriteFile.call(sys, path, data, writeBom); }; } - return sys; + return sys!; })(); if (sys && sys.getEnvironmentVariable) { diff --git a/src/compiler/transformer.ts b/src/compiler/transformer.ts index b661120b961a6..b78202e0c3d58 100644 --- a/src/compiler/transformer.ts +++ b/src/compiler/transformer.ts @@ -78,7 +78,7 @@ namespace ts { * @param transforms An array of `TransformerFactory` callbacks. * @param allowDtsFiles A value indicating whether to allow the transformation of .d.ts files. */ - export function transformNodes(resolver: EmitResolver, host: EmitHost, options: CompilerOptions, nodes: ReadonlyArray, transformers: ReadonlyArray>, allowDtsFiles: boolean): TransformationResult { + export function transformNodes(resolver: EmitResolver | undefined, host: EmitHost | undefined, options: CompilerOptions, nodes: ReadonlyArray, transformers: ReadonlyArray>, allowDtsFiles: boolean): TransformationResult { const enabledSyntaxKindFeatures = new Array(SyntaxKind.Count); let lexicalEnvironmentVariableDeclarations: VariableDeclaration[]; let lexicalEnvironmentFunctionDeclarations: FunctionDeclaration[]; @@ -86,7 +86,7 @@ namespace ts { let lexicalEnvironmentFunctionDeclarationsStack: FunctionDeclaration[][] = []; let lexicalEnvironmentStackOffset = 0; let lexicalEnvironmentSuspended = false; - let emitHelpers: EmitHelper[]; + let emitHelpers: EmitHelper[] | undefined; let onSubstituteNode: TransformationContext["onSubstituteNode"] = (_, node) => node; let onEmitNode: TransformationContext["onEmitNode"] = (hint, node, callback) => callback(hint, node); let state = TransformationState.Uninitialized; @@ -96,8 +96,8 @@ namespace ts { // initialization. const context: TransformationContext = { getCompilerOptions: () => options, - getEmitResolver: () => resolver, - getEmitHost: () => host, + getEmitResolver: () => resolver!, // TODO: GH#18217 + getEmitHost: () => host!, // TODO: GH#18217 startLexicalEnvironment, suspendLexicalEnvironment, resumeLexicalEnvironment, @@ -270,8 +270,8 @@ namespace ts { lexicalEnvironmentVariableDeclarationsStack[lexicalEnvironmentStackOffset] = lexicalEnvironmentVariableDeclarations; lexicalEnvironmentFunctionDeclarationsStack[lexicalEnvironmentStackOffset] = lexicalEnvironmentFunctionDeclarations; lexicalEnvironmentStackOffset++; - lexicalEnvironmentVariableDeclarations = undefined; - lexicalEnvironmentFunctionDeclarations = undefined; + lexicalEnvironmentVariableDeclarations = undefined!; + lexicalEnvironmentFunctionDeclarations = undefined!; } /** Suspends the current lexical environment, usually after visiting a parameter list. */ @@ -294,12 +294,12 @@ namespace ts { * Ends a lexical environment. The previous set of hoisted declarations are restored and * any hoisted declarations added in this environment are returned. */ - function endLexicalEnvironment(): Statement[] { + function endLexicalEnvironment(): Statement[] | undefined { Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization."); Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed."); Debug.assert(!lexicalEnvironmentSuspended, "Lexical environment is suspended."); - let statements: Statement[]; + let statements: Statement[] | undefined; if (lexicalEnvironmentVariableDeclarations || lexicalEnvironmentFunctionDeclarations) { if (lexicalEnvironmentFunctionDeclarations) { statements = [...lexicalEnvironmentFunctionDeclarations]; @@ -354,12 +354,12 @@ namespace ts { } // Release references to external entries for GC purposes. - lexicalEnvironmentVariableDeclarations = undefined; - lexicalEnvironmentVariableDeclarationsStack = undefined; - lexicalEnvironmentFunctionDeclarations = undefined; - lexicalEnvironmentFunctionDeclarationsStack = undefined; - onSubstituteNode = undefined; - onEmitNode = undefined; + lexicalEnvironmentVariableDeclarations = undefined!; + lexicalEnvironmentVariableDeclarationsStack = undefined!; + lexicalEnvironmentFunctionDeclarations = undefined!; + lexicalEnvironmentFunctionDeclarationsStack = undefined!; + onSubstituteNode = undefined!; + onEmitNode = undefined!; emitHelpers = undefined; // Prevent further use of the transformation result. diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 953f8279def76..a92448e529000 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -1,6 +1,6 @@ /*@internal*/ namespace ts { - export function getDeclarationDiagnostics(host: EmitHost, resolver: EmitResolver, file: SourceFile | undefined): DiagnosticWithLocation[] { + export function getDeclarationDiagnostics(host: EmitHost, resolver: EmitResolver, file: SourceFile | undefined): DiagnosticWithLocation[] | undefined { if (file && isSourceFileJavaScript(file)) { return []; // No declaration diagnostics for js for now } @@ -32,8 +32,8 @@ namespace ts { let needsScopeFixMarker = false; let resultHasScopeMarker = false; let enclosingDeclaration: Node; - let necessaryTypeRefernces: Map; - let lateMarkedStatements: LateVisibilityPaintedStatement[]; + let necessaryTypeRefernces: Map | undefined; + let lateMarkedStatements: LateVisibilityPaintedStatement[] | undefined; let lateStatementReplacementMap: Map>; let suppressNewDiagnosticContexts: boolean; @@ -56,7 +56,7 @@ namespace ts { const { noResolve, stripInternal } = options; return transformRoot; - function recordTypeReferenceDirectivesIfNecessary(typeReferenceDirectives: string[]): void { + function recordTypeReferenceDirectivesIfNecessary(typeReferenceDirectives: string[] | undefined): void { if (!typeReferenceDirectives) { return; } @@ -151,7 +151,7 @@ namespace ts { let hasNoDefaultLib = false; const bundle = createBundle(map(node.sourceFiles, sourceFile => { - if (sourceFile.isDeclarationFile || isSourceFileJavaScript(sourceFile)) return; // Omit declaration files from bundle results, too + if (sourceFile.isDeclarationFile || isSourceFileJavaScript(sourceFile)) return undefined!; // Omit declaration files from bundle results, too // TODO: GH#18217 hasNoDefaultLib = hasNoDefaultLib || sourceFile.hasNoDefaultLib; currentSourceFile = sourceFile; enclosingDeclaration = sourceFile; @@ -186,7 +186,7 @@ namespace ts { bundle.syntheticFileReferences = []; bundle.syntheticTypeReferences = getFileReferencesForUsedTypeReferences(); bundle.hasNoDefaultLib = hasNoDefaultLib; - const outputFilePath = getDirectoryPath(normalizeSlashes(getOutputPathsFor(node, host, /*forceDtsPaths*/ true).declarationFilePath)); + const outputFilePath = getDirectoryPath(normalizeSlashes(getOutputPathsFor(node, host, /*forceDtsPaths*/ true).declarationFilePath!)); const referenceVisitor = mapReferencesIntoArray(bundle.syntheticFileReferences as FileReference[], outputFilePath); refs.forEach(referenceVisitor); return bundle; @@ -207,7 +207,7 @@ namespace ts { necessaryTypeRefernces = undefined; refs = collectReferences(currentSourceFile, createMap()); const references: FileReference[] = []; - const outputFilePath = getDirectoryPath(normalizeSlashes(getOutputPathsFor(node, host, /*forceDtsPaths*/ true).declarationFilePath)); + const outputFilePath = getDirectoryPath(normalizeSlashes(getOutputPathsFor(node, host, /*forceDtsPaths*/ true).declarationFilePath!)); const referenceVisitor = mapReferencesIntoArray(references, outputFilePath); const statements = visitNodes(node.statements, visitDeclarationStatements); let combinedStatements = setTextRange(createNodeArray(transformAndReplaceLatePaintedStatements(statements)), node.statements); @@ -304,7 +304,7 @@ namespace ts { } function ensureParameter(p: ParameterDeclaration, modifierMask?: ModifierFlags): ParameterDeclaration { - let oldDiag: typeof getSymbolAccessibilityDiagnostic; + let oldDiag: typeof getSymbolAccessibilityDiagnostic | undefined; if (!suppressNewDiagnosticContexts) { oldDiag = getSymbolAccessibilityDiagnostic; getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(p); @@ -320,7 +320,7 @@ namespace ts { ensureNoInitializer(p) ); if (!suppressNewDiagnosticContexts) { - getSymbolAccessibilityDiagnostic = oldDiag; + getSymbolAccessibilityDiagnostic = oldDiag!; } return newParam; } @@ -350,7 +350,7 @@ namespace ts { | PropertyDeclaration | PropertySignature; - function ensureType(node: HasInferredType, type: TypeNode, ignorePrivate?: boolean): TypeNode { + function ensureType(node: HasInferredType, type: TypeNode | undefined, ignorePrivate?: boolean): TypeNode | undefined { if (!ignorePrivate && hasModifier(node, ModifierFlags.Private)) { // Private nodes emit no types (except private parameter properties, whose parameter types are actually visible) return; @@ -427,7 +427,7 @@ namespace ts { } if (isBindingPattern(elem.name)) { // If any child binding pattern element has been marked visible (usually by collect linked aliases), then this is visible - return forEach(elem.name.elements, getBindingNameVisible); + return some(elem.name.elements, getBindingNameVisible); } else { return resolver.isDeclarationVisible(elem); @@ -436,16 +436,16 @@ namespace ts { function updateParamsList(node: Node, params: NodeArray, modifierMask?: ModifierFlags) { if (hasModifier(node, ModifierFlags.Private)) { - return undefined; + return undefined!; // TODO: GH#18217 } const newParams = map(params, p => ensureParameter(p, modifierMask)); if (!newParams) { - return undefined; + return undefined!; // TODO: GH#18217 } return createNodeArray(newParams, params.hasTrailingComma); } - function ensureTypeParams(node: Node, params: NodeArray) { + function ensureTypeParams(node: Node, params: NodeArray | undefined) { return hasModifier(node, ModifierFlags.Private) ? undefined : visitNodes(params, visitDeclarationSubtree); } @@ -473,8 +473,8 @@ namespace ts { return setCommentRange(updated, getCommentRange(original)); } - function rewriteModuleSpecifier(parent: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration | ImportTypeNode, input: T): T | StringLiteral { - if (!input) return; + function rewriteModuleSpecifier(parent: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration | ImportTypeNode, input: T | undefined): T | StringLiteral { + if (!input) return undefined!; // TODO: GH#18217 resultHasExternalModuleIndicator = resultHasExternalModuleIndicator || (parent.kind !== SyntaxKind.ModuleDeclaration && parent.kind !== SyntaxKind.ImportType); if (input.kind === SyntaxKind.StringLiteral && isBundledEmit) { const newName = getExternalModuleNameFromDeclaration(context.getEmitHost(), resolver, parent); @@ -571,7 +571,7 @@ namespace ts { // be recorded. So while checking D's visibility we mark C as visible, then we must check C which in turn marks B, completing the chain of // dependent imports and allowing a valid declaration file output. Today, this dependent alias marking only happens for internal import aliases. while (length(lateMarkedStatements)) { - const i = lateMarkedStatements.shift(); + const i = lateMarkedStatements!.shift()!; if (!isLateVisibilityPaintedStatement(i)) { return Debug.fail(`Late replaced statement was found which is not handled by the declaration transformer!: ${(ts as any).SyntaxKind ? (ts as any).SyntaxKind[(i as any).kind] : (i as any).kind}`); } @@ -687,7 +687,8 @@ namespace ts { const ctor = createSignatureDeclaration( SyntaxKind.Constructor, isPrivate ? undefined : ensureTypeParams(input, input.typeParameters), - isPrivate ? undefined : updateParamsList(input, input.parameters, ModifierFlags.None), + // TODO: GH#18217 + isPrivate ? undefined! : updateParamsList(input, input.parameters, ModifierFlags.None), /*type*/ undefined ); ctor.modifiers = createNodeArray(ensureModifiers(input)); @@ -807,7 +808,7 @@ namespace ts { return cleanup(visitEachChild(input, visitDeclarationSubtree, context)); - function cleanup(returnValue: T | undefined): T { + function cleanup(returnValue: T | undefined): T | undefined { if (returnValue && canProdiceDiagnostic && hasDynamicName(input as Declaration)) { checkName(input as DeclarationDiagnosticProducing); } @@ -961,7 +962,7 @@ namespace ts { needsDeclare = false; visitNode(inner, visitDeclarationStatements); // eagerly transform nested namespaces (the nesting doesn't need any elision or painting done) - const id = "" + getOriginalNodeId(inner); + const id = "" + getOriginalNodeId(inner!); // TODO: GH#18217 const body = lateStatementReplacementMap.get(id); lateStatementReplacementMap.delete(id); return cleanup(updateModuleDeclaration( @@ -977,7 +978,7 @@ namespace ts { const modifiers = createNodeArray(ensureModifiers(input, isPrivate)); const typeParameters = ensureTypeParams(input, input.typeParameters); const ctor = getFirstConstructorWithBody(input); - let parameterProperties: PropertyDeclaration[]; + let parameterProperties: PropertyDeclaration[] | undefined; if (ctor) { const oldDiag = getSymbolAccessibilityDiagnostic; parameterProperties = compact(flatMap(ctor.parameters, param => { @@ -998,7 +999,7 @@ namespace ts { } function walkBindingPattern(pattern: BindingPattern) { - let elems: PropertyDeclaration[]; + let elems: PropertyDeclaration[] | undefined; for (const elem of pattern.elements) { if (isOmittedExpression(elem)) continue; if (isBindingPattern(elem.name)) { @@ -1025,7 +1026,7 @@ namespace ts { if (extendsClause && !isEntityNameExpression(extendsClause.expression) && extendsClause.expression.kind !== SyntaxKind.NullKeyword) { // We must add a temporary declaration for the extends clause expression - const newId = createOptimisticUniqueName(`${unescapeLeadingUnderscores(input.name.escapedText)}_base`); + const newId = createOptimisticUniqueName(`${unescapeLeadingUnderscores(input.name!.escapedText)}_base`); // TODO: GH#18217 getSymbolAccessibilityDiagnostic = () => ({ diagnosticMessage: Diagnostics.extends_clause_of_exported_class_0_has_or_is_using_private_name_1, errorNode: extendsClause, @@ -1051,7 +1052,7 @@ namespace ts { typeParameters, heritageClauses, members - ))]; + ))!]; // TODO: GH#18217 } else { const heritageClauses = transformHeritageClauses(input.heritageClauses); @@ -1081,7 +1082,7 @@ namespace ts { // Anything left unhandled is an error, so this should be unreachable return Debug.assertNever(input, `Unhandled top-level node in declaration emit: ${(ts as any).SyntaxKind[(input as any).kind]}`); - function cleanup(node: T | undefined): T { + function cleanup(node: T | undefined): T | undefined { if (isEnclosingDeclaration(input)) { enclosingDeclaration = previousEnclosingDeclaration; } @@ -1125,7 +1126,7 @@ namespace ts { } function checkName(node: DeclarationDiagnosticProducing) { - let oldDiag: typeof getSymbolAccessibilityDiagnostic; + let oldDiag: typeof getSymbolAccessibilityDiagnostic | undefined; if (!suppressNewDiagnosticContexts) { oldDiag = getSymbolAccessibilityDiagnostic; getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNodeName(node); @@ -1136,7 +1137,7 @@ namespace ts { const entityName = decl.name.expression; checkEntityNameVisibility(entityName, enclosingDeclaration); if (!suppressNewDiagnosticContexts) { - getSymbolAccessibilityDiagnostic = oldDiag; + getSymbolAccessibilityDiagnostic = oldDiag!; } errorNameNode = undefined; } @@ -1156,7 +1157,7 @@ namespace ts { return false; } - function ensureModifiers(node: Node, privateDeclaration?: boolean): ReadonlyArray { + function ensureModifiers(node: Node, privateDeclaration?: boolean): ReadonlyArray | undefined { const currentFlags = getModifierFlags(node); const newFlags = ensureModifierFlags(node, privateDeclaration); if (currentFlags === newFlags) { @@ -1211,7 +1212,7 @@ namespace ts { return prop; } - function transformHeritageClauses(nodes: NodeArray) { + function transformHeritageClauses(nodes: NodeArray | undefined) { return createNodeArray(filter(map(nodes, clause => updateHeritageClause(clause, visitNodes(createNodeArray(filter(clause.types, t => { return isEntityNameExpression(t.expression) || (clause.token === SyntaxKind.ExtendsKeyword && t.expression.kind === SyntaxKind.NullKeyword); })), visitDeclarationSubtree))), clause => clause.types && !!clause.types.length)); @@ -1238,7 +1239,7 @@ namespace ts { return flags; } - function getTypeAnnotationFromAccessor(accessor: AccessorDeclaration): TypeNode { + function getTypeAnnotationFromAccessor(accessor: AccessorDeclaration): TypeNode | undefined { if (accessor) { return accessor.kind === SyntaxKind.GetAccessor ? accessor.type // Getter - return type diff --git a/src/compiler/transformers/declarations/diagnostics.ts b/src/compiler/transformers/declarations/diagnostics.ts index e81539ca92da0..0865861414e95 100644 --- a/src/compiler/transformers/declarations/diagnostics.ts +++ b/src/compiler/transformers/declarations/diagnostics.ts @@ -90,7 +90,7 @@ namespace ts { } } - function getMethodNameVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic { + function getMethodNameVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic | undefined { const diagnosticMessage = getMethodNameVisibilityDiagnosticMessage(symbolAccessibilityResult); return diagnosticMessage !== undefined ? { diagnosticMessage, @@ -122,7 +122,7 @@ namespace ts { } } - export function createGetSymbolAccessibilityDiagnosticForNode(node: DeclarationDiagnosticProducing) { + export function createGetSymbolAccessibilityDiagnosticForNode(node: DeclarationDiagnosticProducing): (symbolAccessibilityResult: SymbolAccessibilityResult) => SymbolAccessibilityDiagnostic | undefined { if (isVariableDeclaration(node) || isPropertyDeclaration(node) || isPropertySignature(node) || isBindingElement(node) || isConstructorDeclaration(node)) { return getVariableDeclarationTypeVisibilityError; } @@ -151,7 +151,7 @@ namespace ts { return getTypeAliasDeclarationVisibilityError; } else { - Debug.assertNever(node, `Attempted to set a declaration diagnostic context for unhandled node kind: ${(ts as any).SyntaxKind[(node as any).kind]}`); + return Debug.assertNever(node, `Attempted to set a declaration diagnostic context for unhandled node kind: ${(ts as any).SyntaxKind[(node as any).kind]}`); } function getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult: SymbolAccessibilityResult) { @@ -190,7 +190,7 @@ namespace ts { } } - function getVariableDeclarationTypeVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic { + function getVariableDeclarationTypeVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic | undefined { const diagnosticMessage = getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult); return diagnosticMessage !== undefined ? { diagnosticMessage, @@ -233,7 +233,7 @@ namespace ts { } return { diagnosticMessage, - errorNode: (node as NamedDeclaration).name, + errorNode: (node as NamedDeclaration).name!, typeName: (node as NamedDeclaration).name }; } @@ -295,7 +295,7 @@ namespace ts { break; default: - Debug.fail("This is unknown kind for signature: " + node.kind); + return Debug.fail("This is unknown kind for signature: " + node.kind); } return { @@ -304,7 +304,7 @@ namespace ts { }; } - function getParameterDeclarationTypeVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic { + function getParameterDeclarationTypeVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic | undefined { const diagnosticMessage: DiagnosticMessage = getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult); return diagnosticMessage !== undefined ? { diagnosticMessage, @@ -373,7 +373,7 @@ namespace ts { Diagnostics.Parameter_0_of_exported_function_has_or_is_using_private_name_1; default: - Debug.fail(`Unknown parent for parameter: ${(ts as any).SyntaxKind[node.parent.kind]}`); + return Debug.fail(`Unknown parent for parameter: ${(ts as any).SyntaxKind[node.parent.kind]}`); } } @@ -419,7 +419,7 @@ namespace ts { break; default: - Debug.fail("This is unknown parent for type parameter: " + node.parent.kind); + return Debug.fail("This is unknown parent for type parameter: " + node.parent.kind); } return { diff --git a/src/compiler/transformers/destructuring.ts b/src/compiler/transformers/destructuring.ts index 2dd8946e8e2b8..5f54e367d3e88 100644 --- a/src/compiler/transformers/destructuring.ts +++ b/src/compiler/transformers/destructuring.ts @@ -6,7 +6,7 @@ namespace ts { downlevelIteration: boolean; hoistTempVariables: boolean; emitExpression: (value: Expression) => void; - emitBindingOrAssignment: (target: BindingOrAssignmentElementTarget, value: Expression, location: TextRange, original: Node) => void; + emitBindingOrAssignment: (target: BindingOrAssignmentElementTarget, value: Expression, location: TextRange, original: Node | undefined) => void; createArrayBindingOrAssignmentPattern: (elements: BindingOrAssignmentElement[]) => ArrayBindingOrAssignmentPattern; createObjectBindingOrAssignmentPattern: (elements: BindingOrAssignmentElement[]) => ObjectBindingOrAssignmentPattern; createArrayBindingOrAssignmentElement: (node: Identifier) => BindingOrAssignmentElement; @@ -37,7 +37,7 @@ namespace ts { needsValue?: boolean, createAssignmentCallback?: (name: Identifier, value: Expression, location?: TextRange) => Expression): Expression { let location: TextRange = node; - let value: Expression; + let value: Expression | undefined; if (isDestructuringAssignment(node)) { value = node.right; while (isEmptyArrayLiteral(node.left) || isEmptyObjectLiteral(node.left)) { @@ -51,11 +51,11 @@ namespace ts { } } - let expressions: Expression[]; + let expressions: Expression[] | undefined; const flattenContext: FlattenContext = { context, level, - downlevelIteration: context.getCompilerOptions().downlevelIteration, + downlevelIteration: !!context.getCompilerOptions().downlevelIteration, hoistTempVariables: true, emitExpression, emitBindingOrAssignment, @@ -103,7 +103,7 @@ namespace ts { expressions.push(value); } - return aggregateTransformFlags(inlineExpressions(expressions)) || createOmittedExpression(); + return aggregateTransformFlags(inlineExpressions(expressions!)) || createOmittedExpression(); function emitExpression(expression: Expression) { // NOTE: this completely disables source maps, but aligns with the behavior of @@ -127,7 +127,7 @@ namespace ts { } function bindingOrAssignmentElementAssignsToName(element: BindingOrAssignmentElement, escapedName: __String): boolean { - const target = getTargetOfBindingOrAssignmentElement(element); + const target = getTargetOfBindingOrAssignmentElement(element)!; // TODO: GH#18217 if (isBindingOrAssignmentPattern(target)) { return bindingOrAssignmentPatternAssignsToName(target, escapedName); } @@ -164,15 +164,15 @@ namespace ts { context: TransformationContext, level: FlattenLevel, rval?: Expression, - hoistTempVariables?: boolean, + hoistTempVariables = false, skipInitializer?: boolean): VariableDeclaration[] { - let pendingExpressions: Expression[]; + let pendingExpressions: Expression[] | undefined; const pendingDeclarations: { pendingExpressions?: Expression[], name: BindingName, value: Expression, location?: TextRange, original?: Node; }[] = []; const declarations: VariableDeclaration[] = []; const flattenContext: FlattenContext = { context, level, - downlevelIteration: context.getCompilerOptions().downlevelIteration, + downlevelIteration: !!context.getCompilerOptions().downlevelIteration, hoistTempVariables, emitExpression, emitBindingOrAssignment, @@ -202,7 +202,7 @@ namespace ts { } else { context.hoistVariableDeclaration(temp); - const pendingDeclaration = lastOrUndefined(pendingDeclarations); + const pendingDeclaration = last(pendingDeclarations); pendingDeclaration.pendingExpressions = append( pendingDeclaration.pendingExpressions, createAssignment(temp, pendingDeclaration.value) @@ -231,7 +231,7 @@ namespace ts { pendingExpressions = append(pendingExpressions, value); } - function emitBindingOrAssignment(target: BindingOrAssignmentElementTarget, value: Expression, location: TextRange, original: Node) { + function emitBindingOrAssignment(target: BindingOrAssignmentElementTarget, value: Expression, location: TextRange | undefined, original: Node | undefined) { Debug.assertNode(target, isBindingName); if (pendingExpressions) { value = inlineExpressions(append(pendingExpressions, value)); @@ -268,15 +268,15 @@ namespace ts { value = createVoidZero(); } } - const bindingTarget = getTargetOfBindingOrAssignmentElement(element); + const bindingTarget = getTargetOfBindingOrAssignmentElement(element)!; // TODO: GH#18217 if (isObjectBindingOrAssignmentPattern(bindingTarget)) { - flattenObjectBindingOrAssignmentPattern(flattenContext, element, bindingTarget, value, location); + flattenObjectBindingOrAssignmentPattern(flattenContext, element, bindingTarget, value!, location); } else if (isArrayBindingOrAssignmentPattern(bindingTarget)) { - flattenArrayBindingOrAssignmentPattern(flattenContext, element, bindingTarget, value, location); + flattenArrayBindingOrAssignmentPattern(flattenContext, element, bindingTarget, value!, location); } else { - flattenContext.emitBindingOrAssignment(bindingTarget, value, location, /*original*/ element); + flattenContext.emitBindingOrAssignment(bindingTarget, value!, location, /*original*/ element); // TODO: GH#18217 } } @@ -300,15 +300,15 @@ namespace ts { const reuseIdentifierExpressions = !isDeclarationBindingElement(parent) || numElements !== 0; value = ensureIdentifier(flattenContext, value, reuseIdentifierExpressions, location); } - let bindingElements: BindingOrAssignmentElement[]; - let computedTempVariables: Expression[]; + let bindingElements: BindingOrAssignmentElement[] | undefined; + let computedTempVariables: Expression[] | undefined; for (let i = 0; i < numElements; i++) { const element = elements[i]; if (!getRestIndicatorOfBindingOrAssignmentElement(element)) { - const propertyName = getPropertyNameOfBindingOrAssignmentElement(element); + const propertyName = getPropertyNameOfBindingOrAssignmentElement(element)!; if (flattenContext.level >= FlattenLevel.ObjectRest && !(element.transformFlags & (TransformFlags.ContainsRest | TransformFlags.ContainsObjectRest)) - && !(getTargetOfBindingOrAssignmentElement(element).transformFlags & (TransformFlags.ContainsRest | TransformFlags.ContainsObjectRest)) + && !(getTargetOfBindingOrAssignmentElement(element)!.transformFlags & (TransformFlags.ContainsRest | TransformFlags.ContainsObjectRest)) && !isComputedPropertyName(propertyName)) { bindingElements = append(bindingElements, element); } @@ -319,7 +319,7 @@ namespace ts { } const rhsValue = createDestructuringPropertyAccess(flattenContext, value, propertyName); if (isComputedPropertyName(propertyName)) { - computedTempVariables = append(computedTempVariables, (rhsValue as ElementAccessExpression).argumentExpression); + computedTempVariables = append(computedTempVariables, (rhsValue as ElementAccessExpression).argumentExpression); } flattenBindingOrAssignmentElement(flattenContext, element, rhsValue, /*location*/ element); } @@ -329,7 +329,7 @@ namespace ts { flattenContext.emitBindingOrAssignment(flattenContext.createObjectBindingOrAssignmentPattern(bindingElements), value, location, pattern); bindingElements = undefined; } - const rhsValue = createRestCall(flattenContext.context, value, elements, computedTempVariables, pattern); + const rhsValue = createRestCall(flattenContext.context, value, elements, computedTempVariables!, pattern); // TODO: GH#18217 flattenBindingOrAssignmentElement(flattenContext, element, rhsValue, element); } } @@ -377,8 +377,8 @@ namespace ts { const reuseIdentifierExpressions = !isDeclarationBindingElement(parent) || numElements !== 0; value = ensureIdentifier(flattenContext, value, reuseIdentifierExpressions, location); } - let bindingElements: BindingOrAssignmentElement[]; - let restContainingElements: [Identifier, BindingOrAssignmentElement][]; + let bindingElements: BindingOrAssignmentElement[] | undefined; + let restContainingElements: [Identifier, BindingOrAssignmentElement][] | undefined; for (let i = 0; i < numElements; i++) { const element = elements[i]; if (flattenContext.level >= FlattenLevel.ObjectRest) { diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index 7e356ca4a3a65..3a632bb5ec30a 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -159,7 +159,7 @@ namespace ts { ReplaceWithReturn, } - type LoopConverter = (node: IterationStatement, outermostLabeledStatement: LabeledStatement, convertedLoopBodyStatements: Statement[]) => Statement; + type LoopConverter = (node: IterationStatement, outermostLabeledStatement: LabeledStatement | undefined, convertedLoopBodyStatements: Statement[] | undefined) => Statement; // Facts we track as we traverse the tree const enum HierarchyFacts { @@ -286,7 +286,7 @@ namespace ts { /** * Used to track if we are emitting body of the converted loop */ - let convertedLoopState: ConvertedLoopState; + let convertedLoopState: ConvertedLoopState | undefined; /** * Keeps track of whether substitutions have been enabled for specific cases. @@ -308,9 +308,9 @@ namespace ts { const visited = visitSourceFile(node); addEmitHelpers(visited, context.readEmitHelpers()); - currentSourceFile = undefined; - currentText = undefined; - taggedTemplateStringDeclarations = undefined; + currentSourceFile = undefined!; + currentText = undefined!; + taggedTemplateStringDeclarations = undefined!; hierarchyFacts = HierarchyFacts.None; return visited; } @@ -338,7 +338,7 @@ namespace ts { } function isReturnVoidStatementInConstructorWithCapturedSuper(node: Node): boolean { - return hierarchyFacts & HierarchyFacts.ConstructorWithCapturedSuper + return (hierarchyFacts & HierarchyFacts.ConstructorWithCapturedSuper) !== 0 && node.kind === SyntaxKind.ReturnStatement && !(node).expression; } @@ -520,7 +520,7 @@ namespace ts { const ancestorFacts = enterSubtree(HierarchyFacts.SourceFileExcludes, HierarchyFacts.SourceFileIncludes); const statements: Statement[] = []; startLexicalEnvironment(); - let statementOffset = addStandardPrologue(statements, node.statements, /*ensureUseStrict*/ false); + let statementOffset: number | undefined = addStandardPrologue(statements, node.statements, /*ensureUseStrict*/ false); addCaptureThisForNodeIfNeeded(statements, node); statementOffset = addCustomPrologue(statements, node.statements, statementOffset, visitor); addRange(statements, visitNodes(node.statements, visitor, isStatement, statementOffset)); @@ -541,7 +541,7 @@ namespace ts { if (convertedLoopState !== undefined) { const savedAllowedNonLabeledJumps = convertedLoopState.allowedNonLabeledJumps; // for switch statement allow only non-labeled break - convertedLoopState.allowedNonLabeledJumps |= Jump.Break; + convertedLoopState.allowedNonLabeledJumps! |= Jump.Break; const result = visitEachChild(node, visitor, context); convertedLoopState.allowedNonLabeledJumps = savedAllowedNonLabeledJumps; return result; @@ -562,7 +562,7 @@ namespace ts { function visitReturnStatement(node: ReturnStatement): Statement { if (convertedLoopState) { - convertedLoopState.nonLocalJumps |= Jump.Return; + convertedLoopState.nonLocalJumps! |= Jump.Return; if (isReturnVoidStatementInConstructorWithCapturedSuper(node)) { node = returnCapturedThis(node); } @@ -619,45 +619,46 @@ namespace ts { const jump = node.kind === SyntaxKind.BreakStatement ? Jump.Break : Jump.Continue; const canUseBreakOrContinue = (node.label && convertedLoopState.labels && convertedLoopState.labels.get(idText(node.label))) || - (!node.label && (convertedLoopState.allowedNonLabeledJumps & jump)); + (!node.label && (convertedLoopState.allowedNonLabeledJumps! & jump)); if (!canUseBreakOrContinue) { let labelMarker: string; - if (!node.label) { + const label = node.label; + if (!label) { if (node.kind === SyntaxKind.BreakStatement) { - convertedLoopState.nonLocalJumps |= Jump.Break; + convertedLoopState.nonLocalJumps! |= Jump.Break; labelMarker = "break"; } else { - convertedLoopState.nonLocalJumps |= Jump.Continue; + convertedLoopState.nonLocalJumps! |= Jump.Continue; // note: return value is emitted only to simplify debugging, call to converted loop body does not do any dispatching on it. labelMarker = "continue"; } } else { if (node.kind === SyntaxKind.BreakStatement) { - labelMarker = `break-${node.label.escapedText}`; - setLabeledJump(convertedLoopState, /*isBreak*/ true, idText(node.label), labelMarker); + labelMarker = `break-${label.escapedText}`; + setLabeledJump(convertedLoopState, /*isBreak*/ true, idText(label), labelMarker); } else { - labelMarker = `continue-${node.label.escapedText}`; - setLabeledJump(convertedLoopState, /*isBreak*/ false, idText(node.label), labelMarker); + labelMarker = `continue-${label.escapedText}`; + setLabeledJump(convertedLoopState, /*isBreak*/ false, idText(label), labelMarker); } } let returnExpression: Expression = createLiteral(labelMarker); - if (convertedLoopState.loopOutParameters.length) { - const outParams = convertedLoopState.loopOutParameters; - let expr: Expression; + if (convertedLoopState.loopOutParameters!.length) { + const outParams = convertedLoopState.loopOutParameters!; + let expr: Expression | undefined; for (let i = 0; i < outParams.length; i++) { const copyExpr = copyOutParameter(outParams[i], CopyDirection.ToOutParameter); if (i === 0) { expr = copyExpr; } else { - expr = createBinary(expr, SyntaxKind.CommaToken, copyExpr); + expr = createBinary(expr!, SyntaxKind.CommaToken, copyExpr); } } - returnExpression = createBinary(expr, SyntaxKind.CommaToken, returnExpression); + returnExpression = createBinary(expr!, SyntaxKind.CommaToken, returnExpression); } return createReturn(returnExpression); } @@ -814,7 +815,7 @@ namespace ts { * @param node A ClassExpression or ClassDeclaration node. * @param extendsClauseElement The expression for the class `extends` clause. */ - function transformClassBody(node: ClassExpression | ClassDeclaration, extendsClauseElement: ExpressionWithTypeArguments): Block { + function transformClassBody(node: ClassExpression | ClassDeclaration, extendsClauseElement: ExpressionWithTypeArguments | undefined): Block { const statements: Statement[] = []; startLexicalEnvironment(); addExtendsHelperIfNeeded(statements, node, extendsClauseElement); @@ -850,7 +851,7 @@ namespace ts { * @param node The ClassExpression or ClassDeclaration node. * @param extendsClauseElement The expression for the class `extends` clause. */ - function addExtendsHelperIfNeeded(statements: Statement[], node: ClassExpression | ClassDeclaration, extendsClauseElement: ExpressionWithTypeArguments): void { + function addExtendsHelperIfNeeded(statements: Statement[], node: ClassExpression | ClassDeclaration, extendsClauseElement: ExpressionWithTypeArguments | undefined): void { if (extendsClauseElement) { statements.push( setTextRange( @@ -870,7 +871,7 @@ namespace ts { * @param node The ClassExpression or ClassDeclaration node. * @param extendsClauseElement The expression for the class `extends` clause. */ - function addConstructor(statements: Statement[], node: ClassExpression | ClassDeclaration, extendsClauseElement: ExpressionWithTypeArguments): void { + function addConstructor(statements: Statement[], node: ClassExpression | ClassDeclaration, extendsClauseElement: ExpressionWithTypeArguments | undefined): void { const savedConvertedLoopState = convertedLoopState; convertedLoopState = undefined; const ancestorFacts = enterSubtree(HierarchyFacts.ConstructorExcludes, HierarchyFacts.ConstructorIncludes); @@ -904,13 +905,13 @@ namespace ts { * @param hasSynthesizedSuper A value indicating whether the constructor starts with a * synthesized `super` call. */ - function transformConstructorParameters(constructor: ConstructorDeclaration, hasSynthesizedSuper: boolean) { + function transformConstructorParameters(constructor: ConstructorDeclaration | undefined, hasSynthesizedSuper: boolean) { // If the TypeScript transformer needed to synthesize a constructor for property // initializers, it would have also added a synthetic `...args` parameter and // `super` call. // If this is the case, we do not include the synthetic `...args` parameter and // will instead use the `arguments` object in ES5/3. - return visitParameterList(constructor && !hasSynthesizedSuper && constructor.parameters, visitor, context) + return visitParameterList(constructor && !hasSynthesizedSuper ? constructor.parameters : undefined, visitor, context) || []; } @@ -923,7 +924,7 @@ namespace ts { * @param hasSynthesizedSuper A value indicating whether the constructor starts with a * synthesized `super` call. */ - function transformConstructorBody(constructor: ConstructorDeclaration | undefined, node: ClassDeclaration | ClassExpression, extendsClauseElement: ExpressionWithTypeArguments, hasSynthesizedSuper: boolean) { + function transformConstructorBody(constructor: ConstructorDeclaration | undefined, node: ClassDeclaration | ClassExpression, extendsClauseElement: ExpressionWithTypeArguments | undefined, hasSynthesizedSuper: boolean) { const statements: Statement[] = []; resumeLexicalEnvironment(); @@ -935,7 +936,7 @@ namespace ts { statementOffset = 0; } else if (constructor) { - statementOffset = addStandardPrologue(statements, constructor.body.statements, /*ensureUseStrict*/ false); + statementOffset = addStandardPrologue(statements, constructor.body!.statements, /*ensureUseStrict*/ false); } if (constructor) { @@ -943,7 +944,7 @@ namespace ts { addRestParameterIfNeeded(statements, constructor, hasSynthesizedSuper); if (!hasSynthesizedSuper) { // If no super call has been synthesized, emit custom prologue directives. - statementOffset = addCustomPrologue(statements, constructor.body.statements, statementOffset, visitor); + statementOffset = addCustomPrologue(statements, constructor.body!.statements, statementOffset, visitor); } Debug.assert(statementOffset >= 0, "statementOffset not initialized correctly!"); @@ -951,7 +952,7 @@ namespace ts { // determine whether the class is known syntactically to be a derived class (e.g. a // class that extends a value that is not syntactically known to be `null`). - const isDerivedClass = extendsClauseElement && skipOuterExpressions(extendsClauseElement.expression).kind !== SyntaxKind.NullKeyword; + const isDerivedClass = !!extendsClauseElement && skipOuterExpressions(extendsClauseElement.expression).kind !== SyntaxKind.NullKeyword; const superCaptureStatus = declareOrCaptureOrReturnThisForConstructorIfNeeded(statements, constructor, isDerivedClass, hasSynthesizedSuper, statementOffset); // The last statement expression was replaced. Skip it. @@ -964,14 +965,14 @@ namespace ts { hierarchyFacts |= HierarchyFacts.ConstructorWithCapturedSuper; } - addRange(statements, visitNodes(constructor.body.statements, visitor, isStatement, /*start*/ statementOffset)); + addRange(statements, visitNodes(constructor.body!.statements, visitor, isStatement, /*start*/ statementOffset)); } // Return `_this` unless we're sure enough that it would be pointless to add a return statement. // If there's a constructor that we can tell returns in enough places, then we *do not* want to add a return. if (isDerivedClass && superCaptureStatus !== SuperCaptureResult.ReplaceWithReturn - && !(constructor && isSufficientlyCoveredByReturnStatements(constructor.body))) { + && !(constructor && isSufficientlyCoveredByReturnStatements(constructor.body!))) { statements.push( createReturn( createFileLevelUniqueName("_this") @@ -990,7 +991,7 @@ namespace ts { createNodeArray( statements ), - /*location*/ constructor ? constructor.body.statements : node.members + /*location*/ constructor ? constructor.body!.statements : node.members ), /*multiLine*/ true ); @@ -1085,10 +1086,10 @@ namespace ts { // // return _super.call(...) || this; // - let firstStatement: Statement; - let superCallExpression: Expression; + let firstStatement: Statement | undefined; + let superCallExpression: Expression | undefined; - const ctorStatements = ctor.body.statements; + const ctorStatements = ctor.body!.statements; if (statementOffset < ctorStatements.length) { firstStatement = ctorStatements[statementOffset]; @@ -1156,7 +1157,7 @@ namespace ts { * * @param node A ParameterDeclaration node. */ - function visitParameter(node: ParameterDeclaration): ParameterDeclaration { + function visitParameter(node: ParameterDeclaration): ParameterDeclaration | undefined { if (node.dotDotDotToken) { // rest parameters are elided return undefined; @@ -1251,7 +1252,7 @@ namespace ts { * @param name The name of the parameter. * @param initializer The initializer for the parameter. */ - function addDefaultValueAssignmentForBindingPattern(statements: Statement[], parameter: ParameterDeclaration, name: BindingPattern, initializer: Expression): void { + function addDefaultValueAssignmentForBindingPattern(statements: Statement[], parameter: ParameterDeclaration, name: BindingPattern, initializer: Expression | undefined): void { const temp = getGeneratedNameForNode(parameter); // In cases where a binding pattern is simply '[]' or '{}', @@ -1339,7 +1340,7 @@ namespace ts { * part of a constructor declaration with a * synthesized call to `super` */ - function shouldAddRestParameter(node: ParameterDeclaration, inConstructorWithSynthesizedSuper: boolean) { + function shouldAddRestParameter(node: ParameterDeclaration | undefined, inConstructorWithSynthesizedSuper: boolean) { return node && node.dotDotDotToken && node.name.kind === SyntaxKind.Identifier && !inConstructorWithSynthesizedSuper; } @@ -1359,11 +1360,11 @@ namespace ts { } // `declarationName` is the name of the local declaration for the parameter. - const declarationName = getMutableClone(parameter.name); + const declarationName = getMutableClone(parameter!.name); setEmitFlags(declarationName, EmitFlags.NoSourceMap); // `expressionName` is the name of the parameter used in expressions. - const expressionName = getSynthesizedClone(parameter.name); + const expressionName = getSynthesizedClone(parameter!.name); const restIndex = node.parameters.length - 1; const temp = createLoopVariable(); @@ -1640,7 +1641,7 @@ namespace ts { // arguments are both mapped contiguously to the accessor name. const target = getMutableClone(receiver); setEmitFlags(target, EmitFlags.NoComments | EmitFlags.NoTrailingSourceMap); - setSourceMapRange(target, firstAccessor.name); + setSourceMapRange(target, firstAccessor.name); // TODO: GH#18217 const propertyName = createExpressionForPropertyName(visitNode(firstAccessor.name, visitor, isPropertyName)); setEmitFlags(propertyName, EmitFlags.NoComments | EmitFlags.NoLeadingSourceMap); @@ -1789,7 +1790,7 @@ namespace ts { * @param location The source-map location for the new FunctionExpression. * @param name The name of the new FunctionExpression. */ - function transformFunctionLikeToExpression(node: FunctionLikeDeclaration, location: TextRange, name: Identifier, container: Node): FunctionExpression { + function transformFunctionLikeToExpression(node: FunctionLikeDeclaration, location: TextRange | undefined, name: Identifier | undefined, container: Node | undefined): FunctionExpression { const savedConvertedLoopState = convertedLoopState; convertedLoopState = undefined; const ancestorFacts = container && isClassLike(container) && !hasModifier(node, ModifierFlags.Static) @@ -1829,11 +1830,11 @@ namespace ts { let multiLine = false; // indicates whether the block *must* be emitted as multiple lines let singleLine = false; // indicates whether the block *may* be emitted as a single line let statementsLocation: TextRange; - let closeBraceLocation: TextRange; + let closeBraceLocation: TextRange | undefined; const statements: Statement[] = []; - const body = node.body; - let statementOffset: number; + const body = node.body!; + let statementOffset: number | undefined; resumeLexicalEnvironment(); if (isBlock(body)) { @@ -1919,7 +1920,7 @@ namespace ts { } function visitFunctionBodyDownLevel(node: FunctionDeclaration | FunctionExpression | AccessorDeclaration) { - const updated = visitFunctionBody(node.body, functionBodyVisitor, context); + const updated = visitFunctionBody(node.body, functionBodyVisitor, context)!; return updateBlock( updated, setTextRange( @@ -2003,12 +2004,12 @@ namespace ts { return visitEachChild(node, visitor, context); } - function visitVariableStatement(node: VariableStatement): Statement { + function visitVariableStatement(node: VariableStatement): Statement | undefined { const ancestorFacts = enterSubtree(HierarchyFacts.None, hasModifier(node, ModifierFlags.Export) ? HierarchyFacts.ExportedVariableStatement : HierarchyFacts.None); - let updated: Statement; + let updated: Statement | undefined; if (convertedLoopState && (node.declarationList.flags & NodeFlags.BlockScoped) === 0) { // we are inside a converted loop - hoist variable declarations - let assignments: Expression[]; + let assignments: Expression[] | undefined; for (const decl of node.declarationList.declarations) { hoistVariableDeclarationDeclaredInConvertedLoop(convertedLoopState, decl); if (decl.initializer) { @@ -2066,13 +2067,12 @@ namespace ts { setCommentRange(declarationList, node); if (node.transformFlags & TransformFlags.ContainsBindingPattern - && (isBindingPattern(node.declarations[0].name) || isBindingPattern(lastOrUndefined(node.declarations).name))) { + && (isBindingPattern(node.declarations[0].name) || isBindingPattern(last(node.declarations).name))) { // If the first or last declaration is a binding pattern, we need to modify // the source map range for the declaration list. const firstDeclaration = firstOrUndefined(declarations); if (firstDeclaration) { - const lastDeclaration = lastOrUndefined(declarations); - setSourceMapRange(declarationList, createRange(firstDeclaration.pos, lastDeclaration.end)); + setSourceMapRange(declarationList, createRange(firstDeclaration.pos, last(declarations).end)); } } @@ -2198,11 +2198,11 @@ namespace ts { } function recordLabel(node: LabeledStatement) { - convertedLoopState.labels.set(idText(node.label), true); + convertedLoopState!.labels!.set(idText(node.label), true); } function resetLabel(node: LabeledStatement) { - convertedLoopState.labels.set(idText(node.label), false); + convertedLoopState!.labels!.set(idText(node.label), false); } function visitLabeledStatement(node: LabeledStatement): VisitResult { @@ -2229,14 +2229,14 @@ namespace ts { } } - function visitIterationStatementWithFacts(excludeFacts: HierarchyFacts, includeFacts: HierarchyFacts, node: IterationStatement, outermostLabeledStatement: LabeledStatement, convert?: LoopConverter) { + function visitIterationStatementWithFacts(excludeFacts: HierarchyFacts, includeFacts: HierarchyFacts, node: IterationStatement, outermostLabeledStatement: LabeledStatement | undefined, convert?: LoopConverter) { const ancestorFacts = enterSubtree(excludeFacts, includeFacts); const updated = convertIterationStatementBodyIfNecessary(node, outermostLabeledStatement, convert); exitSubtree(ancestorFacts, HierarchyFacts.None, HierarchyFacts.None); return updated; } - function visitDoOrWhileStatement(node: DoStatement | WhileStatement, outermostLabeledStatement: LabeledStatement) { + function visitDoOrWhileStatement(node: DoStatement | WhileStatement, outermostLabeledStatement: LabeledStatement | undefined) { return visitIterationStatementWithFacts( HierarchyFacts.DoOrWhileStatementExcludes, HierarchyFacts.DoOrWhileStatementIncludes, @@ -2244,7 +2244,7 @@ namespace ts { outermostLabeledStatement); } - function visitForStatement(node: ForStatement, outermostLabeledStatement: LabeledStatement) { + function visitForStatement(node: ForStatement, outermostLabeledStatement: LabeledStatement | undefined) { return visitIterationStatementWithFacts( HierarchyFacts.ForStatementExcludes, HierarchyFacts.ForStatementIncludes, @@ -2252,7 +2252,7 @@ namespace ts { outermostLabeledStatement); } - function visitForInStatement(node: ForInStatement, outermostLabeledStatement: LabeledStatement) { + function visitForInStatement(node: ForInStatement, outermostLabeledStatement: LabeledStatement | undefined) { return visitIterationStatementWithFacts( HierarchyFacts.ForInOrForOfStatementExcludes, HierarchyFacts.ForInOrForOfStatementIncludes, @@ -2260,7 +2260,7 @@ namespace ts { outermostLabeledStatement); } - function visitForOfStatement(node: ForOfStatement, outermostLabeledStatement: LabeledStatement): VisitResult { + function visitForOfStatement(node: ForOfStatement, outermostLabeledStatement: LabeledStatement | undefined): VisitResult { return visitIterationStatementWithFacts( HierarchyFacts.ForInOrForOfStatementExcludes, HierarchyFacts.ForInOrForOfStatementIncludes, @@ -2271,12 +2271,13 @@ namespace ts { function convertForOfStatementHead(node: ForOfStatement, boundValue: Expression, convertedLoopBodyStatements: Statement[]) { const statements: Statement[] = []; - if (isVariableDeclarationList(node.initializer)) { + const initializer = node.initializer; + if (isVariableDeclarationList(initializer)) { if (node.initializer.flags & NodeFlags.BlockScoped) { enableSubstitutionsForBlockScopedBindings(); } - const firstOriginalDeclaration = firstOrUndefined(node.initializer.declarations); + const firstOriginalDeclaration = firstOrUndefined(initializer.declarations); if (firstOriginalDeclaration && isBindingPattern(firstOriginalDeclaration.name)) { // This works whether the declaration is a var, let, or const. // It will use rhsIterationValue _a[_i] as the initializer. @@ -2293,9 +2294,7 @@ namespace ts { // Adjust the source map range for the first declaration to align with the old // emitter. - const firstDeclaration = declarations[0]; - const lastDeclaration = lastOrUndefined(declarations); - setSourceMapRange(declarationList, createRange(firstDeclaration.pos, lastDeclaration.end)); + setSourceMapRange(declarationList, createRange(declarations[0].pos, last(declarations).end)); statements.push( createVariableStatement( @@ -2320,12 +2319,12 @@ namespace ts { boundValue ) ]), - moveRangePos(node.initializer, -1) + moveRangePos(initializer, -1) ), - node.initializer + initializer ) ), - moveRangeEnd(node.initializer, -1) + moveRangeEnd(initializer, -1) ) ); } @@ -2333,14 +2332,14 @@ namespace ts { else { // Initializer is an expression. Emit the expression in the body, so that it's // evaluated on every iteration. - const assignment = createAssignment(node.initializer, boundValue); + const assignment = createAssignment(initializer, boundValue); if (isDestructuringAssignment(assignment)) { aggregateTransformFlags(assignment); statements.push(createStatement(visitBinaryExpression(assignment, /*needsDestructuringValue*/ false))); } else { - assignment.end = node.initializer.end; - statements.push(setTextRange(createStatement(visitNode(assignment, visitor, isExpression)), moveRangeEnd(node.initializer, -1))); + assignment.end = initializer.end; + statements.push(setTextRange(createStatement(visitNode(assignment, visitor, isExpression)), moveRangeEnd(initializer, -1))); } } @@ -2565,7 +2564,7 @@ namespace ts { && i < numInitialPropertiesWithoutYield) { numInitialPropertiesWithoutYield = i; } - if (property.name.kind === SyntaxKind.ComputedPropertyName) { + if (property.name!.kind === SyntaxKind.ComputedPropertyName) { numInitialProperties = i; break; } @@ -2625,7 +2624,7 @@ namespace ts { function visit(node: Identifier | BindingPattern) { if (node.kind === SyntaxKind.Identifier) { - state.hoistedLocalVariables.push(node); + state.hoistedLocalVariables!.push(node); } else { for (const element of node.elements) { @@ -2637,9 +2636,9 @@ namespace ts { } } - function convertIterationStatementBodyIfNecessary(node: IterationStatement, outermostLabeledStatement: LabeledStatement, convert?: LoopConverter): VisitResult { + function convertIterationStatementBodyIfNecessary(node: IterationStatement, outermostLabeledStatement: LabeledStatement | undefined, convert?: LoopConverter): VisitResult { if (!shouldConvertIterationStatementBody(node)) { - let saveAllowedNonLabeledJumps: Jump; + let saveAllowedNonLabeledJumps: Jump | undefined; if (convertedLoopState) { // we get here if we are trying to emit normal loop loop inside converted loop // set allowedNonLabeledJumps to Break | Continue to mark that break\continue inside the loop should be emitted as is @@ -2658,7 +2657,7 @@ namespace ts { } const functionName = createUniqueName("_loop"); - let loopInitializer: VariableDeclarationList; + let loopInitializer: VariableDeclarationList | undefined; switch (node.kind) { case SyntaxKind.ForStatement: case SyntaxKind.ForInStatement: @@ -2766,7 +2765,7 @@ namespace ts { const statements: Statement[] = [convertedLoopVariable]; - let extraVariableDeclarations: VariableDeclaration[]; + let extraVariableDeclarations: VariableDeclaration[] | undefined; // propagate state from the inner loop to the outer loop if necessary if (currentState.argumentsName) { // if alias for arguments is set @@ -2851,7 +2850,7 @@ namespace ts { else { let clone = getMutableClone(node); // clean statement part - clone.statement = undefined; + clone.statement = undefined!; // visit childnodes to transform initializer/condition/incrementor parts clone = visitEachChild(clone, visitor, context); // set loop statement @@ -2886,7 +2885,7 @@ namespace ts { // simple loops are emitted as just 'loop()'; // NOTE: if loop uses only 'continue' it still will be emitted as simple loop const isSimpleLoop = - !(state.nonLocalJumps & ~Jump.Continue) && + !(state.nonLocalJumps! & ~Jump.Continue) && !state.labeledNonLocalBreaks && !state.labeledNonLocalContinues; @@ -2899,7 +2898,7 @@ namespace ts { : call; if (isSimpleLoop) { statements.push(createStatement(callResult)); - copyOutParameters(state.loopOutParameters, CopyDirection.ToOriginal, statements); + copyOutParameters(state.loopOutParameters!, CopyDirection.ToOriginal, statements); } else { const loopResultName = createUniqueName("state"); @@ -2910,12 +2909,12 @@ namespace ts { ) ); statements.push(stateVariable); - copyOutParameters(state.loopOutParameters, CopyDirection.ToOriginal, statements); + copyOutParameters(state.loopOutParameters!, CopyDirection.ToOriginal, statements); - if (state.nonLocalJumps & Jump.Return) { + if (state.nonLocalJumps! & Jump.Return) { let returnStatement: ReturnStatement; if (outerConvertedLoopState) { - outerConvertedLoopState.nonLocalJumps |= Jump.Return; + outerConvertedLoopState.nonLocalJumps! |= Jump.Return; returnStatement = createReturn(loopResultName); } else { @@ -2933,7 +2932,7 @@ namespace ts { ); } - if (state.nonLocalJumps & Jump.Break) { + if (state.nonLocalJumps! & Jump.Break) { statements.push( createIf( createBinary( @@ -2948,8 +2947,8 @@ namespace ts { if (state.labeledNonLocalBreaks || state.labeledNonLocalContinues) { const caseClauses: CaseClause[] = []; - processLabeledJumps(state.labeledNonLocalBreaks, /*isBreak*/ true, loopResultName, outerConvertedLoopState, caseClauses); - processLabeledJumps(state.labeledNonLocalContinues, /*isBreak*/ false, loopResultName, outerConvertedLoopState, caseClauses); + processLabeledJumps(state.labeledNonLocalBreaks!, /*isBreak*/ true, loopResultName, outerConvertedLoopState, caseClauses); + processLabeledJumps(state.labeledNonLocalContinues!, /*isBreak*/ false, loopResultName, outerConvertedLoopState, caseClauses); statements.push( createSwitch( loopResultName, @@ -2976,7 +2975,7 @@ namespace ts { } } - function processLabeledJumps(table: Map, isBreak: boolean, loopResultName: Identifier, outerLoop: ConvertedLoopState, caseClauses: CaseClause[]): void { + function processLabeledJumps(table: Map, isBreak: boolean, loopResultName: Identifier, outerLoop: ConvertedLoopState | undefined, caseClauses: CaseClause[]): void { if (!table) { return; } @@ -3034,21 +3033,21 @@ namespace ts { case SyntaxKind.SetAccessor: const accessors = getAllAccessorDeclarations(node.properties, property); if (property === accessors.firstAccessor) { - expressions.push(transformAccessorsToExpression(receiver, accessors, node, node.multiLine)); + expressions.push(transformAccessorsToExpression(receiver, accessors, node, !!node.multiLine)); } break; case SyntaxKind.MethodDeclaration: - expressions.push(transformObjectLiteralMethodDeclarationToExpression(property, receiver, node, node.multiLine)); + expressions.push(transformObjectLiteralMethodDeclarationToExpression(property, receiver, node, node.multiLine!)); break; case SyntaxKind.PropertyAssignment: - expressions.push(transformPropertyAssignmentToExpression(property, receiver, node.multiLine)); + expressions.push(transformPropertyAssignmentToExpression(property, receiver, node.multiLine!)); break; case SyntaxKind.ShorthandPropertyAssignment: - expressions.push(transformShorthandPropertyAssignmentToExpression(property, receiver, node.multiLine)); + expressions.push(transformShorthandPropertyAssignmentToExpression(property, receiver, node.multiLine!)); break; default: @@ -3130,12 +3129,12 @@ namespace ts { const ancestorFacts = enterSubtree(HierarchyFacts.BlockScopeExcludes, HierarchyFacts.BlockScopeIncludes); let updated: CatchClause; Debug.assert(!!node.variableDeclaration, "Catch clause variable should always be present when downleveling ES2015."); - if (isBindingPattern(node.variableDeclaration.name)) { + if (isBindingPattern(node.variableDeclaration!.name)) { const temp = createTempVariable(/*recordTempVariable*/ undefined); const newVariableDeclaration = createVariableDeclaration(temp); setTextRange(newVariableDeclaration, node.variableDeclaration); const vars = flattenDestructuringBinding( - node.variableDeclaration, + node.variableDeclaration!, visitor, context, FlattenLevel.All, @@ -3247,7 +3246,7 @@ namespace ts { function visitArrayLiteralExpression(node: ArrayLiteralExpression): Expression { if (node.transformFlags & TransformFlags.ES2015) { // We are here because we contain a SpreadElementExpression. - return transformAndSpreadElements(node.elements, /*needsUniqueCopy*/ true, node.multiLine, /*hasTrailingComma*/ node.elements.hasTrailingComma); + return transformAndSpreadElements(node.elements, /*needsUniqueCopy*/ true, !!node.multiLine, /*hasTrailingComma*/ !!node.elements.hasTrailingComma); } return visitEachChild(node, visitor, context); } @@ -3312,16 +3311,16 @@ namespace ts { // The class statements are the statements generated by visiting the first statement with initializer of the // body (1), while all other statements are added to remainingStatements (2) - const isVariableStatementWithInitializer = (stmt: Statement) => isVariableStatement(stmt) && !!firstOrUndefined(stmt.declarationList.declarations).initializer; + const isVariableStatementWithInitializer = (stmt: Statement) => isVariableStatement(stmt) && !!first(stmt.declarationList.declarations).initializer; const bodyStatements = visitNodes(body.statements, visitor, isStatement); const classStatements = filter(bodyStatements, isVariableStatementWithInitializer); const remainingStatements = filter(bodyStatements, stmt => !isVariableStatementWithInitializer(stmt)); - const varStatement = cast(firstOrUndefined(classStatements), isVariableStatement); + const varStatement = cast(first(classStatements), isVariableStatement); // We know there is only one variable declaration here as we verified this in an // earlier call to isTypeScriptClassWrapper const variable = varStatement.declarationList.declarations[0]; - const initializer = skipOuterExpressions(variable.initializer); + const initializer = skipOuterExpressions(variable.initializer!); // Under certain conditions, the 'ts' transformer may introduce a class alias, which // we see as an assignment, for example: @@ -3374,7 +3373,7 @@ namespace ts { } // Find the trailing 'return' statement (4) - while (!isReturnStatement(elementAt(funcStatements, classBodyEnd))) { + while (!isReturnStatement(elementAt(funcStatements, classBodyEnd)!)) { classBodyEnd--; } @@ -3517,7 +3516,7 @@ namespace ts { createFunctionApply( visitNode(target, visitor, isExpression), thisArg, - transformAndSpreadElements(createNodeArray([createVoidZero(), ...node.arguments]), /*needsUniqueCopy*/ false, /*multiLine*/ false, /*hasTrailingComma*/ false) + transformAndSpreadElements(createNodeArray([createVoidZero(), ...node.arguments!]), /*needsUniqueCopy*/ false, /*multiLine*/ false, /*hasTrailingComma*/ false) ), /*typeArguments*/ undefined, [] @@ -3571,7 +3570,7 @@ namespace ts { } // Rewrite using the pattern .concat(, , ...) - return createArrayConcat(segments.shift(), segments); + return createArrayConcat(segments.shift()!, segments); } } @@ -3650,7 +3649,7 @@ namespace ts { // Build up the template arguments and the raw and cooked strings for the template. // We start out with 'undefined' for the first argument and revisit later // to avoid walking over the template string twice and shifting all our arguments over after the fact. - const templateArguments: Expression[] = [undefined]; + const templateArguments: Expression[] = [undefined!]; const cookedStrings: Expression[] = []; const rawStrings: Expression[] = []; const template = node.template; @@ -3734,7 +3733,7 @@ namespace ts { // ("abc" + 1) << (2 + "") // rather than // "abc" + (1 << 2) + "" - const expression = reduceLeft(expressions, createAdd); + const expression = reduceLeft(expressions, createAdd)!; if (nodeIsSynthesized(expression)) { expression.pos = node.pos; expression.end = node.end; @@ -3921,14 +3920,13 @@ namespace ts { * @param node An original source tree node. */ function isNameOfDeclarationWithCollidingName(node: Identifier) { - const parent = node.parent; - switch (parent.kind) { + switch (node.parent.kind) { case SyntaxKind.BindingElement: case SyntaxKind.ClassDeclaration: case SyntaxKind.EnumDeclaration: case SyntaxKind.VariableDeclaration: - return (parent).name === node - && resolver.isDeclarationWithCollidingName(parent); + return (node.parent).name === node + && resolver.isDeclarationWithCollidingName(node.parent); } return false; @@ -3968,7 +3966,7 @@ namespace ts { } function isPartOfClassBody(declaration: ClassLikeDeclaration, node: Identifier) { - let currentNode = getParseTreeNode(node); + let currentNode: Node | undefined = getParseTreeNode(node); if (!currentNode || currentNode === declaration || currentNode.end <= declaration.pos || currentNode.pos >= declaration.end) { // if the node has no correlation to a parse tree node, its definitely not // part of the body. @@ -4010,7 +4008,7 @@ namespace ts { : createPropertyAccess(getInternalName(node), "prototype"); } - function hasSynthesizedDefaultSuperCall(constructor: ConstructorDeclaration, hasExtendsClause: boolean) { + function hasSynthesizedDefaultSuperCall(constructor: ConstructorDeclaration | undefined, hasExtendsClause: boolean) { if (!constructor || !hasExtendsClause) { return false; } @@ -4019,7 +4017,7 @@ namespace ts { return false; } - const statement = firstOrUndefined(constructor.body.statements); + const statement = firstOrUndefined(constructor.body!.statements); if (!statement || !nodeIsSynthesized(statement) || statement.kind !== SyntaxKind.ExpressionStatement) { return false; } diff --git a/src/compiler/transformers/es2017.ts b/src/compiler/transformers/es2017.ts index 0316c90b250a1..8cc9cf3a3a0ed 100644 --- a/src/compiler/transformers/es2017.ts +++ b/src/compiler/transformers/es2017.ts @@ -116,10 +116,10 @@ namespace ts { function visitCatchClauseInAsyncBody(node: CatchClause) { const catchClauseNames = createUnderscoreEscapedMap(); - recordDeclarationName(node.variableDeclaration, catchClauseNames); + recordDeclarationName(node.variableDeclaration!, catchClauseNames); // TODO: GH#18217 // names declared in a catch variable are block scoped - let catchClauseUnshadowedNames: UnderscoreEscapedMap; + let catchClauseUnshadowedNames: UnderscoreEscapedMap | undefined; catchClauseNames.forEach((_, escapedName) => { if (enclosingFunctionParameterNames.has(escapedName)) { if (!catchClauseUnshadowedNames) { @@ -153,7 +153,7 @@ namespace ts { return updateForIn( node, isVariableDeclarationListWithCollidingName(node.initializer) - ? visitVariableDeclarationListWithCollidingNames(node.initializer, /*hasReceiver*/ true) + ? visitVariableDeclarationListWithCollidingNames(node.initializer, /*hasReceiver*/ true)! : visitNode(node.initializer, visitor, isForInitializer), visitNode(node.expression, visitor, isExpression), visitNode(node.statement, asyncBodyVisitor, isStatement, liftToBlock) @@ -165,7 +165,7 @@ namespace ts { node, visitNode(node.awaitModifier, visitor, isToken), isVariableDeclarationListWithCollidingName(node.initializer) - ? visitVariableDeclarationListWithCollidingNames(node.initializer, /*hasReceiver*/ true) + ? visitVariableDeclarationListWithCollidingNames(node.initializer, /*hasReceiver*/ true)! : visitNode(node.initializer, visitor, isForInitializer), visitNode(node.expression, visitor, isExpression), visitNode(node.statement, asyncBodyVisitor, isStatement, liftToBlock) @@ -173,10 +173,11 @@ namespace ts { } function visitForStatementInAsyncBody(node: ForStatement) { + const initializer = node.initializer!; // TODO: GH#18217 return updateFor( node, - isVariableDeclarationListWithCollidingName(node.initializer) - ? visitVariableDeclarationListWithCollidingNames(node.initializer, /*hasReceiver*/ false) + isVariableDeclarationListWithCollidingName(initializer) + ? visitVariableDeclarationListWithCollidingNames(initializer, /*hasReceiver*/ false) : visitNode(node.initializer, visitor, isForInitializer), visitNode(node.condition, visitor, isExpression), visitNode(node.incrementor, visitor, isExpression), @@ -312,10 +313,10 @@ namespace ts { } function isVariableDeclarationListWithCollidingName(node: ForInitializer): node is VariableDeclarationList { - return node + return !!node && isVariableDeclarationList(node) && !(node.flags & NodeFlags.BlockScoped) - && forEach(node.declarations, collidesWithParameterName); + && node.declarations.some(collidesWithParameterName); } function visitVariableDeclarationListWithCollidingNames(node: VariableDeclarationList, hasReceiver: boolean) { @@ -353,7 +354,7 @@ namespace ts { const converted = setSourceMapRange( createAssignment( convertToAssignmentElementTarget(node.name), - node.initializer + node.initializer! ), node ); @@ -437,7 +438,7 @@ namespace ts { context, hasLexicalArguments, promiseConstructor, - transformAsyncFunctionBodyWorker(node.body) + transformAsyncFunctionBodyWorker(node.body!) ); const declarations = endLexicalEnvironment(); @@ -463,7 +464,7 @@ namespace ts { } } - function getPromiseConstructor(type: TypeNode) { + function getPromiseConstructor(type: TypeNode | undefined) { const typeName = type && getEntityNameFromTypeNode(type); if (typeName && isEntityName(typeName)) { const serializationKind = resolver.getTypeReferenceSerializationKind(typeName); @@ -634,7 +635,7 @@ namespace ts { };` }; - function createAwaiterHelper(context: TransformationContext, hasLexicalArguments: boolean, promiseConstructor: EntityName | Expression, body: Block) { + function createAwaiterHelper(context: TransformationContext, hasLexicalArguments: boolean, promiseConstructor: EntityName | Expression | undefined, body: Block) { context.requestEmitHelper(awaiterHelper); const generatorFunc = createFunctionExpression( @@ -648,7 +649,7 @@ namespace ts { ); // Mark this node as originally an async function - (generatorFunc.emitNode || (generatorFunc.emitNode = {})).flags |= EmitFlags.AsyncFunctionBody | EmitFlags.ReuseTempVariableScope; + (generatorFunc.emitNode || (generatorFunc.emitNode = {} as EmitNode)).flags |= EmitFlags.AsyncFunctionBody | EmitFlags.ReuseTempVariableScope; return createCall( getHelperName("__awaiter"), diff --git a/src/compiler/transformers/es5.ts b/src/compiler/transformers/es5.ts index bace315e95338..1c85e684e8cba 100644 --- a/src/compiler/transformers/es5.ts +++ b/src/compiler/transformers/es5.ts @@ -109,7 +109,7 @@ namespace ts { */ function trySubstituteReservedName(name: Identifier) { const token = name.originalKeywordKind || (nodeIsSynthesized(name) ? stringToToken(idText(name)) : undefined); - if (token >= SyntaxKind.FirstReservedWord && token <= SyntaxKind.LastReservedWord) { + if (token !== undefined && token >= SyntaxKind.FirstReservedWord && token <= SyntaxKind.LastReservedWord) { return setTextRange(createLiteral(name), name); } return undefined; diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index d054aaaf909df..a1d6631072fab 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -294,7 +294,7 @@ namespace ts { * * @param node A ForOfStatement. */ - function visitForOfStatement(node: ForOfStatement, outermostLabeledStatement: LabeledStatement): VisitResult { + function visitForOfStatement(node: ForOfStatement, outermostLabeledStatement: LabeledStatement | undefined): VisitResult { if (node.initializer.transformFlags & TransformFlags.ContainsObjectRest) { node = transformForOfStatementWithObjectRest(node); } @@ -309,8 +309,8 @@ namespace ts { function transformForOfStatementWithObjectRest(node: ForOfStatement) { const initializerWithoutParens = skipParentheses(node.initializer) as ForInitializer; if (isVariableDeclarationList(initializerWithoutParens) || isAssignmentPattern(initializerWithoutParens)) { - let bodyLocation: TextRange; - let statementsLocation: TextRange; + let bodyLocation: TextRange | undefined; + let statementsLocation: TextRange | undefined; const temp = createTempVariable(/*recordTempVariable*/ undefined); const statements: Statement[] = [createForOfBindingStatement(initializerWithoutParens, temp)]; if (isBlock(node.statement)) { @@ -351,8 +351,8 @@ namespace ts { function convertForOfStatementHead(node: ForOfStatement, boundValue: Expression) { const binding = createForOfBindingStatement(node.initializer, boundValue); - let bodyLocation: TextRange; - let statementsLocation: TextRange; + let bodyLocation: TextRange | undefined; + let statementsLocation: TextRange | undefined; const statements: Statement[] = [visitNode(binding, visitor, isStatement)]; const statement = visitNode(node.statement, visitor, isStatement); if (isBlock(statement)) { @@ -382,7 +382,7 @@ namespace ts { : createAwait(expression); } - function transformForAwaitOfStatement(node: ForOfStatement, outermostLabeledStatement: LabeledStatement) { + function transformForAwaitOfStatement(node: ForOfStatement, outermostLabeledStatement: LabeledStatement | undefined) { const expression = visitNode(node.expression, visitor, isExpression); const iterator = isIdentifier(expression) ? getGeneratedNameForNode(expression) : createTempVariable(/*recordTempVariable*/ undefined); const result = isIdentifier(expression) ? getGeneratedNameForNode(iterator) : createTempVariable(/*recordTempVariable*/ undefined); @@ -562,7 +562,7 @@ namespace ts { ? undefined : node.asteriskToken, visitNode(node.name, visitor, isPropertyName), - visitNode(/*questionToken*/ undefined, visitor, isToken), + visitNode>(/*questionToken*/ undefined, visitor, isToken), /*typeParameters*/ undefined, visitParameterList(node.parameters, visitor, context), /*type*/ undefined, @@ -640,7 +640,7 @@ namespace ts { function transformAsyncGeneratorFunctionBody(node: MethodDeclaration | AccessorDeclaration | FunctionDeclaration | FunctionExpression): FunctionBody { resumeLexicalEnvironment(); const statements: Statement[] = []; - const statementOffset = addPrologue(statements, node.body.statements, /*ensureUseStrict*/ false, visitor); + const statementOffset = addPrologue(statements, node.body!.statements, /*ensureUseStrict*/ false, visitor); appendObjectRestAssignmentsIfNeeded(statements, node); statements.push( @@ -655,8 +655,8 @@ namespace ts { /*parameters*/ [], /*type*/ undefined, updateBlock( - node.body, - visitLexicalEnvironment(node.body.statements, visitor, context, statementOffset) + node.body!, + visitLexicalEnvironment(node.body!.statements, visitor, context, statementOffset) ) ) ) @@ -664,7 +664,7 @@ namespace ts { ); prependRange(statements, endLexicalEnvironment()); - const block = updateBlock(node.body, statements); + const block = updateBlock(node.body!, statements); // Minor optimization, emit `_super` helper to capture `super` access in an arrow. // This step isn't needed if we eventually transform this to ES5. @@ -702,7 +702,7 @@ namespace ts { return body; } - function appendObjectRestAssignmentsIfNeeded(statements: Statement[], node: FunctionLikeDeclaration): Statement[] { + function appendObjectRestAssignmentsIfNeeded(statements: Statement[] | undefined, node: FunctionLikeDeclaration): Statement[] | undefined { for (const parameter of node.parameters) { if (parameter.transformFlags & TransformFlags.ContainsObjectRest) { const temp = getGeneratedNameForNode(parameter); @@ -889,7 +889,7 @@ namespace ts { }; export function createAssignHelper(context: TransformationContext, attributesSegments: Expression[]) { - if (context.getCompilerOptions().target >= ScriptTarget.ES2015) { + if (context.getCompilerOptions().target! >= ScriptTarget.ES2015) { return createCall(createPropertyAccess(createIdentifier("Object"), "assign"), /*typeArguments*/ undefined, attributesSegments); @@ -936,7 +936,7 @@ namespace ts { context.requestEmitHelper(asyncGeneratorHelper); // Mark this node as originally an async function - (generatorFunc.emitNode || (generatorFunc.emitNode = {})).flags |= EmitFlags.AsyncFunctionBody; + (generatorFunc.emitNode || (generatorFunc.emitNode = {} as EmitNode)).flags |= EmitFlags.AsyncFunctionBody; return createCall( getHelperName("__asyncGenerator"), diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts index 04d131b20a9fa..f796d64d03d74 100644 --- a/src/compiler/transformers/generators.ts +++ b/src/compiler/transformers/generators.ts @@ -135,7 +135,7 @@ namespace ts { Endfinally // Marks the end of a `finally` block } - type OperationArguments = [Label] | [Label, Expression] | [Statement] | [Expression] | [Expression, Expression]; + type OperationArguments = [Label] | [Label, Expression] | [Statement] | [Expression | undefined] | [Expression, Expression]; // whether a generated code block is opening or closing at the current operation for a FunctionBuilder const enum BlockAction { @@ -224,6 +224,7 @@ namespace ts { case Instruction.Yield: return "yield"; case Instruction.YieldStar: return "yield*"; case Instruction.Endfinally: return "endfinally"; + default: return undefined!; // TODO: GH#18217 } } @@ -251,18 +252,18 @@ namespace ts { // All three arrays are correlated by their index. This approach is used over allocating // objects to store the same information to avoid GC overhead. // - let blocks: CodeBlock[]; // Information about the code block - let blockOffsets: number[]; // The operation offset at which a code block begins or ends - let blockActions: BlockAction[]; // Whether the code block is opened or closed - let blockStack: CodeBlock[]; // A stack of currently open code blocks + let blocks: CodeBlock[] | undefined; // Information about the code block + let blockOffsets: number[] | undefined; // The operation offset at which a code block begins or ends + let blockActions: BlockAction[] | undefined; // Whether the code block is opened or closed + let blockStack: CodeBlock[] | undefined; // A stack of currently open code blocks // Labels are used to mark locations in the code that can be the target of a Break (jump) // operation. These are translated into case clauses in a switch statement. // The following two arrays are correlated by their index. This approach is used over // allocating objects to store the same information to avoid GC overhead. // - let labelOffsets: number[]; // The operation offset at which the label is defined. - let labelExpressions: LiteralExpression[][]; // The NumericLiteral nodes bound to each label. + let labelOffsets: number[] | undefined; // The operation offset at which the label is defined. + let labelExpressions: LiteralExpression[][] | undefined; // The NumericLiteral nodes bound to each label. let nextLabelId = 1; // The next label id to use. // Operations store information about generated code for the function body. This @@ -270,9 +271,9 @@ namespace ts { // The following three arrays are correlated by their index. This approach is used over // allocating objects to store the same information to avoid GC overhead. // - let operations: OpCode[]; // The operation to perform. - let operationArguments: OperationArguments[]; // The arguments to the operation. - let operationLocations: TextRange[]; // The source map location for the operation. + let operations: OpCode[] | undefined; // The operation to perform. + let operationArguments: (OperationArguments | undefined)[] | undefined; // The arguments to the operation. + let operationLocations: (TextRange | undefined)[] | undefined; // The source map location for the operation. let state: Identifier; // The name of the state object used by the generator at runtime. @@ -280,14 +281,14 @@ namespace ts { // let blockIndex = 0; // The index of the current block. let labelNumber = 0; // The current label number. - let labelNumbers: number[][]; + let labelNumbers: number[][] | undefined; let lastOperationWasAbrupt: boolean; // Indicates whether the last operation was abrupt (break/continue). let lastOperationWasCompletion: boolean; // Indicates whether the last operation was a completion (return/throw). - let clauses: CaseClause[]; // The case clauses generated for labels. - let statements: Statement[]; // The statements for the current label. - let exceptionBlockStack: ExceptionBlock[]; // A stack of containing exception blocks. - let currentExceptionBlock: ExceptionBlock; // The current exception block. - let withBlockStack: WithBlock[]; // A stack containing `with` blocks. + let clauses: CaseClause[] | undefined; // The case clauses generated for labels. + let statements: Statement[] | undefined; // The statements for the current label. + let exceptionBlockStack: ExceptionBlock[] | undefined; // A stack of containing exception blocks. + let currentExceptionBlock: ExceptionBlock | undefined; // The current exception block. + let withBlockStack: WithBlock[] | undefined; // A stack containing `with` blocks. return chainBundle(transformSourceFile); @@ -440,7 +441,7 @@ namespace ts { * * @param node The node to visit. */ - function visitFunctionDeclaration(node: FunctionDeclaration): Statement { + function visitFunctionDeclaration(node: FunctionDeclaration): Statement | undefined { // Currently, we only support generators that were originally async functions. if (node.asteriskToken) { node = setOriginalNode( @@ -453,7 +454,7 @@ namespace ts { /*typeParameters*/ undefined, visitParameterList(node.parameters, visitor, context), /*type*/ undefined, - transformGeneratorFunctionBody(node.body) + transformGeneratorFunctionBody(node.body!) ), /*location*/ node ), @@ -615,7 +616,7 @@ namespace ts { * * @param node The node to visit. */ - function visitVariableStatement(node: VariableStatement): Statement { + function visitVariableStatement(node: VariableStatement): Statement | undefined { if (node.transformFlags & TransformFlags.ContainsYield) { transformAndEmitVariableDeclarationList(node.declarationList); return undefined; @@ -655,13 +656,14 @@ namespace ts { * @param node The node to visit. */ function visitBinaryExpression(node: BinaryExpression): Expression { - switch (getExpressionAssociativity(node)) { + const assoc = getExpressionAssociativity(node); + switch (assoc) { case Associativity.Left: return visitLeftAssociativeBinaryExpression(node); case Associativity.Right: return visitRightAssociativeBinaryExpression(node); default: - Debug.fail("Unknown associativity."); + return Debug.assertNever(assoc); } } @@ -934,9 +936,9 @@ namespace ts { // x = %sent%; const resumeLabel = defineLabel(); - const expression = visitNode(node.expression, visitor, isExpression); + const expression = visitNode(node.expression!, visitor, isExpression); if (node.asteriskToken) { - const iterator = (getEmitFlags(node.expression) & EmitFlags.Iterator) === 0 + const iterator = (getEmitFlags(node.expression!) & EmitFlags.Iterator) === 0 ? createValuesHelper(context, expression, /*location*/ node) : expression; emitYieldStar(iterator, /*location*/ node); @@ -978,7 +980,7 @@ namespace ts { const numInitialElements = countInitialNodesWithoutYield(elements); - let temp: Identifier; + let temp: Identifier | undefined; if (numInitialElements > 0) { temp = declareLocal(); const initialElements = visitNodes(elements, visitor, isExpression, 0, numInitialElements); @@ -1155,7 +1157,7 @@ namespace ts { cacheExpression(visitNode(target, visitor, isExpression)), thisArg, visitElements( - node.arguments, + node.arguments!, /*leadingElement*/ createVoidZero() ) ), @@ -1246,7 +1248,7 @@ namespace ts { emitStatement(visitNode(node, visitor, isStatement)); } - function transformAndEmitVariableDeclarationList(node: VariableDeclarationList): VariableDeclarationList { + function transformAndEmitVariableDeclarationList(node: VariableDeclarationList): VariableDeclarationList | undefined { for (const variable of node.declarations) { const name = getSynthesizedClone(variable.name); setCommentRange(name, variable.name); @@ -1260,7 +1262,7 @@ namespace ts { while (variablesWritten < numVariables) { for (let i = variablesWritten; i < numVariables; i++) { const variable = variables[i]; - if (containsYield(variable.initializer) && pendingExpressions.length > 0) { + if (containsYield(variable.initializer!) && pendingExpressions.length > 0) { break; } @@ -1281,7 +1283,7 @@ namespace ts { return setSourceMapRange( createAssignment( setSourceMapRange(getSynthesizedClone(node.name), node.name), - visitNode(node.initializer, visitor, isExpression) + visitNode(node.initializer!, visitor, isExpression) ), node ); @@ -1306,11 +1308,11 @@ namespace ts { if (containsYield(node.thenStatement) || containsYield(node.elseStatement)) { const endLabel = defineLabel(); const elseLabel = node.elseStatement ? defineLabel() : undefined; - emitBreakWhenFalse(node.elseStatement ? elseLabel : endLabel, visitNode(node.expression, visitor, isExpression), /*location*/ node.expression); + emitBreakWhenFalse(node.elseStatement ? elseLabel! : endLabel, visitNode(node.expression, visitor, isExpression), /*location*/ node.expression); transformAndEmitEmbeddedStatement(node.thenStatement); if (node.elseStatement) { emitBreak(endLabel); - markLabel(elseLabel); + markLabel(elseLabel!); transformAndEmitEmbeddedStatement(node.elseStatement); } markLabel(endLabel); @@ -1866,7 +1868,7 @@ namespace ts { function transformAndEmitThrowStatement(node: ThrowStatement): void { emitThrow( - visitNode(node.expression, visitor, isExpression), + visitNode(node.expression!, visitor, isExpression), /*location*/ node ); } @@ -1906,7 +1908,7 @@ namespace ts { beginExceptionBlock(); transformAndEmitEmbeddedStatement(node.tryBlock); if (node.catchClause) { - beginCatchBlock(node.catchClause.variableDeclaration); + beginCatchBlock(node.catchClause.variableDeclaration!); // TODO: GH#18217 transformAndEmitEmbeddedStatement(node.catchClause.block); } @@ -1922,8 +1924,8 @@ namespace ts { } } - function containsYield(node: Node) { - return node && (node.transformFlags & TransformFlags.ContainsYield) !== 0; + function containsYield(node: Node | undefined): boolean { + return !!node && (node.transformFlags & TransformFlags.ContainsYield) !== 0; } function countInitialNodesWithoutYield(nodes: NodeArray) { @@ -2010,7 +2012,7 @@ namespace ts { */ function markLabel(label: Label): void { Debug.assert(labelOffsets !== undefined, "No labels were defined."); - labelOffsets[label] = operations ? operations.length : 0; + labelOffsets![label] = operations ? operations.length : 0; } /** @@ -2026,11 +2028,11 @@ namespace ts { blockStack = []; } - const index = blockActions.length; - blockActions[index] = BlockAction.Open; - blockOffsets[index] = operations ? operations.length : 0; + const index = blockActions!.length; + blockActions![index] = BlockAction.Open; + blockOffsets![index] = operations ? operations.length : 0; blocks[index] = block; - blockStack.push(block); + blockStack!.push(block); return index; } @@ -2039,13 +2041,13 @@ namespace ts { */ function endBlock(): CodeBlock { const block = peekBlock(); - Debug.assert(block !== undefined, "beginBlock was never called."); + if (block === undefined) return Debug.fail("beginBlock was never called."); - const index = blockActions.length; - blockActions[index] = BlockAction.Close; - blockOffsets[index] = operations ? operations.length : 0; - blocks[index] = block; - blockStack.pop(); + const index = blockActions!.length; + blockActions![index] = BlockAction.Close; + blockOffsets![index] = operations ? operations.length : 0; + blocks![index] = block; + blockStack!.pop(); return block; } @@ -2053,13 +2055,13 @@ namespace ts { * Gets the current open block. */ function peekBlock() { - return lastOrUndefined(blockStack); + return lastOrUndefined(blockStack!); } /** * Gets the kind of the current open block. */ - function peekBlockKind(): CodeBlockKind { + function peekBlockKind(): CodeBlockKind | undefined { const block = peekBlock(); return block && block.kind; } @@ -2331,7 +2333,7 @@ namespace ts { function hasImmediateContainingLabeledBlock(labelText: string, start: number) { for (let j = start; j >= 0; j--) { - const containingBlock = blockStack[j]; + const containingBlock = blockStack![j]; if (supportsLabeledBreakOrContinue(containingBlock)) { if (containingBlock.labelText === labelText) { return true; @@ -2407,8 +2409,8 @@ namespace ts { * * @param label A label. */ - function createLabel(label: Label): Expression { - if (label > 0) { + function createLabel(label: Label | undefined): Expression { + if (label !== undefined && label > 0) { if (labelExpressions === undefined) { labelExpressions = []; } @@ -2620,8 +2622,8 @@ namespace ts { const operationIndex = operations.length; operations[operationIndex] = code; - operationArguments[operationIndex] = args; - operationLocations[operationIndex] = location; + operationArguments![operationIndex] = args; + operationLocations![operationIndex] = location; } /** @@ -2869,9 +2871,9 @@ namespace ts { */ function tryEnterOrLeaveBlock(operationIndex: number): void { if (blocks) { - for (; blockIndex < blockActions.length && blockOffsets[blockIndex] <= operationIndex; blockIndex++) { + for (; blockIndex < blockActions!.length && blockOffsets![blockIndex] <= operationIndex; blockIndex++) { const block = blocks[blockIndex]; - const blockAction = blockActions[blockIndex]; + const blockAction = blockActions![blockIndex]; switch (block.kind) { case CodeBlockKind.Exception: if (blockAction === BlockAction.Open) { @@ -2883,11 +2885,11 @@ namespace ts { statements = []; } - exceptionBlockStack.push(currentExceptionBlock); + exceptionBlockStack.push(currentExceptionBlock!); currentExceptionBlock = block; } else if (blockAction === BlockAction.Close) { - currentExceptionBlock = exceptionBlockStack.pop(); + currentExceptionBlock = exceptionBlockStack!.pop(); } break; case CodeBlockKind.With: @@ -2899,7 +2901,7 @@ namespace ts { withBlockStack.push(block); } else if (blockAction === BlockAction.Close) { - withBlockStack.pop(); + withBlockStack!.pop(); } break; // default: do nothing @@ -2925,7 +2927,7 @@ namespace ts { lastOperationWasAbrupt = false; lastOperationWasCompletion = false; - const opcode = operations[operationIndex]; + const opcode = operations![operationIndex]; if (opcode === OpCode.Nop) { return; } @@ -2933,12 +2935,12 @@ namespace ts { return writeEndfinally(); } - const args = operationArguments[operationIndex]; + const args = operationArguments![operationIndex]!; if (opcode === OpCode.Statement) { return writeStatement(args[0]); } - const location = operationLocations[operationIndex]; + const location = operationLocations![operationIndex]; switch (opcode) { case OpCode.Assign: return writeAssign(args[0], args[1], location); @@ -2982,7 +2984,7 @@ namespace ts { * @param right The right-hand side of the assignment. * @param operationLocation The source map location for the operation. */ - function writeAssign(left: Expression, right: Expression, operationLocation: TextRange): void { + function writeAssign(left: Expression, right: Expression, operationLocation: TextRange | undefined): void { writeStatement(setTextRange(createStatement(createAssignment(left, right)), operationLocation)); } @@ -2992,7 +2994,7 @@ namespace ts { * @param expression The value to throw. * @param operationLocation The source map location for the operation. */ - function writeThrow(expression: Expression, operationLocation: TextRange): void { + function writeThrow(expression: Expression, operationLocation: TextRange | undefined): void { lastOperationWasAbrupt = true; lastOperationWasCompletion = true; writeStatement(setTextRange(createThrow(expression), operationLocation)); @@ -3004,7 +3006,7 @@ namespace ts { * @param expression The value to return. * @param operationLocation The source map location for the operation. */ - function writeReturn(expression: Expression, operationLocation: TextRange): void { + function writeReturn(expression: Expression | undefined, operationLocation: TextRange | undefined): void { lastOperationWasAbrupt = true; lastOperationWasCompletion = true; writeStatement( @@ -3029,7 +3031,7 @@ namespace ts { * @param label The label for the Break. * @param operationLocation The source map location for the operation. */ - function writeBreak(label: Label, operationLocation: TextRange): void { + function writeBreak(label: Label, operationLocation: TextRange | undefined): void { lastOperationWasAbrupt = true; writeStatement( setEmitFlags( @@ -3054,7 +3056,7 @@ namespace ts { * @param condition The condition for the Break. * @param operationLocation The source map location for the operation. */ - function writeBreakWhenTrue(label: Label, condition: Expression, operationLocation: TextRange): void { + function writeBreakWhenTrue(label: Label, condition: Expression, operationLocation: TextRange | undefined): void { writeStatement( setEmitFlags( createIf( @@ -3084,7 +3086,7 @@ namespace ts { * @param condition The condition for the Break. * @param operationLocation The source map location for the operation. */ - function writeBreakWhenFalse(label: Label, condition: Expression, operationLocation: TextRange): void { + function writeBreakWhenFalse(label: Label, condition: Expression, operationLocation: TextRange | undefined): void { writeStatement( setEmitFlags( createIf( @@ -3113,7 +3115,7 @@ namespace ts { * @param expression The expression to yield. * @param operationLocation The source map location for the operation. */ - function writeYield(expression: Expression, operationLocation: TextRange): void { + function writeYield(expression: Expression, operationLocation: TextRange | undefined): void { lastOperationWasAbrupt = true; writeStatement( setEmitFlags( @@ -3138,7 +3140,7 @@ namespace ts { * @param expression The expression to yield. * @param operationLocation The source map location for the operation. */ - function writeYieldStar(expression: Expression, operationLocation: TextRange): void { + function writeYieldStar(expression: Expression, operationLocation: TextRange | undefined): void { lastOperationWasAbrupt = true; writeStatement( setEmitFlags( diff --git a/src/compiler/transformers/jsx.ts b/src/compiler/transformers/jsx.ts index 48d3bee42d6a8..c31cdd17f027c 100644 --- a/src/compiler/transformers/jsx.ts +++ b/src/compiler/transformers/jsx.ts @@ -50,7 +50,7 @@ namespace ts { } } - function transformJsxChildToExpression(node: JsxChild): Expression { + function transformJsxChildToExpression(node: JsxChild): Expression | undefined { switch (node.kind) { case SyntaxKind.JsxText: return visitJsxText(node); @@ -84,9 +84,9 @@ namespace ts { return visitJsxOpeningFragment(node.openingFragment, node.children, isChild, /*location*/ node); } - function visitJsxOpeningLikeElement(node: JsxOpeningLikeElement, children: ReadonlyArray, isChild: boolean, location: TextRange) { + function visitJsxOpeningLikeElement(node: JsxOpeningLikeElement, children: ReadonlyArray | undefined, isChild: boolean, location: TextRange) { const tagName = getTagName(node); - let objectProperties: Expression; + let objectProperties: Expression | undefined; const attrs = node.attributes.properties; if (attrs.length === 0) { // When there are no attributes, React wants "null" @@ -118,7 +118,7 @@ namespace ts { const element = createExpressionForJsxElement( context.getEmitResolver().getJsxFactoryEntity(currentSourceFile), - compilerOptions.reactNamespace, + compilerOptions.reactNamespace!, // TODO: GH#18217 tagName, objectProperties, mapDefined(children, transformJsxChildToExpression), @@ -136,7 +136,7 @@ namespace ts { function visitJsxOpeningFragment(node: JsxOpeningFragment, children: ReadonlyArray, isChild: boolean, location: TextRange) { const element = createExpressionForJsxFragment( context.getEmitResolver().getJsxFactoryEntity(currentSourceFile), - compilerOptions.reactNamespace, + compilerOptions.reactNamespace!, // TODO: GH#18217 mapDefined(children, transformJsxChildToExpression), node, location @@ -159,7 +159,7 @@ namespace ts { return createPropertyAssignment(name, expression); } - function transformJsxAttributeInitializer(node: StringLiteral | JsxExpression) { + function transformJsxAttributeInitializer(node: StringLiteral | JsxExpression | undefined): Expression { if (node === undefined) { return createTrue(); } @@ -563,4 +563,4 @@ namespace ts { hearts: 0x2665, diams: 0x2666 }); -} \ No newline at end of file +} diff --git a/src/compiler/transformers/module/es2015.ts b/src/compiler/transformers/module/es2015.ts index 070980df5de15..792dd9445960f 100644 --- a/src/compiler/transformers/module/es2015.ts +++ b/src/compiler/transformers/module/es2015.ts @@ -9,7 +9,7 @@ namespace ts { context.enableEmitNotification(SyntaxKind.SourceFile); context.enableSubstitution(SyntaxKind.Identifier); - let currentSourceFile: SourceFile; + let currentSourceFile: SourceFile | undefined; return chainBundle(transformSourceFile); function transformSourceFile(node: SourceFile) { @@ -104,7 +104,7 @@ namespace ts { function substituteExpressionIdentifier(node: Identifier): Expression { if (getEmitFlags(node) & EmitFlags.HelperName) { - const externalHelpersModuleName = getExternalHelpersModuleName(currentSourceFile); + const externalHelpersModuleName = getExternalHelpersModuleName(currentSourceFile!); if (externalHelpersModuleName) { return createPropertyAccess(externalHelpersModuleName, node); } diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts index dbc29215e408f..86d0a6bc9527d 100644 --- a/src/compiler/transformers/module/module.ts +++ b/src/compiler/transformers/module/module.ts @@ -38,7 +38,7 @@ namespace ts { context.enableEmitNotification(SyntaxKind.SourceFile); // Restore state when substituting nodes in a file. const moduleInfoMap: ExternalModuleInfo[] = []; // The ExternalModuleInfo for each file. - const deferredExports: Statement[][] = []; // Exports to defer until an EndOfDeclarationMarker is found. + const deferredExports: (Statement[] | undefined)[] = []; // Exports to defer until an EndOfDeclarationMarker is found. let currentSourceFile: SourceFile; // The current file. let currentModuleInfo: ExternalModuleInfo; // The ExternalModuleInfo for the current file. @@ -64,8 +64,8 @@ namespace ts { // Perform the transformation. const transformModule = getTransformModuleDelegate(moduleKind); const updated = transformModule(node); - currentSourceFile = undefined; - currentModuleInfo = undefined; + currentSourceFile = undefined!; + currentModuleInfo = undefined!; needUMDDynamicImportHelper = false; return aggregateTransformFlags(updated); } @@ -391,7 +391,7 @@ namespace ts { if (isImportEqualsDeclaration(node) || isExportDeclaration(node) || !getExternalModuleNameLiteral(node, currentSourceFile, host, resolver, compilerOptions)) { return undefined; } - const name = getLocalNameForExternalImport(node, currentSourceFile); + const name = getLocalNameForExternalImport(node, currentSourceFile)!; // TODO: GH#18217 const expr = getHelperExpressionForImport(node, name); if (expr === name) { return undefined; @@ -605,7 +605,7 @@ namespace ts { } } - function createImportCallExpressionUMD(arg: Expression | undefined, containsLexicalThis: boolean): Expression { + function createImportCallExpressionUMD(arg: Expression, containsLexicalThis: boolean): Expression { // (function (factory) { // ... (regular UMD) // } @@ -762,7 +762,7 @@ namespace ts { * @param node The node to visit. */ function visitImportDeclaration(node: ImportDeclaration): VisitResult { - let statements: Statement[]; + let statements: Statement[] | undefined; const namespaceDeclaration = getNamespaceDeclarationNode(node); if (moduleKind !== ModuleKind.AMD) { if (!node.importClause) { @@ -876,7 +876,7 @@ namespace ts { function visitImportEqualsDeclaration(node: ImportEqualsDeclaration): VisitResult { Debug.assert(isExternalModuleImportEqualsDeclaration(node), "import= for internal module references should be handled in an earlier transformer."); - let statements: Statement[]; + let statements: Statement[] | undefined; if (moduleKind !== ModuleKind.AMD) { if (hasModifier(node, ModifierFlags.Export)) { statements = append(statements, @@ -1009,7 +1009,7 @@ namespace ts { return undefined; } - let statements: Statement[]; + let statements: Statement[] | undefined; const original = node.original; if (original && hasAssociatedEndOfDeclarationMarker(original)) { // Defer exports until we encounter an EndOfDeclarationMarker node @@ -1029,7 +1029,7 @@ namespace ts { * @param node The node to visit. */ function visitFunctionDeclaration(node: FunctionDeclaration): VisitResult { - let statements: Statement[]; + let statements: Statement[] | undefined; if (hasModifier(node, ModifierFlags.Export)) { statements = append(statements, setOriginalNode( @@ -1072,7 +1072,7 @@ namespace ts { * @param node The node to visit. */ function visitClassDeclaration(node: ClassDeclaration): VisitResult { - let statements: Statement[]; + let statements: Statement[] | undefined; if (hasModifier(node, ModifierFlags.Export)) { statements = append(statements, setOriginalNode( @@ -1113,12 +1113,12 @@ namespace ts { * @param node The node to visit. */ function visitVariableStatement(node: VariableStatement): VisitResult { - let statements: Statement[]; - let variables: VariableDeclaration[]; - let expressions: Expression[]; + let statements: Statement[] | undefined; + let variables: VariableDeclaration[] | undefined; + let expressions: Expression[] | undefined; if (hasModifier(node, ModifierFlags.Export)) { - let modifiers: NodeArray; + let modifiers: NodeArray | undefined; // If we're exporting these variables, then these just become assignments to 'exports.x'. // We only want to emit assignments for variables with initializers. @@ -1219,7 +1219,7 @@ namespace ts { // // To balance the declaration, add the exports of the elided variable // statement. - if (hasAssociatedEndOfDeclarationMarker(node) && node.original.kind === SyntaxKind.VariableStatement) { + if (hasAssociatedEndOfDeclarationMarker(node) && node.original!.kind === SyntaxKind.VariableStatement) { const id = getOriginalNodeId(node); deferredExports[id] = appendExportsOfVariableStatement(deferredExports[id], node.original); } @@ -1532,9 +1532,9 @@ namespace ts { previousOnEmitNode(hint, node, emitCallback); - currentSourceFile = undefined; - currentModuleInfo = undefined; - noSubstitution = undefined; + currentSourceFile = undefined!; + currentModuleInfo = undefined!; + noSubstitution = undefined!; } else { previousOnEmitNode(hint, node, emitCallback); diff --git a/src/compiler/transformers/module/system.ts b/src/compiler/transformers/module/system.ts index 0e6f5afad18b0..4ff4d5b4e7fc0 100644 --- a/src/compiler/transformers/module/system.ts +++ b/src/compiler/transformers/module/system.ts @@ -27,7 +27,7 @@ namespace ts { context.enableEmitNotification(SyntaxKind.SourceFile); // Restore state when substituting nodes in a file. const moduleInfoMap: ExternalModuleInfo[] = []; // The ExternalModuleInfo for each file. - const deferredExports: Statement[][] = []; // Exports to defer until an EndOfDeclarationMarker is found. + const deferredExports: (Statement[] | undefined)[] = []; // Exports to defer until an EndOfDeclarationMarker is found. const exportFunctionsMap: Identifier[] = []; // The export function associated with a source file. const noSubstitutionMap: boolean[][] = []; // Set of nodes for which substitution rules should be ignored for each file. @@ -35,9 +35,9 @@ namespace ts { let moduleInfo: ExternalModuleInfo; // ExternalModuleInfo for the current file. let exportFunction: Identifier; // The export function for the current file. let contextObject: Identifier; // The context object for the current file. - let hoistedStatements: Statement[]; + let hoistedStatements: Statement[] | undefined; let enclosingBlockScopedContainer: Node; - let noSubstitution: boolean[]; // Set of nodes for which substitution rules should be ignored. + let noSubstitution: boolean[] | undefined; // Set of nodes for which substitution rules should be ignored. return chainBundle(transformSourceFile); @@ -126,12 +126,12 @@ namespace ts { noSubstitution = undefined; } - currentSourceFile = undefined; - moduleInfo = undefined; - exportFunction = undefined; - contextObject = undefined; - hoistedStatements = undefined; - enclosingBlockScopedContainer = undefined; + currentSourceFile = undefined!; + moduleInfo = undefined!; + exportFunction = undefined!; + contextObject = undefined!; + hoistedStatements = undefined!; + enclosingBlockScopedContainer = undefined!; return aggregateTransformFlags(updated); } @@ -259,7 +259,7 @@ namespace ts { // - Temporary variables will appear at the top rather than at the bottom of the file prependRange(statements, endLexicalEnvironment()); - const exportStarFunction = addExportStarIfNeeded(statements); + const exportStarFunction = addExportStarIfNeeded(statements)!; // TODO: GH#18217 const moduleObject = createObjectLiteral([ createPropertyAssignment("setters", createSettersArray(exportStarFunction, dependencyGroups) @@ -464,7 +464,7 @@ namespace ts { const parameterName = localName ? getGeneratedNameForNode(localName) : createUniqueName(""); const statements: Statement[] = []; for (const entry of group.externalImports) { - const importVariableName = getLocalNameForExternalImport(entry, currentSourceFile); + const importVariableName = getLocalNameForExternalImport(entry, currentSourceFile)!; // TODO: GH#18217 switch (entry.kind) { case SyntaxKind.ImportDeclaration: if (!entry.importClause) { @@ -590,9 +590,9 @@ namespace ts { * @param node The node to visit. */ function visitImportDeclaration(node: ImportDeclaration): VisitResult { - let statements: Statement[]; + let statements: Statement[] | undefined; if (node.importClause) { - hoistVariableDeclaration(getLocalNameForExternalImport(node, currentSourceFile)); + hoistVariableDeclaration(getLocalNameForExternalImport(node, currentSourceFile)!); // TODO: GH#18217 } if (hasAssociatedEndOfDeclarationMarker(node)) { @@ -615,13 +615,13 @@ namespace ts { function visitImportEqualsDeclaration(node: ImportEqualsDeclaration): VisitResult { Debug.assert(isExternalModuleImportEqualsDeclaration(node), "import= for internal module references should be handled in an earlier transformer."); - let statements: Statement[]; - hoistVariableDeclaration(getLocalNameForExternalImport(node, currentSourceFile)); + let statements: Statement[] | undefined; + hoistVariableDeclaration(getLocalNameForExternalImport(node, currentSourceFile)!); // TODO: GH#18217 if (hasAssociatedEndOfDeclarationMarker(node)) { // Defer exports until we encounter an EndOfDeclarationMarker node const id = getOriginalNodeId(node); - deferredExports[id] = appendExportsOfImportEqualsDeclaration(deferredExports[id], node); + deferredExports[id] = appendExportsOfImportEqualsDeclaration(deferredExports[id]!, node); } else { statements = appendExportsOfImportEqualsDeclaration(statements, node); @@ -694,7 +694,7 @@ namespace ts { * @param node The node to visit. */ function visitClassDeclaration(node: ClassDeclaration): VisitResult { - let statements: Statement[]; + let statements: Statement[] | undefined; // Hoist the name of the class declaration to the outer module body function. const name = getLocalName(node); @@ -745,7 +745,7 @@ namespace ts { return visitNode(node, destructuringAndImportCallVisitor, isStatement); } - let expressions: Expression[]; + let expressions: Expression[] | undefined; const isExportedDeclaration = hasModifier(node, ModifierFlags.Export); const isMarkedDeclaration = hasAssociatedEndOfDeclarationMarker(node); for (const variable of node.declarationList.declarations) { @@ -757,7 +757,7 @@ namespace ts { } } - let statements: Statement[]; + let statements: Statement[] | undefined; if (expressions) { statements = append(statements, setTextRange(createStatement(inlineExpressions(expressions)), node)); } @@ -854,7 +854,7 @@ namespace ts { * @param location The source map location for the assignment. * @param isExportedDeclaration A value indicating whether the variable is exported. */ - function createVariableAssignment(name: Identifier, value: Expression, location: TextRange, isExportedDeclaration: boolean) { + function createVariableAssignment(name: Identifier, value: Expression, location: TextRange | undefined, isExportedDeclaration: boolean) { hoistVariableDeclaration(getSynthesizedClone(name)); return isExportedDeclaration ? createExportExpression(name, preventSubstitution(setTextRange(createAssignment(name, value), location))) @@ -875,9 +875,9 @@ namespace ts { // // To balance the declaration, we defer the exports of the elided variable // statement until we visit this declaration's `EndOfDeclarationMarker`. - if (hasAssociatedEndOfDeclarationMarker(node) && node.original.kind === SyntaxKind.VariableStatement) { + if (hasAssociatedEndOfDeclarationMarker(node) && node.original!.kind === SyntaxKind.VariableStatement) { const id = getOriginalNodeId(node); - const isExportedDeclaration = hasModifier(node.original, ModifierFlags.Export); + const isExportedDeclaration = hasModifier(node.original!, ModifierFlags.Export); deferredExports[id] = appendExportsOfVariableStatement(deferredExports[id], node.original, isExportedDeclaration); } @@ -928,7 +928,7 @@ namespace ts { * appended. * @param decl The declaration whose exports are to be recorded. */ - function appendExportsOfImportDeclaration(statements: Statement[], decl: ImportDeclaration) { + function appendExportsOfImportDeclaration(statements: Statement[] | undefined, decl: ImportDeclaration) { if (moduleInfo.exportEquals) { return statements; } @@ -970,7 +970,7 @@ namespace ts { * appended. * @param decl The declaration whose exports are to be recorded. */ - function appendExportsOfImportEqualsDeclaration(statements: Statement[], decl: ImportEqualsDeclaration): Statement[] | undefined { + function appendExportsOfImportEqualsDeclaration(statements: Statement[] | undefined, decl: ImportEqualsDeclaration): Statement[] | undefined { if (moduleInfo.exportEquals) { return statements; } @@ -1026,7 +1026,7 @@ namespace ts { } } else if (!isGeneratedIdentifier(decl.name)) { - let excludeName: string; + let excludeName: string | undefined; if (exportSelf) { statements = appendExportStatement(statements, decl.name, getLocalName(decl)); excludeName = idText(decl.name); @@ -1052,9 +1052,9 @@ namespace ts { return statements; } - let excludeName: string; + let excludeName: string | undefined; if (hasModifier(decl, ModifierFlags.Export)) { - const exportName = hasModifier(decl, ModifierFlags.Default) ? createLiteral("default") : decl.name; + const exportName = hasModifier(decl, ModifierFlags.Default) ? createLiteral("default") : decl.name!; statements = appendExportStatement(statements, exportName, getLocalName(decl)); excludeName = getTextOfIdentifierOrLiteral(exportName); } @@ -1221,7 +1221,7 @@ namespace ts { node = updateFor( node, - visitForInitializer(node.initializer), + node.initializer && visitForInitializer(node.initializer), visitNode(node.condition, destructuringAndImportCallVisitor, isExpression), visitNode(node.incrementor, destructuringAndImportCallVisitor, isExpression), visitNode(node.statement, nestedElementVisitor, isStatement) @@ -1289,12 +1289,8 @@ namespace ts { * @param node The node to visit. */ function visitForInitializer(node: ForInitializer): ForInitializer { - if (!node) { - return node; - } - if (shouldHoistForInitializer(node)) { - let expressions: Expression[]; + let expressions: Expression[] | undefined; for (const variable of node.declarations) { expressions = append(expressions, transformInitializedVariable(variable, /*isExportedDeclaration*/ false)); if (!variable.initializer) { @@ -1598,9 +1594,9 @@ namespace ts { previousOnEmitNode(hint, node, emitCallback); - currentSourceFile = undefined; - moduleInfo = undefined; - exportFunction = undefined; + currentSourceFile = undefined!; + moduleInfo = undefined!; + exportFunction = undefined!; noSubstitution = undefined; } else { @@ -1841,7 +1837,7 @@ namespace ts { * @param name The name. */ function getExports(name: Identifier) { - let exportedNames: Identifier[]; + let exportedNames: Identifier[] | undefined; if (!isGeneratedIdentifier(name)) { const valueDeclaration = resolver.getReferencedImportDeclaration(name) || resolver.getReferencedValueDeclaration(name); diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 67c9ddfc788f9..903474e9f510b 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -62,7 +62,7 @@ namespace ts { let currentNamespace: ModuleDeclaration; let currentNamespaceContainerName: Identifier; let currentScope: SourceFile | Block | ModuleBlock | CaseBlock; - let currentScopeFirstDeclarationsOfName: UnderscoreEscapedMap; + let currentScopeFirstDeclarationsOfName: UnderscoreEscapedMap | undefined; /** * Keeps track of whether expression substitution has been enabled for specific edge cases. @@ -121,7 +121,7 @@ namespace ts { const visited = saveStateAndInvoke(node, visitSourceFile); addEmitHelpers(visited, context.readEmitHelpers()); - currentSourceFile = undefined; + currentSourceFile = undefined!; return visited; } @@ -625,7 +625,7 @@ namespace ts { // Write any pending expressions from elided or moved computed property names if (some(pendingExpressions)) { - statements.push(createStatement(inlineExpressions(pendingExpressions))); + statements.push(createStatement(inlineExpressions(pendingExpressions!))); } pendingExpressions = savedPendingExpressions; @@ -723,7 +723,7 @@ namespace ts { * @param name The name of the class. * @param facts Precomputed facts about the class. */ - function createClassDeclarationHeadWithoutDecorators(node: ClassDeclaration, name: Identifier, facts: ClassFacts) { + function createClassDeclarationHeadWithoutDecorators(node: ClassDeclaration, name: Identifier | undefined, facts: ClassFacts) { // ${modifiers} class ${name} ${heritageClauses} { // ${members} // } @@ -759,7 +759,7 @@ namespace ts { * Transforms a decorated class declaration and appends the resulting statements. If * the class requires an alias to avoid issues with double-binding, the alias is returned. */ - function createClassDeclarationHeadWithDecorators(node: ClassDeclaration, name: Identifier, facts: ClassFacts) { + function createClassDeclarationHeadWithDecorators(node: ClassDeclaration, name: Identifier | undefined, facts: ClassFacts) { // When we emit an ES6 class that has a class decorator, we must tailor the // emit to certain specific cases. // @@ -998,7 +998,7 @@ namespace ts { * * @param constructor The constructor declaration. */ - function transformConstructorParameters(constructor: ConstructorDeclaration) { + function transformConstructorParameters(constructor: ConstructorDeclaration | undefined) { // The ES2015 spec specifies in 14.5.14. Runtime Semantics: ClassDefinitionEvaluation: // If constructor is empty, then // If ClassHeritag_eopt is present and protoParent is not null, then @@ -1026,7 +1026,7 @@ namespace ts { * @param constructor The current class constructor. * @param isDerivedClass A value indicating whether the class has an extends clause that does not extend 'null'. */ - function transformConstructorBody(node: ClassExpression | ClassDeclaration, constructor: ConstructorDeclaration, isDerivedClass: boolean) { + function transformConstructorBody(node: ClassExpression | ClassDeclaration, constructor: ConstructorDeclaration | undefined, isDerivedClass: boolean) { let statements: Statement[] = []; let indexOfFirstStatement = 0; @@ -1081,7 +1081,7 @@ namespace ts { if (constructor) { // The class already had a constructor, so we should add the existing statements, skipping the initial super call. - addRange(statements, visitNodes(constructor.body.statements, visitor, isStatement, indexOfFirstStatement)); + addRange(statements, visitNodes(constructor.body!.statements, visitor, isStatement, indexOfFirstStatement)); } // End the lexical environment. @@ -1090,7 +1090,7 @@ namespace ts { createBlock( setTextRange( createNodeArray(statements), - /*location*/ constructor ? constructor.body.statements : node.members + /*location*/ constructor ? constructor.body!.statements : node.members ), /*multiLine*/ true ), @@ -1266,7 +1266,7 @@ namespace ts { const propertyName = isComputedPropertyName(property.name) && !isSimpleInlineableExpression(property.name.expression) ? updateComputedPropertyName(property.name, getGeneratedNameForNode(property.name)) : property.name; - const initializer = visitNode(property.initializer, visitor, isExpression); + const initializer = visitNode(property.initializer!, visitor, isExpression); const memberAccess = createMemberAccessForPropertyName(receiver, propertyName, /*location*/ propertyName); return createAssignment(memberAccess, initializer); @@ -1319,8 +1319,8 @@ namespace ts { * A structure describing the decorators for a class element. */ interface AllDecorators { - decorators: ReadonlyArray; - parameters?: ReadonlyArray>; + decorators: ReadonlyArray | undefined; + parameters?: ReadonlyArray | undefined>; } /** @@ -1329,8 +1329,8 @@ namespace ts { * * @param node The function-like node. */ - function getDecoratorsOfParameters(node: FunctionLikeDeclaration) { - let decorators: ReadonlyArray[]; + function getDecoratorsOfParameters(node: FunctionLikeDeclaration | undefined) { + let decorators: (ReadonlyArray | undefined)[] | undefined; if (node) { const parameters = node.parameters; for (let i = 0; i < parameters.length; i++) { @@ -1354,7 +1354,7 @@ namespace ts { * * @param node The class node. */ - function getAllDecoratorsOfConstructor(node: ClassExpression | ClassDeclaration): AllDecorators { + function getAllDecoratorsOfConstructor(node: ClassExpression | ClassDeclaration): AllDecorators | undefined { const decorators = node.decorators; const parameters = getDecoratorsOfParameters(getFirstConstructorWithBody(node)); if (!decorators && !parameters) { @@ -1373,7 +1373,7 @@ namespace ts { * @param node The class node that contains the member. * @param member The class member. */ - function getAllDecoratorsOfClassElement(node: ClassExpression | ClassDeclaration, member: ClassElement): AllDecorators { + function getAllDecoratorsOfClassElement(node: ClassExpression | ClassDeclaration, member: ClassElement): AllDecorators | undefined { switch (member.kind) { case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: @@ -1396,7 +1396,7 @@ namespace ts { * @param node The class node that contains the accessor. * @param accessor The class accessor member. */ - function getAllDecoratorsOfAccessors(node: ClassExpression | ClassDeclaration, accessor: AccessorDeclaration): AllDecorators { + function getAllDecoratorsOfAccessors(node: ClassExpression | ClassDeclaration, accessor: AccessorDeclaration): AllDecorators | undefined { if (!accessor.body) { return undefined; } @@ -1421,7 +1421,7 @@ namespace ts { * * @param method The class method member. */ - function getAllDecoratorsOfMethod(method: MethodDeclaration): AllDecorators { + function getAllDecoratorsOfMethod(method: MethodDeclaration): AllDecorators | undefined { if (!method.body) { return undefined; } @@ -1440,7 +1440,7 @@ namespace ts { * * @param property The class property member. */ - function getAllDecoratorsOfProperty(property: PropertyDeclaration): AllDecorators { + function getAllDecoratorsOfProperty(property: PropertyDeclaration): AllDecorators | undefined { const decorators = property.decorators; if (!decorators) { return undefined; @@ -1456,7 +1456,7 @@ namespace ts { * @param node The declaration node. * @param allDecorators An object containing all of the decorators for the declaration. */ - function transformAllDecoratorsOfDeclaration(node: Declaration, container: ClassLikeDeclaration, allDecorators: AllDecorators) { + function transformAllDecoratorsOfDeclaration(node: Declaration, container: ClassLikeDeclaration, allDecorators: AllDecorators | undefined) { if (!allDecorators) { return undefined; } @@ -1490,7 +1490,7 @@ namespace ts { */ function generateClassElementDecorationExpressions(node: ClassExpression | ClassDeclaration, isStatic: boolean) { const members = getDecoratedClassElements(node, isStatic); - let expressions: Expression[]; + let expressions: Expression[] | undefined; for (const member of members) { const expression = generateClassElementDecorationExpression(node, member); if (expression) { @@ -1624,7 +1624,7 @@ namespace ts { * @param parameterOffset The offset of the parameter. */ function transformDecoratorsOfParameter(decorators: Decorator[], parameterOffset: number) { - let expressions: Expression[]; + let expressions: Expression[] | undefined; if (decorators) { expressions = []; for (const decorator of decorators) { @@ -1672,7 +1672,7 @@ namespace ts { function addNewTypeMetadata(node: Declaration, container: ClassLikeDeclaration, decoratorExpressions: Expression[]) { if (compilerOptions.emitDecoratorMetadata) { - let properties: ObjectLiteralElementLike[]; + let properties: ObjectLiteralElementLike[] | undefined; if (shouldAddTypeMetadata(node)) { (properties || (properties = [])).push(createPropertyAssignment("type", createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, createToken(SyntaxKind.EqualsGreaterThanToken), serializeTypeOfNode(node)))); } @@ -1837,7 +1837,7 @@ namespace ts { * * @param node The type node to serialize. */ - function serializeTypeNode(node: TypeNode): SerializedTypeNode { + function serializeTypeNode(node: TypeNode | undefined): SerializedTypeNode { if (node === undefined) { return createIdentifier("Object"); } @@ -1920,7 +1920,7 @@ namespace ts { function serializeUnionOrIntersectionType(node: UnionOrIntersectionTypeNode): SerializedTypeNode { // Note when updating logic here also update getEntityNameForDecoratorMetadata // so that aliases can be marked as referenced - let serializedUnion: SerializedTypeNode; + let serializedUnion: SerializedTypeNode | undefined; for (let typeNode of node.types) { while (typeNode.kind === SyntaxKind.ParenthesizedType) { typeNode = (typeNode as ParenthesizedTypeNode).type; // Skip parens if need be @@ -2102,7 +2102,7 @@ namespace ts { * @param member The member whose name should be converted into an expression. */ function getExpressionForPropertyName(member: ClassElement | EnumMember, generateNameForComputedPropertyName: boolean): Expression { - const name = member.name; + const name = member.name!; if (isComputedPropertyName(name)) { return generateNameForComputedPropertyName && !isSimpleInlineableExpression(name.expression) ? getGeneratedNameForNode(name) @@ -2122,7 +2122,7 @@ namespace ts { * @param shouldHoist Does the expression need to be reused? (ie, for an initializer or a decorator) * @param omitSimple Should expressions with no observable side-effects be elided? (ie, the expression is not hoisted for a decorator or initializer and is a literal) */ - function getPropertyNameExpressionIfNeeded(name: PropertyName, shouldHoist: boolean, omitSimple: boolean): Expression { + function getPropertyNameExpressionIfNeeded(name: PropertyName, shouldHoist: boolean, omitSimple: boolean): Expression | undefined { if (isComputedPropertyName(name)) { const expression = visitNode(name.expression, visitor, isExpression); const innerExpression = skipPartiallyEmittedExpressions(expression); @@ -2144,7 +2144,7 @@ namespace ts { * @param member The member whose name should be visited. */ function visitPropertyNameOfClassElement(member: ClassElement): PropertyName { - const name = member.name; + const name = member.name!; let expr = getPropertyNameExpressionIfNeeded(name, some(member.decorators), /*omitSimple*/ false); if (expr) { // expr only exists if `name` is a computed property name // Inline any pending expressions from previous elided or relocated computed property name expressions in order to preserve execution order @@ -2168,7 +2168,7 @@ namespace ts { * * @param node The HeritageClause to transform. */ - function visitHeritageClause(node: HeritageClause): HeritageClause { + function visitHeritageClause(node: HeritageClause): HeritageClause | undefined { if (node.token === SyntaxKind.ExtendsKeyword) { const types = visitNodes(node.types, visitor, isExpressionWithTypeArguments, 0, 1); return setTextRange( @@ -2455,7 +2455,7 @@ namespace ts { * This function will be called when one of the following conditions are met: * - The node is exported from a TypeScript namespace. */ - function visitVariableStatement(node: VariableStatement): Statement { + function visitVariableStatement(node: VariableStatement): Statement | undefined { if (isExportOfNamespace(node)) { const variables = getInitializedVariables(node.declarationList); if (variables.length === 0) { @@ -2493,7 +2493,7 @@ namespace ts { return setTextRange( createAssignment( getNamespaceMemberNameWithSourceMapsAndWithoutComments(name), - visitNode(node.initializer, visitor, isExpression) + visitNode(node.initializer!, visitor, isExpression) ), /*location*/ node ); @@ -2766,7 +2766,7 @@ namespace ts { * @param node The module declaration node. */ function shouldEmitModuleDeclaration(node: ModuleDeclaration) { - return isInstantiatedModule(node, compilerOptions.preserveConstEnums || compilerOptions.isolatedModules); + return isInstantiatedModule(node, !!compilerOptions.preserveConstEnums || !!compilerOptions.isolatedModules); } /** @@ -2984,8 +2984,8 @@ namespace ts { startLexicalEnvironment(); let statementsLocation: TextRange; - let blockLocation: TextRange; - const body = node.body; + let blockLocation: TextRange | undefined; + const body = node.body!; if (body.kind === SyntaxKind.ModuleBlock) { saveStateAndInvoke(body, body => addRange(statements, visitNodes((body).statements, namespaceElementVisitor, isStatement))); statementsLocation = body.statements; @@ -3002,7 +3002,7 @@ namespace ts { } } - const moduleBlock = getInnerMostModuleDeclarationFromDottedModule(node).body; + const moduleBlock = getInnerMostModuleDeclarationFromDottedModule(node)!.body; statementsLocation = moveRangePos(moduleBlock.statements, -1); } @@ -3046,8 +3046,8 @@ namespace ts { return block; } - function getInnerMostModuleDeclarationFromDottedModule(moduleDeclaration: ModuleDeclaration): ModuleDeclaration { - if (moduleDeclaration.body.kind === SyntaxKind.ModuleDeclaration) { + function getInnerMostModuleDeclarationFromDottedModule(moduleDeclaration: ModuleDeclaration): ModuleDeclaration | undefined { + if (moduleDeclaration.body!.kind === SyntaxKind.ModuleDeclaration) { const recursiveInnerModule = getInnerMostModuleDeclarationFromDottedModule(moduleDeclaration.body); return recursiveInnerModule || moduleDeclaration.body; } @@ -3138,7 +3138,7 @@ namespace ts { function visitExportDeclaration(node: ExportDeclaration): VisitResult { if (!node.exportClause) { // Elide a star export if the module it references does not export a value. - return compilerOptions.isolatedModules || resolver.moduleExportsSomeValue(node.moduleSpecifier) ? node : undefined; + return compilerOptions.isolatedModules || resolver.moduleExportsSomeValue(node.moduleSpecifier!) ? node : undefined; } if (!resolver.isValueAliasDeclaration(node)) { @@ -3494,7 +3494,7 @@ namespace ts { || node; } - function trySubstituteClassAlias(node: Identifier): Expression { + function trySubstituteClassAlias(node: Identifier): Expression | undefined { if (enabledSubstitutions & TypeScriptSubstitutionFlags.ClassAliases) { if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.ConstructorReferenceInClass) { // Due to the emit for class decorators, any reference to the class from inside of the class body @@ -3504,7 +3504,7 @@ namespace ts { // constructor references in static property initializers. const declaration = resolver.getReferencedValueDeclaration(node); if (declaration) { - const classAlias = classAliases[declaration.id]; + const classAlias = classAliases[declaration.id!]; // TODO: GH#18217 if (classAlias) { const clone = getSynthesizedClone(classAlias); setSourceMapRange(clone, node); @@ -3518,7 +3518,7 @@ namespace ts { return undefined; } - function trySubstituteNamespaceExportedName(node: Identifier): Expression { + function trySubstituteNamespaceExportedName(node: Identifier): Expression | undefined { // If this is explicitly a local name, do not substitute. if (enabledSubstitutions & applicableSubstitutions && !isGeneratedIdentifier(node) && !isLocalName(node)) { // If we are nested within a namespace declaration, we may need to qualifiy @@ -3569,7 +3569,7 @@ namespace ts { return node; } - function tryGetConstEnumValue(node: Node): string | number { + function tryGetConstEnumValue(node: Node): string | number | undefined { if (compilerOptions.isolatedModules) { return undefined; } diff --git a/src/compiler/transformers/utilities.ts b/src/compiler/transformers/utilities.ts index f8a6a6a2795d9..09239d7765fd9 100644 --- a/src/compiler/transformers/utilities.ts +++ b/src/compiler/transformers/utilities.ts @@ -10,19 +10,19 @@ namespace ts { externalHelpersImportDeclaration: ImportDeclaration | undefined; // import of external helpers exportSpecifiers: Map; // export specifiers by name exportedBindings: Identifier[][]; // exported names of local declarations - exportedNames: Identifier[]; // all exported names local to module + exportedNames: Identifier[] | undefined; // all exported names local to module exportEquals: ExportAssignment | undefined; // an export= declaration if one was present hasExportStarsToExportValues: boolean; // whether this module contains export* } - function containsDefaultReference(node: NamedImportBindings) { + function containsDefaultReference(node: NamedImportBindings | undefined) { if (!node) return false; if (!isNamedImports(node)) return false; return some(node.elements, isNamedDefaultReference); } - function isNamedDefaultReference(e: ImportSpecifier) { - return e.propertyName && e.propertyName.escapedText === InternalSymbolName.Default; + function isNamedDefaultReference(e: ImportSpecifier): boolean { + return e.propertyName !== undefined && e.propertyName.escapedText === InternalSymbolName.Default; } export function chainBundle(transformSourceFile: (x: SourceFile) => SourceFile): (x: SourceFile | Bundle) => SourceFile | Bundle { @@ -37,7 +37,7 @@ namespace ts { } } - export function getImportNeedsImportStarHelper(node: ImportDeclaration) { + export function getImportNeedsImportStarHelper(node: ImportDeclaration): boolean { if (!!getNamespaceDeclarationNode(node)) { return true; } @@ -56,9 +56,9 @@ namespace ts { return (defaultRefCount > 0 && defaultRefCount !== bindings.elements.length) || (!!(bindings.elements.length - defaultRefCount) && isDefaultImport(node)); } - export function getImportNeedsImportDefaultHelper(node: ImportDeclaration) { + export function getImportNeedsImportDefaultHelper(node: ImportDeclaration): boolean { // Import default is needed if there's a default import or a default ref and no other refs (meaning an import star helper wasn't requested) - return !getImportNeedsImportStarHelper(node) && (isDefaultImport(node) || (node.importClause && isNamedImports(node.importClause.namedBindings) && containsDefaultReference(node.importClause.namedBindings))); + return !getImportNeedsImportStarHelper(node) && (isDefaultImport(node) || (!!node.importClause && isNamedImports(node.importClause.namedBindings!) && containsDefaultReference(node.importClause.namedBindings))); // TODO: GH#18217 } export function collectExternalModuleInfo(sourceFile: SourceFile, resolver: EmitResolver, compilerOptions: CompilerOptions): ExternalModuleInfo { @@ -66,9 +66,9 @@ namespace ts { const exportSpecifiers = createMultiMap(); const exportedBindings: Identifier[][] = []; const uniqueExports = createMap(); - let exportedNames: Identifier[]; + let exportedNames: Identifier[] | undefined; let hasExportDefault = false; - let exportEquals: ExportAssignment; + let exportEquals: ExportAssignment | undefined; let hasExportStarsToExportValues = false; let hasImportStarOrImportDefault = false; @@ -105,7 +105,7 @@ namespace ts { } else { // export { x, y } - for (const specifier of (node).exportClause.elements) { + for (const specifier of (node).exportClause!.elements) { if (!uniqueExports.get(idText(specifier.name))) { const name = specifier.propertyName || specifier.name; exportSpecifiers.add(idText(name), specifier); @@ -150,7 +150,7 @@ namespace ts { } else { // export function x() { } - const name = (node).name; + const name = (node).name!; if (!uniqueExports.get(idText(name))) { multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), name); uniqueExports.set(idText(name), true); @@ -198,7 +198,7 @@ namespace ts { return { externalImports, exportSpecifiers, exportEquals, hasExportStarsToExportValues, exportedBindings, exportedNames, externalHelpersImportDeclaration }; } - function collectExportedVariableInfo(decl: VariableDeclaration | BindingElement, uniqueExports: Map, exportedNames: Identifier[]) { + function collectExportedVariableInfo(decl: VariableDeclaration | BindingElement, uniqueExports: Map, exportedNames: Identifier[] | undefined) { if (isBindingPattern(decl.name)) { for (const element of decl.name.elements) { if (!isOmittedExpression(element)) { diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 7617fc62cb6f2..e3e0ea08f5300 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -50,7 +50,7 @@ namespace ts { const commandLine = parseCommandLine(args); // Configuration file name (if any) - let configFileName: string; + let configFileName: string | undefined; if (commandLine.options.locale) { validateLocaleAndSetLanguage(commandLine.options.locale, sys, commandLine.errors); } @@ -74,7 +74,7 @@ namespace ts { if (commandLine.options.help || commandLine.options.all) { printVersion(); - printHelp(commandLine.options.all); + printHelp(!!commandLine.options.all); return sys.exit(ExitStatus.Success); } @@ -107,13 +107,13 @@ namespace ts { if (commandLine.fileNames.length === 0 && !configFileName) { printVersion(); - printHelp(commandLine.options.all); + printHelp(!!commandLine.options.all); return sys.exit(ExitStatus.Success); } const commandLineOptions = commandLine.options; if (configFileName) { - const configParseResult = parseConfigFileWithSystem(configFileName, commandLineOptions, sys, reportDiagnostic); + const configParseResult = parseConfigFileWithSystem(configFileName, commandLineOptions, sys, reportDiagnostic)!; // TODO: GH#18217 updateReportDiagnostic(configParseResult.options); if (isWatchSet(configParseResult.options)) { reportWatchModeWithoutSysSupport(); @@ -168,7 +168,7 @@ namespace ts { } return compileUsingBuilder(rootNames, options, host, oldProgram, configFileParsingDiagnostics); }; - const emitFilesUsingBuilder = watchCompilerHost.afterProgramCreate; + const emitFilesUsingBuilder = watchCompilerHost.afterProgramCreate!; // TODO: GH#18217 watchCompilerHost.afterProgramCreate = builderProgram => { emitFilesUsingBuilder(builderProgram); reportStatistics(builderProgram.getProgram()); @@ -180,7 +180,7 @@ namespace ts { } function createWatchOfConfigFile(configParseResult: ParsedCommandLine, optionsToExtend: CompilerOptions) { - const watchCompilerHost = createWatchCompilerHostOfConfigFile(configParseResult.options.configFilePath, optionsToExtend, sys, /*createProgram*/ undefined, reportDiagnostic, createWatchStatusReporter(configParseResult.options)); + const watchCompilerHost = createWatchCompilerHostOfConfigFile(configParseResult.options.configFilePath!, optionsToExtend, sys, /*createProgram*/ undefined, reportDiagnostic, createWatchStatusReporter(configParseResult.options)); // TODO: GH#18217 updateWatchCompilationHost(watchCompilerHost); watchCompilerHost.configFileParsingResult = configParseResult; createWatchProgram(watchCompilerHost); @@ -302,7 +302,7 @@ namespace ts { // Sort our options by their names, (e.g. "--noImplicitAny" comes before "--watch") const optsList = showAllOptions ? sort(optionDeclarations, (a, b) => compareStringsCaseInsensitive(a.name, b.name)) : - filter(optionDeclarations.slice(), v => v.showInSimplifiedHelpView); + filter(optionDeclarations.slice(), v => !!v.showInSimplifiedHelpView); // We want our descriptions to align at the same column in our output, // so we keep track of the longest option usage string. diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 44c5ddb5d5034..a3cdb32df0702 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -574,13 +574,13 @@ namespace ts { kind: SyntaxKind; flags: NodeFlags; /* @internal */ modifierFlagsCache?: ModifierFlags; - /* @internal */ transformFlags?: TransformFlags; + /* @internal */ transformFlags: TransformFlags; // Flags for transforms, possibly undefined decorators?: NodeArray; // Array of decorators (in document order) modifiers?: ModifiersArray; // Array of modifiers /* @internal */ id?: number; // Unique id (used to look up NodeLinks) - parent?: Node; // Parent node (initialized by binding) + parent: Node; // Parent node (initialized by binding) /* @internal */ original?: Node; // The original node if this is an updated node. - /* @internal */ symbol?: Symbol; // Symbol declared by node (initialized by binding) + /* @internal */ symbol: Symbol; // Symbol declared by node (initialized by binding) /* @internal */ locals?: SymbolTable; // Locals associated with node (initialized by binding) /* @internal */ nextContainer?: Node; // Next container in declaration order (initialized by binding) /* @internal */ localSymbol?: Symbol; // Local symbol declared by node (initialized by binding only for exported nodes) @@ -667,7 +667,7 @@ namespace ts { export interface NodeArray extends ReadonlyArray, TextRange { hasTrailingComma?: boolean; - /* @internal */ transformFlags?: TransformFlags; + /* @internal */ transformFlags: TransformFlags; // Flags for transforms, possibly undefined } export interface Token extends Node { @@ -794,13 +794,13 @@ namespace ts { export interface Decorator extends Node { kind: SyntaxKind.Decorator; - parent?: NamedDeclaration; + parent: NamedDeclaration; expression: LeftHandSideExpression; } export interface TypeParameterDeclaration extends NamedDeclaration { kind: SyntaxKind.TypeParameter; - parent?: DeclarationWithTypeParameters | InferTypeNode; + parent: DeclarationWithTypeParameters | InferTypeNode; name: Identifier; constraint?: TypeNode; default?: TypeNode; @@ -814,7 +814,7 @@ namespace ts { name?: PropertyName; typeParameters?: NodeArray; parameters: NodeArray; - type: TypeNode | undefined; + type?: TypeNode; /* @internal */ typeArguments?: NodeArray; // Used for quick info, replaces typeParameters for instantiated signatures } @@ -845,7 +845,7 @@ namespace ts { export interface VariableDeclaration extends NamedDeclaration { kind: SyntaxKind.VariableDeclaration; - parent?: VariableDeclarationList | CatchClause; + parent: VariableDeclarationList | CatchClause; name: BindingName; // Declared variable name exclamationToken?: ExclamationToken; // Optional definite assignment assertion type?: TypeNode; // Optional type annotation @@ -854,13 +854,13 @@ namespace ts { export interface VariableDeclarationList extends Node { kind: SyntaxKind.VariableDeclarationList; - parent?: VariableStatement | ForStatement | ForOfStatement | ForInStatement; + parent: VariableStatement | ForStatement | ForOfStatement | ForInStatement; declarations: NodeArray; } export interface ParameterDeclaration extends NamedDeclaration, JSDocContainer { kind: SyntaxKind.Parameter; - parent?: SignatureDeclaration; + parent: SignatureDeclaration; dotDotDotToken?: DotDotDotToken; // Present on rest parameter name: BindingName; // Declared parameter name. questionToken?: QuestionToken; // Present on optional parameter @@ -870,7 +870,7 @@ namespace ts { export interface BindingElement extends NamedDeclaration { kind: SyntaxKind.BindingElement; - parent?: BindingPattern; + parent: BindingPattern; propertyName?: PropertyName; // Binding property name (in object binding pattern) dotDotDotToken?: DotDotDotToken; // Present on rest element (in object binding pattern) name: BindingName; // Declared binding element name @@ -955,13 +955,13 @@ namespace ts { export interface ObjectBindingPattern extends Node { kind: SyntaxKind.ObjectBindingPattern; - parent?: VariableDeclaration | ParameterDeclaration | BindingElement; + parent: VariableDeclaration | ParameterDeclaration | BindingElement; elements: NodeArray; } export interface ArrayBindingPattern extends Node { kind: SyntaxKind.ArrayBindingPattern; - parent?: VariableDeclaration | ParameterDeclaration | BindingElement; + parent: VariableDeclaration | ParameterDeclaration | BindingElement; elements: NodeArray; } @@ -1004,7 +1004,7 @@ namespace ts { export interface MethodSignature extends SignatureDeclarationBase, TypeElement { kind: SyntaxKind.MethodSignature; - parent?: ObjectTypeDeclaration; + parent: ObjectTypeDeclaration; name: PropertyName; } @@ -1019,14 +1019,14 @@ namespace ts { // of the method, or use helpers like isObjectLiteralMethodDeclaration export interface MethodDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer { kind: SyntaxKind.MethodDeclaration; - parent?: ClassLikeDeclaration | ObjectLiteralExpression; + parent: ClassLikeDeclaration | ObjectLiteralExpression; name: PropertyName; body?: FunctionBody; } export interface ConstructorDeclaration extends FunctionLikeDeclarationBase, ClassElement, JSDocContainer { kind: SyntaxKind.Constructor; - parent?: ClassLikeDeclaration; + parent: ClassLikeDeclaration; body?: FunctionBody; /* @internal */ returnFlowNode?: FlowNode; } @@ -1034,14 +1034,14 @@ namespace ts { /** For when we encounter a semicolon in a class declaration. ES6 allows these as class elements. */ export interface SemicolonClassElement extends ClassElement { kind: SyntaxKind.SemicolonClassElement; - parent?: ClassLikeDeclaration; + parent: ClassLikeDeclaration; } // See the comment on MethodDeclaration for the intuition behind GetAccessorDeclaration being a // ClassElement and an ObjectLiteralElement. export interface GetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer { kind: SyntaxKind.GetAccessor; - parent?: ClassLikeDeclaration | ObjectLiteralExpression; + parent: ClassLikeDeclaration | ObjectLiteralExpression; name: PropertyName; body?: FunctionBody; } @@ -1050,7 +1050,7 @@ namespace ts { // ClassElement and an ObjectLiteralElement. export interface SetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer { kind: SyntaxKind.SetAccessor; - parent?: ClassLikeDeclaration | ObjectLiteralExpression; + parent: ClassLikeDeclaration | ObjectLiteralExpression; name: PropertyName; body?: FunctionBody; } @@ -1059,7 +1059,7 @@ namespace ts { export interface IndexSignatureDeclaration extends SignatureDeclarationBase, ClassElement, TypeElement { kind: SyntaxKind.IndexSignature; - parent?: ObjectTypeDeclaration; + parent: ObjectTypeDeclaration; } export interface TypeNode extends Node { @@ -1117,7 +1117,7 @@ namespace ts { export interface TypePredicateNode extends TypeNode { kind: SyntaxKind.TypePredicate; - parent?: SignatureDeclaration; + parent: SignatureDeclaration; parameterName: Identifier | ThisTypeNode; type: TypeNode; } @@ -1604,22 +1604,22 @@ namespace ts { export interface NumericLiteral extends LiteralExpression { kind: SyntaxKind.NumericLiteral; /* @internal */ - numericLiteralFlags?: TokenFlags; + numericLiteralFlags: TokenFlags; } export interface TemplateHead extends LiteralLikeNode { kind: SyntaxKind.TemplateHead; - parent?: TemplateExpression; + parent: TemplateExpression; } export interface TemplateMiddle extends LiteralLikeNode { kind: SyntaxKind.TemplateMiddle; - parent?: TemplateSpan; + parent: TemplateSpan; } export interface TemplateTail extends LiteralLikeNode { kind: SyntaxKind.TemplateTail; - parent?: TemplateSpan; + parent: TemplateSpan; } export type TemplateLiteral = TemplateExpression | NoSubstitutionTemplateLiteral; @@ -1634,7 +1634,7 @@ namespace ts { // The template literal must have kind TemplateMiddleLiteral or TemplateTailLiteral. export interface TemplateSpan extends Node { kind: SyntaxKind.TemplateSpan; - parent?: TemplateExpression; + parent: TemplateExpression; expression: Expression; literal: TemplateMiddle | TemplateTail; } @@ -1653,7 +1653,7 @@ namespace ts { export interface SpreadElement extends Expression { kind: SyntaxKind.SpreadElement; - parent?: ArrayLiteralExpression | CallExpression | NewExpression; + parent: ArrayLiteralExpression | CallExpression | NewExpression; expression: Expression; } @@ -1724,7 +1724,7 @@ namespace ts { export interface ExpressionWithTypeArguments extends NodeWithTypeArguments { kind: SyntaxKind.ExpressionWithTypeArguments; - parent?: HeritageClause; + parent: HeritageClause; expression: LeftHandSideExpression; } @@ -1787,13 +1787,13 @@ namespace ts { export type JsxTagNameExpression = PrimaryExpression | PropertyAccessExpression; export interface JsxAttributes extends ObjectLiteralExpressionBase { - parent?: JsxOpeningLikeElement; + parent: JsxOpeningLikeElement; } /// The opening element of a ... JsxElement export interface JsxOpeningElement extends Expression { kind: SyntaxKind.JsxOpeningElement; - parent?: JsxElement; + parent: JsxElement; tagName: JsxTagNameExpression; typeArguments?: NodeArray; attributes: JsxAttributes; @@ -1818,18 +1818,18 @@ namespace ts { /// The opening element of a <>... JsxFragment export interface JsxOpeningFragment extends Expression { kind: SyntaxKind.JsxOpeningFragment; - parent?: JsxFragment; + parent: JsxFragment; } /// The closing element of a <>... JsxFragment export interface JsxClosingFragment extends Expression { kind: SyntaxKind.JsxClosingFragment; - parent?: JsxFragment; + parent: JsxFragment; } export interface JsxAttribute extends ObjectLiteralElement { kind: SyntaxKind.JsxAttribute; - parent?: JsxAttributes; + parent: JsxAttributes; name: Identifier; /// JSX attribute initializers are optional; is sugar for initializer?: StringLiteral | JsxExpression; @@ -1837,19 +1837,19 @@ namespace ts { export interface JsxSpreadAttribute extends ObjectLiteralElement { kind: SyntaxKind.JsxSpreadAttribute; - parent?: JsxAttributes; + parent: JsxAttributes; expression: Expression; } export interface JsxClosingElement extends Node { kind: SyntaxKind.JsxClosingElement; - parent?: JsxElement; + parent: JsxElement; tagName: JsxTagNameExpression; } export interface JsxExpression extends Expression { kind: SyntaxKind.JsxExpression; - parent?: JsxElement | JsxAttributeLike; + parent: JsxElement | JsxAttributeLike; dotDotDotToken?: Token; expression?: Expression; } @@ -1857,7 +1857,7 @@ namespace ts { export interface JsxText extends Node { kind: SyntaxKind.JsxText; containsOnlyWhiteSpaces: boolean; - parent?: JsxElement; + parent: JsxElement; } export type JsxChild = JsxText | JsxExpression | JsxElement | JsxSelfClosingElement | JsxFragment; @@ -2009,20 +2009,20 @@ namespace ts { export interface CaseBlock extends Node { kind: SyntaxKind.CaseBlock; - parent?: SwitchStatement; + parent: SwitchStatement; clauses: NodeArray; } export interface CaseClause extends Node { kind: SyntaxKind.CaseClause; - parent?: CaseBlock; + parent: CaseBlock; expression: Expression; statements: NodeArray; } export interface DefaultClause extends Node { kind: SyntaxKind.DefaultClause; - parent?: CaseBlock; + parent: CaseBlock; statements: NodeArray; } @@ -2036,7 +2036,7 @@ namespace ts { export interface ThrowStatement extends Statement { kind: SyntaxKind.ThrowStatement; - expression: Expression; + expression?: Expression; } export interface TryStatement extends Statement { @@ -2048,7 +2048,7 @@ namespace ts { export interface CatchClause extends Node { kind: SyntaxKind.CatchClause; - parent?: TryStatement; + parent: TryStatement; variableDeclaration?: VariableDeclaration; block: Block; } @@ -2098,7 +2098,7 @@ namespace ts { export interface HeritageClause extends Node { kind: SyntaxKind.HeritageClause; - parent?: InterfaceDeclaration | ClassLikeDeclaration; + parent: InterfaceDeclaration | ClassLikeDeclaration; token: SyntaxKind.ExtendsKeyword | SyntaxKind.ImplementsKeyword; types: NodeArray; } @@ -2112,7 +2112,7 @@ namespace ts { export interface EnumMember extends NamedDeclaration, JSDocContainer { kind: SyntaxKind.EnumMember; - parent?: EnumDeclaration; + parent: EnumDeclaration; // This does include ComputedPropertyName, but the parser will give an error // if it parses a ComputedPropertyName in an EnumMember name: PropertyName; @@ -2134,7 +2134,7 @@ namespace ts { export interface ModuleDeclaration extends DeclarationStatement, JSDocContainer { kind: SyntaxKind.ModuleDeclaration; - parent?: ModuleBody | SourceFile; + parent: ModuleBody | SourceFile; name: ModuleName; body?: ModuleBody | JSDocNamespaceDeclaration; } @@ -2150,12 +2150,12 @@ namespace ts { export interface JSDocNamespaceDeclaration extends ModuleDeclaration { name: Identifier; - body: JSDocNamespaceBody; + body?: JSDocNamespaceBody; } export interface ModuleBlock extends Node, Statement { kind: SyntaxKind.ModuleBlock; - parent?: ModuleDeclaration; + parent: ModuleDeclaration; statements: NodeArray; } @@ -2168,7 +2168,7 @@ namespace ts { */ export interface ImportEqualsDeclaration extends DeclarationStatement, JSDocContainer { kind: SyntaxKind.ImportEqualsDeclaration; - parent?: SourceFile | ModuleBlock; + parent: SourceFile | ModuleBlock; name: Identifier; // 'EntityName' for an internal module reference, 'ExternalModuleReference' for an external @@ -2178,8 +2178,8 @@ namespace ts { export interface ExternalModuleReference extends Node { kind: SyntaxKind.ExternalModuleReference; - parent?: ImportEqualsDeclaration; - expression?: Expression; + parent: ImportEqualsDeclaration; + expression: Expression; } // In case of: @@ -2188,7 +2188,7 @@ namespace ts { // ImportClause information is shown at its declaration below. export interface ImportDeclaration extends Statement { kind: SyntaxKind.ImportDeclaration; - parent?: SourceFile | ModuleBlock; + parent: SourceFile | ModuleBlock; importClause?: ImportClause; /** If this is not a StringLiteral it will be a grammar error. */ moduleSpecifier: Expression; @@ -2204,14 +2204,14 @@ namespace ts { // import d, { a, b as x } from "mod" => name = d, namedBinding: NamedImports = { elements: [{ name: a }, { name: x, propertyName: b}]} export interface ImportClause extends NamedDeclaration { kind: SyntaxKind.ImportClause; - parent?: ImportDeclaration; + parent: ImportDeclaration; name?: Identifier; // Default binding namedBindings?: NamedImportBindings; } export interface NamespaceImport extends NamedDeclaration { kind: SyntaxKind.NamespaceImport; - parent?: ImportClause; + parent: ImportClause; name: Identifier; } @@ -2222,7 +2222,7 @@ namespace ts { export interface ExportDeclaration extends DeclarationStatement { kind: SyntaxKind.ExportDeclaration; - parent?: SourceFile | ModuleBlock; + parent: SourceFile | ModuleBlock; /** Will not be assigned in the case of `export * from "foo";` */ exportClause?: NamedExports; /** If this is not a StringLiteral it will be a grammar error. */ @@ -2231,13 +2231,13 @@ namespace ts { export interface NamedImports extends Node { kind: SyntaxKind.NamedImports; - parent?: ImportClause; + parent: ImportClause; elements: NodeArray; } export interface NamedExports extends Node { kind: SyntaxKind.NamedExports; - parent?: ExportDeclaration; + parent: ExportDeclaration; elements: NodeArray; } @@ -2245,14 +2245,14 @@ namespace ts { export interface ImportSpecifier extends NamedDeclaration { kind: SyntaxKind.ImportSpecifier; - parent?: NamedImports; + parent: NamedImports; propertyName?: Identifier; // Name preceding "as" keyword (or undefined when "as" is absent) name: Identifier; // Declared name } export interface ExportSpecifier extends NamedDeclaration { kind: SyntaxKind.ExportSpecifier; - parent?: NamedExports; + parent: NamedExports; propertyName?: Identifier; // Name preceding "as" keyword (or undefined when "as" is absent) name: Identifier; // Declared name } @@ -2265,7 +2265,7 @@ namespace ts { */ export interface ExportAssignment extends DeclarationStatement { kind: SyntaxKind.ExportAssignment; - parent?: SourceFile; + parent: SourceFile; isExportEquals?: boolean; expression: Expression; } @@ -2337,16 +2337,16 @@ namespace ts { export interface JSDoc extends Node { kind: SyntaxKind.JSDocComment; - parent?: HasJSDoc; - tags: NodeArray | undefined; - comment: string | undefined; + parent: HasJSDoc; + tags?: NodeArray; + comment?: string; } export interface JSDocTag extends Node { parent: JSDoc | JSDocTypeLiteral; atToken: AtToken; tagName: Identifier; - comment: string | undefined; + comment?: string; } export interface JSDocUnknownTag extends JSDocTag { @@ -2373,12 +2373,12 @@ namespace ts { export interface JSDocReturnTag extends JSDocTag { kind: SyntaxKind.JSDocReturnTag; - typeExpression: JSDocTypeExpression; + typeExpression?: JSDocTypeExpression; } export interface JSDocTypeTag extends JSDocTag { kind: SyntaxKind.JSDocTypeTag; - typeExpression: JSDocTypeExpression; + typeExpression?: JSDocTypeExpression; } export interface JSDocTypedefTag extends JSDocTag, NamedDeclaration { @@ -2475,7 +2475,7 @@ namespace ts { // FlowLabel represents a junction with multiple possible preceding control flows. export interface FlowLabel extends FlowNodeBase { - antecedents: FlowNode[]; + antecedents: FlowNode[] | undefined; } // FlowAssignment represents a node that assigns a value to a narrowable reference, @@ -2518,7 +2518,7 @@ namespace ts { export interface AmdDependency { path: string; - name: string; + name?: string; } /* @internal */ @@ -2557,10 +2557,10 @@ namespace ts { * (See `createRedirectSourceFile` in program.ts.) * The redirect will have this set. The redirected-to source file will be in `redirectTargetsSet`. */ - /* @internal */ redirectInfo?: RedirectInfo | undefined; + /* @internal */ redirectInfo?: RedirectInfo; amdDependencies: ReadonlyArray; - moduleName: string; + moduleName?: string; referencedFiles: ReadonlyArray; typeReferenceDirectives: ReadonlyArray; languageVariant: LanguageVariant; @@ -2588,9 +2588,9 @@ namespace ts { * This is intended to be the first top-level import/export, * but could be arbitrarily nested (e.g. `import.meta`). */ - /* @internal */ externalModuleIndicator: Node; + /* @internal */ externalModuleIndicator?: Node; // The first node that causes this file to be a CommonJS module - /* @internal */ commonJsModuleIndicator: Node; + /* @internal */ commonJsModuleIndicator?: Node; /* @internal */ identifiers: Map; // Map from a string to an interned string /* @internal */ nodeCount: number; @@ -2618,7 +2618,7 @@ namespace ts { // Stores a mapping 'external module reference text' -> 'resolved file name' | undefined // It is used to resolve module names in the checker. // Content of this field should never be used directly - use getResolvedModuleFileName/setResolvedModuleFileName functions instead - /* @internal */ resolvedModules: Map; + /* @internal */ resolvedModules?: Map; /* @internal */ resolvedTypeReferenceDirectiveNames: Map; /* @internal */ imports: ReadonlyArray; /** @@ -2631,7 +2631,7 @@ namespace ts { /* @internal */ moduleAugmentations: ReadonlyArray; /* @internal */ patternAmbientModules?: PatternAmbientModule[]; /* @internal */ ambientModuleNames: ReadonlyArray; - /* @internal */ checkJsDirective: CheckJsDirective | undefined; + /* @internal */ checkJsDirective?: CheckJsDirective; /* @internal */ version: string; /* @internal */ pragmas: PragmaMap; /* @internal */ localJsxNamespace?: __String; @@ -2702,7 +2702,7 @@ namespace ts { data: string, writeByteOrderMark: boolean, onError: ((message: string) => void) | undefined, - sourceFiles: ReadonlyArray, + sourceFiles?: ReadonlyArray, ) => void; export class OperationCanceledException { } @@ -2714,6 +2714,7 @@ namespace ts { throwIfCancellationRequested(): void; } + // TODO: This should implement TypeCheckerHost but that's an internal type. export interface Program extends ScriptReferenceHost { /** @@ -2861,8 +2862,8 @@ namespace ts { emitSkipped: boolean; /** Contains declaration emit diagnostics */ diagnostics: ReadonlyArray; - emittedFiles: string[]; // Array of files the compiler wrote to disk - /* @internal */ sourceMaps: SourceMapData[]; // Array of sourceMapData if compiler emitted sourcemaps + emittedFiles?: string[]; // Array of files the compiler wrote to disk + /* @internal */ sourceMaps?: SourceMapData[]; // Array of sourceMapData if compiler emitted sourcemaps } /* @internal */ @@ -2894,9 +2895,10 @@ namespace ts { getNullableType(type: Type, flags: TypeFlags): Type; getNonNullableType(type: Type): Type; + // TODO: GH#18217 `xToDeclaration` calls are frequently asserted as defined. /** Note that the resulting nodes cannot be checked. */ - typeToTypeNode(type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): TypeNode; - /* @internal */ typeToTypeNode(type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker): TypeNode; // tslint:disable-line unified-signatures + typeToTypeNode(type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): TypeNode | undefined; + /* @internal */ typeToTypeNode(type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker): TypeNode | undefined; // tslint:disable-line unified-signatures /** Note that the resulting nodes cannot be checked. */ signatureToSignatureDeclaration(signature: Signature, kind: SyntaxKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): SignatureDeclaration & {typeArguments?: NodeArray} | undefined; /** Note that the resulting nodes cannot be checked. */ @@ -2931,7 +2933,7 @@ namespace ts { */ getExportSymbolOfSymbol(symbol: Symbol): Symbol; getPropertySymbolOfDestructuringAssignment(location: Identifier): Symbol | undefined; - getTypeAtLocation(node: Node): Type; + getTypeAtLocation(node: Node): Type | undefined; getTypeFromTypeNode(node: TypeNode): Type; signatureToString(signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): string; @@ -2953,15 +2955,16 @@ namespace ts { getAugmentedPropertiesOfType(type: Type): Symbol[]; getRootSymbols(symbol: Symbol): Symbol[]; getContextualType(node: Expression): Type | undefined; - /* @internal */ getContextualTypeForArgumentAtIndex(call: CallLikeExpression, argIndex: number): Type; + /* @internal */ getContextualTypeForArgumentAtIndex(call: CallLikeExpression, argIndex: number): Type | undefined; /* @internal */ getContextualTypeForJsxAttribute(attribute: JsxAttribute | JsxSpreadAttribute): Type | undefined; /* @internal */ isContextSensitive(node: Expression | MethodDeclaration | ObjectLiteralElementLike | JsxAttributeLike): boolean; /** * returns unknownSignature in the case of an error. + * returns undefined if the node is not valid. * @param argumentCount Apparent number of arguments, passed in case of a possibly incomplete call. This should come from an ArgumentListInfo. See `signatureHelp.ts`. */ - getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[], argumentCount?: number): Signature; + getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[], argumentCount?: number): Signature | undefined; getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature | undefined; isImplementationOfOverload(node: SignatureDeclaration): boolean | undefined; isUndefinedSymbol(symbol: Symbol): boolean; @@ -2976,7 +2979,7 @@ namespace ts { /** Follow all aliases to get the original symbol. */ getAliasedSymbol(symbol: Symbol): Symbol; /** Follow a *single* alias to get the immediately aliased symbol. */ - /* @internal */ getImmediateAliasedSymbol(symbol: Symbol): Symbol; + /* @internal */ getImmediateAliasedSymbol(symbol: Symbol): Symbol | undefined; getExportsOfModule(moduleSymbol: Symbol): Symbol[]; /** Unlike `getExportsOfModule`, this includes properties of an `export =` value. */ /* @internal */ getExportsAndPropertiesOfModule(moduleSymbol: Symbol): Symbol[]; @@ -3012,10 +3015,10 @@ namespace ts { /* @internal */ createArrayType(elementType: Type): Type; /* @internal */ createPromiseType(type: Type): Type; - /* @internal */ createAnonymousType(symbol: Symbol, members: SymbolTable, callSignatures: Signature[], constructSignatures: Signature[], stringIndexInfo: IndexInfo, numberIndexInfo: IndexInfo): Type; + /* @internal */ createAnonymousType(symbol: Symbol, members: SymbolTable, callSignatures: Signature[], constructSignatures: Signature[], stringIndexInfo: IndexInfo | undefined, numberIndexInfo: IndexInfo | undefined): Type; /* @internal */ createSignature( declaration: SignatureDeclaration, - typeParameters: TypeParameter[], + typeParameters: TypeParameter[] | undefined, thisParameter: Symbol | undefined, parameters: Symbol[], resolvedReturnType: Type, @@ -3026,7 +3029,7 @@ namespace ts { ): Signature; /* @internal */ createSymbol(flags: SymbolFlags, name: __String): TransientSymbol; /* @internal */ createIndexInfo(type: Type, isReadonly: boolean, declaration?: SignatureDeclaration): IndexInfo; - /* @internal */ isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags, shouldComputeAliasToMarkVisible: boolean): SymbolAccessibilityResult; + /* @internal */ isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags, shouldComputeAliasToMarkVisible: boolean): SymbolAccessibilityResult; /* @internal */ tryFindAmbientModuleWithoutAugmentations(moduleName: string): Symbol | undefined; /* @internal */ getSymbolWalker(accept?: (symbol: Symbol) => boolean): SymbolWalker; @@ -3313,9 +3316,9 @@ namespace ts { /* @internal */ export interface AllAccessorDeclarations { firstAccessor: AccessorDeclaration; - secondAccessor: AccessorDeclaration; - getAccessor: AccessorDeclaration; - setAccessor: AccessorDeclaration; + secondAccessor: AccessorDeclaration | undefined; + getAccessor: AccessorDeclaration | undefined; + setAccessor: AccessorDeclaration | undefined; } /** Indicates how to serialize the name for a TypeReferenceNode when emitting decorator metadata */ @@ -3342,9 +3345,9 @@ namespace ts { /* @internal */ export interface EmitResolver { hasGlobalName(name: string): boolean; - getReferencedExportContainer(node: Identifier, prefixLocals?: boolean): SourceFile | ModuleDeclaration | EnumDeclaration; - getReferencedImportDeclaration(node: Identifier): Declaration; - getReferencedDeclarationWithCollidingName(node: Identifier): Declaration; + getReferencedExportContainer(node: Identifier, prefixLocals?: boolean): SourceFile | ModuleDeclaration | EnumDeclaration | undefined; + getReferencedImportDeclaration(node: Identifier): Declaration | undefined; + getReferencedDeclarationWithCollidingName(node: Identifier): Declaration | undefined; isDeclarationWithCollidingName(node: Declaration): boolean; isValueAliasDeclaration(node: Node): boolean; isReferencedAliasDeclaration(node: Node, checkChildren?: boolean): boolean; @@ -3352,28 +3355,28 @@ namespace ts { getNodeCheckFlags(node: Node): NodeCheckFlags; isDeclarationVisible(node: Declaration | AnyImportSyntax): boolean; isLateBound(node: Declaration): node is LateBoundDeclaration; - collectLinkedAliases(node: Identifier): Node[]; + collectLinkedAliases(node: Identifier): Node[] | undefined; isImplementationOfOverload(node: FunctionLike): boolean | undefined; isRequiredInitializedParameter(node: ParameterDeclaration): boolean; isOptionalUninitializedParameterProperty(node: ParameterDeclaration): boolean; - createTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker, addUndefined?: boolean): TypeNode; - createReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker): TypeNode; - createTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker): TypeNode; + createTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker, addUndefined?: boolean): TypeNode | undefined; + createReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker): TypeNode | undefined; + createTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker): TypeNode | undefined; createLiteralConstValue(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration): Expression; - isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags, shouldComputeAliasToMarkVisible: boolean): SymbolAccessibilityResult; + isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags | undefined, shouldComputeAliasToMarkVisible: boolean): SymbolAccessibilityResult; isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node): SymbolVisibilityResult; // Returns the constant value this property access resolves to, or 'undefined' for a non-constant - getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): string | number; - getReferencedValueDeclaration(reference: Identifier): Declaration; + getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): string | number | undefined; + getReferencedValueDeclaration(reference: Identifier): Declaration | undefined; getTypeReferenceSerializationKind(typeName: EntityName, location?: Node): TypeReferenceSerializationKind; isOptionalParameter(node: ParameterDeclaration): boolean; moduleExportsSomeValue(moduleReferenceExpression: Expression): boolean; isArgumentsLocalBinding(node: Identifier): boolean; - getExternalModuleFileFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration | ImportTypeNode): SourceFile; - getTypeReferenceDirectivesForEntityName(name: EntityNameOrEntityNameExpression): string[]; - getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags): string[]; + getExternalModuleFileFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration | ImportTypeNode): SourceFile | undefined; + getTypeReferenceDirectivesForEntityName(name: EntityNameOrEntityNameExpression): string[] | undefined; + getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags): string[] | undefined; isLiteralConstDeclaration(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration): boolean; - getJsxFactoryEntity(location?: Node): EntityName; + getJsxFactoryEntity(location?: Node): EntityName | undefined; getAllAccessorDeclarations(declaration: AccessorDeclaration): AllAccessorDeclarations; } @@ -3469,8 +3472,8 @@ namespace ts { export interface Symbol { flags: SymbolFlags; // Symbol flags escapedName: __String; // Name of symbol - declarations?: Declaration[]; // Declarations associated with this symbol - valueDeclaration?: Declaration; // First value declaration of the symbol + declarations: Declaration[]; // Declarations associated with this symbol + valueDeclaration: Declaration; // First value declaration of the symbol members?: SymbolTable; // Class, interface or object literal instance members exports?: SymbolTable; // Module exports globalExports?: SymbolTable; // Conditional global UMD exports @@ -3641,7 +3644,7 @@ namespace ts { /* @internal */ export interface NodeLinks { - flags?: NodeCheckFlags; // Set of flags specific to Node + flags: NodeCheckFlags; // Set of flags specific to Node resolvedType?: Type; // Cached type of type node resolvedSignature?: Signature; // Cached signature of signature node or call expression resolvedSignatures?: Map; // Cached signatures of jsx node @@ -3652,7 +3655,7 @@ namespace ts { isVisible?: boolean; // Is this node visible containsArgumentsReference?: boolean; // Whether a function-like declaration contains an 'arguments' reference hasReportedStatementInAmbientContext?: boolean; // Cache boolean if we report statements in ambient context - jsxFlags?: JsxFlags; // flags for knowing what kind of element/attributes we're dealing with + jsxFlags: JsxFlags; // flags for knowing what kind of element/attributes we're dealing with resolvedJsxElementAttributesType?: Type; // resolved element attributes type of a JSX openinglike element resolvedJsxElementAllAttributesType?: Type; // resolved all element attributes type of a JSX openinglike element hasSuperCall?: boolean; // recorded result when we try to find super-call. We only try to find one if this flag is undefined, indicating that we haven't made an attempt. @@ -3756,7 +3759,7 @@ namespace ts { flags: TypeFlags; // Flags /* @internal */ id: number; // Unique ID /* @internal */ checker: TypeChecker; - symbol?: Symbol; // Symbol associated with type (if any) + symbol: Symbol; // Symbol associated with type (if any) pattern?: DestructuringPattern; // Destructuring pattern represented by type (if any) aliasSymbol?: Symbol; // Alias associated with type aliasTypeArguments?: Type[]; // Alias type arguments (if any) @@ -3774,8 +3777,8 @@ namespace ts { // Numeric literal types (TypeFlags.NumberLiteral) export interface LiteralType extends Type { value: string | number; // Value of literal - freshType?: LiteralType; // Fresh version of type - regularType?: LiteralType; // Regular version of type + freshType: LiteralType; // Fresh version of type + regularType: LiteralType; // Regular version of type } // Unique symbol types (TypeFlags.UniqueESSymbol) @@ -3820,25 +3823,25 @@ namespace ts { /** Class and interface types (ObjectFlags.Class and ObjectFlags.Interface). */ export interface InterfaceType extends ObjectType { - typeParameters: TypeParameter[]; // Type parameters (undefined if non-generic) - outerTypeParameters: TypeParameter[]; // Outer type parameters (undefined if none) - localTypeParameters: TypeParameter[]; // Local type parameters (undefined if none) - thisType: TypeParameter; // The "this" type (undefined if none) + typeParameters: TypeParameter[] | undefined; // Type parameters (undefined if non-generic) + outerTypeParameters: TypeParameter[] | undefined; // Outer type parameters (undefined if none) + localTypeParameters: TypeParameter[] | undefined; // Local type parameters (undefined if none) + thisType: TypeParameter | undefined; // The "this" type (undefined if none) /* @internal */ - resolvedBaseConstructorType?: Type; // Resolved base constructor type of class + resolvedBaseConstructorType?: Type; // Resolved base constructor type of class /* @internal */ - resolvedBaseTypes: BaseType[]; // Resolved base types + resolvedBaseTypes: BaseType[]; // Resolved base types } // Object type or intersection of object types export type BaseType = ObjectType | IntersectionType; export interface InterfaceTypeWithDeclaredMembers extends InterfaceType { - declaredProperties: Symbol[]; // Declared members - declaredCallSignatures: Signature[]; // Declared call signatures - declaredConstructSignatures: Signature[]; // Declared construct signatures - declaredStringIndexInfo: IndexInfo; // Declared string indexing info - declaredNumberIndexInfo: IndexInfo; // Declared numeric indexing info + declaredProperties: Symbol[]; // Declared members + declaredCallSignatures: Signature[]; // Declared call signatures + declaredConstructSignatures: Signature[]; // Declared construct signatures + declaredStringIndexInfo?: IndexInfo; // Declared string indexing info + declaredNumberIndexInfo?: IndexInfo; // Declared numeric indexing info } /** @@ -3928,12 +3931,12 @@ namespace ts { /* @internal */ // Resolved object, union, or intersection type export interface ResolvedType extends ObjectType, UnionOrIntersectionType { - members: SymbolTable; // Properties by name - properties: Symbol[]; // Properties - callSignatures: Signature[]; // Call signatures of type - constructSignatures: Signature[]; // Construct signatures of type - stringIndexInfo?: IndexInfo; // String indexing info - numberIndexInfo?: IndexInfo; // Numeric indexing info + members: SymbolTable; // Properties by name + properties: Symbol[]; // Properties + callSignatures: Signature[]; // Call signatures of type + constructSignatures: Signature[]; // Construct signatures of type + stringIndexInfo?: IndexInfo; // String indexing info + numberIndexInfo?: IndexInfo; // Numeric indexing info } /* @internal */ @@ -4016,11 +4019,11 @@ namespace ts { trueType: Type; falseType: Type; isDistributive: boolean; - inferTypeParameters: TypeParameter[]; + inferTypeParameters?: TypeParameter[]; outerTypeParameters?: TypeParameter[]; instantiations?: Map; - aliasSymbol: Symbol; - aliasTypeArguments: Type[]; + aliasSymbol?: Symbol; + aliasTypeArguments?: Type[]; } // T extends U ? X : Y (TypeFlags.Conditional) @@ -4062,12 +4065,12 @@ namespace ts { thisParameter?: Symbol; // symbol of this-type parameter /* @internal */ // See comment in `instantiateSignature` for why these are set lazily. - resolvedReturnType: Type | undefined; // Lazily set by `getReturnTypeOfSignature`. + resolvedReturnType?: Type; // Lazily set by `getReturnTypeOfSignature`. /* @internal */ // Lazily set by `getTypePredicateOfSignature`. // `undefined` indicates a type predicate that has not yet been computed. // Uses a special `noTypePredicate` sentinel value to indicate that there is no type predicate. This looks like a TypePredicate at runtime to avoid polymorphism. - resolvedTypePredicate: TypePredicate | undefined; + resolvedTypePredicate?: TypePredicate; /* @internal */ minArgumentCount: number; // Number of non-optional parameters /* @internal */ @@ -4118,13 +4121,13 @@ namespace ts { /* @internal */ export interface InferenceInfo { - typeParameter: TypeParameter; // Type parameter for which inferences are being made - candidates: Type[]; // Candidates in covariant positions (or undefined) - contraCandidates: Type[]; // Candidates in contravariant positions (or undefined) - inferredType: Type; // Cache for resolved inferred type - priority: InferencePriority; // Priority of current inference set - topLevel: boolean; // True if all inferences are to top level occurrences - isFixed: boolean; // True if inferences are fixed + typeParameter: TypeParameter; // Type parameter for which inferences are being made + candidates: Type[] | undefined; // Candidates in covariant positions (or undefined) + contraCandidates: Type[] | undefined; // Candidates in contravariant positions (or undefined) + inferredType?: Type; // Cache for resolved inferred type + priority?: InferencePriority; // Priority of current inference set + topLevel: boolean; // True if all inferences are to top level occurrences + isFixed: boolean; // True if inferences are fixed } /* @internal */ @@ -4157,7 +4160,7 @@ namespace ts { /* @internal */ export interface InferenceContext extends TypeMapper { typeParameters: TypeParameter[]; // Type parameters for which inferences are made - signature: Signature; // Generic signature for which inferences are made (if any) + signature?: Signature; // Generic signature for which inferences are made (if any) inferences: InferenceInfo[]; // Inferences made for each type parameter flags: InferenceFlags; // Inference flags compareTypes: TypeComparer; // Type comparer function @@ -4355,7 +4358,7 @@ namespace ts { suppressExcessPropertyErrors?: boolean; suppressImplicitAnyIndexErrors?: boolean; /* @internal */ suppressOutputPathCheck?: boolean; - target?: ScriptTarget; + target?: ScriptTarget; // TODO: GH#18217 frequently asserted as defined traceResolution?: boolean; resolveJsonModule?: boolean; types?: string[]; @@ -4462,18 +4465,18 @@ namespace ts { /* @internal */ export interface ConfigFileSpecs { - filesSpecs: ReadonlyArray; + filesSpecs: ReadonlyArray | undefined; referencesSpecs: ReadonlyArray | undefined; /** * Present to report errors (user specified specs), validatedIncludeSpecs are used for file name matching */ - includeSpecs: ReadonlyArray; + includeSpecs?: ReadonlyArray; /** * Present to report errors (user specified specs), validatedExcludeSpecs are used for file name matching */ - excludeSpecs: ReadonlyArray; - validatedIncludeSpecs: ReadonlyArray; - validatedExcludeSpecs: ReadonlyArray; + excludeSpecs?: ReadonlyArray; + validatedIncludeSpecs?: ReadonlyArray; + validatedExcludeSpecs?: ReadonlyArray; wildcardDirectories: MapLike; } @@ -4671,6 +4674,8 @@ namespace ts { } export interface ModuleResolutionHost { + // TODO: GH#18217 Optional methods frequently used as non-optional + fileExists(fileName: string): boolean; // readFile function is used to read arbitrary text files on disk, i.e. when resolution procedure needs the content of 'package.json' // to determine location of bundled typings for node module @@ -4760,7 +4765,7 @@ namespace ts { } export interface ResolvedTypeReferenceDirectiveWithFailedLookupLocations { - readonly resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective; + readonly resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective | undefined; readonly failedLookupLocations: ReadonlyArray; } @@ -4792,8 +4797,8 @@ namespace ts { /** * This method is a companion for 'resolveModuleNames' and is used to resolve 'types' references to actual type declaration files */ - resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): (ResolvedTypeReferenceDirective | undefined)[]; - getEnvironmentVariable?(name: string): string; + resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[]; + getEnvironmentVariable?(name: string): string | undefined; /* @internal */ onReleaseOldSourceFile?(oldSourceFile: SourceFile, oldOptions: CompilerOptions): void; /* @internal */ hasInvalidatedResolution?: HasInvalidatedResolution; /* @internal */ hasChangedAutomaticTypeDirectiveNames?: boolean; @@ -4897,12 +4902,12 @@ namespace ts { /* @internal */ export interface EmitNode { annotatedNodes?: Node[]; // Tracks Parse-tree nodes with EmitNodes for eventual cleanup. - flags?: EmitFlags; // Flags that customize emit + flags: EmitFlags; // Flags that customize emit leadingComments?: SynthesizedComment[]; // Synthesized leading comments trailingComments?: SynthesizedComment[]; // Synthesized trailing comments commentRange?: TextRange; // The text range to use when emitting leading or trailing comments sourceMapRange?: SourceMapRange; // The text range to use when emitting leading or trailing source mappings - tokenSourceMapRanges?: SourceMapRange[]; // The text range to use when emitting source mappings for tokens + tokenSourceMapRanges?: (SourceMapRange | undefined)[]; // The text range to use when emitting source mappings for tokens constantValue?: string | number; // The constant value of an expression externalHelpersModuleName?: Identifier; // The local name for an imported helpers module helpers?: EmitHelper[]; // Emit helpers for the node @@ -4910,6 +4915,7 @@ namespace ts { } export const enum EmitFlags { + None = 0, SingleLine = 1 << 0, // The contents of this node should be emitted on a single line. AdviseOnEmitNode = 1 << 1, // The printer should invoke the onEmitNode callback when printing this node. NoSubstitution = 1 << 2, // Disables further substitution of an expression. @@ -5040,7 +5046,7 @@ namespace ts { resumeLexicalEnvironment(): void; /** Ends a lexical environment, returning any declarations. */ - endLexicalEnvironment(): Statement[]; + endLexicalEnvironment(): Statement[] | undefined; /** Hoists a function declaration to the containing scope. */ hoistFunctionDeclaration(node: FunctionDeclaration): void; @@ -5169,7 +5175,7 @@ namespace ts { */ printBundle(bundle: Bundle): string; /*@internal*/ writeNode(hint: EmitHint, node: Node, sourceFile: SourceFile | undefined, writer: EmitTextWriter): void; - /*@internal*/ writeList(format: ListFormat, list: NodeArray, sourceFile: SourceFile | undefined, writer: EmitTextWriter): void; + /*@internal*/ writeList(format: ListFormat, list: NodeArray | undefined, sourceFile: SourceFile | undefined, writer: EmitTextWriter): void; /*@internal*/ writeFile(sourceFile: SourceFile, writer: EmitTextWriter): void; /*@internal*/ writeBundle(bundle: Bundle, writer: EmitTextWriter, info?: BundleInfo): void; } @@ -5214,7 +5220,7 @@ namespace ts { * }); * ``` */ - onEmitNode?(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void; + onEmitNode?(hint: EmitHint, node: Node | undefined, emitCallback: (hint: EmitHint, node: Node | undefined) => void): void; /** * A hook used by the Printer to perform just-in-time substitution of a node. This is * primarily used by node transformations that need to substitute one node for another, @@ -5233,11 +5239,11 @@ namespace ts { */ substituteNode?(hint: EmitHint, node: Node): Node; /*@internal*/ onEmitSourceMapOfNode?: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void; - /*@internal*/ onEmitSourceMapOfToken?: (node: Node, token: SyntaxKind, writer: (s: string) => void, pos: number, emitCallback: (token: SyntaxKind, writer: (s: string) => void, pos: number) => number) => number; + /*@internal*/ onEmitSourceMapOfToken?: (node: Node | undefined, token: SyntaxKind, writer: (s: string) => void, pos: number, emitCallback: (token: SyntaxKind, writer: (s: string) => void, pos: number) => number) => number; /*@internal*/ onEmitSourceMapOfPosition?: (pos: number) => void; /*@internal*/ onSetSourceFile?: (node: SourceFile) => void; - /*@internal*/ onBeforeEmitNodeArray?: (nodes: NodeArray) => void; - /*@internal*/ onAfterEmitNodeArray?: (nodes: NodeArray) => void; + /*@internal*/ onBeforeEmitNodeArray?: (nodes: NodeArray | undefined) => void; + /*@internal*/ onAfterEmitNodeArray?: (nodes: NodeArray | undefined) => void; /*@internal*/ onBeforeEmitToken?: (node: Node) => void; /*@internal*/ onAfterEmitToken?: (node: Node) => void; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 64996153d23b6..d25d41e6bbaff 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -6,7 +6,7 @@ namespace ts { export const externalHelpersModuleNameText = "tslib"; - export function getDeclarationOfKind(symbol: Symbol, kind: T["kind"]): T { + export function getDeclarationOfKind(symbol: Symbol, kind: T["kind"]): T | undefined { const declarations = symbol.declarations; if (declarations) { for (const declaration of declarations) { @@ -103,7 +103,7 @@ namespace ts { } function packageIdIsEqual(a: PackageId | undefined, b: PackageId | undefined): boolean { - return a === b || a && b && a.name === b.name && a.subModuleName === b.subModuleName && a.version === b.version; + return a === b || !!a && !!b && a.name === b.name && a.subModuleName === b.subModuleName && a.version === b.version; } export function packageIdToString({ name, subModuleName, version }: PackageId): string { @@ -118,7 +118,7 @@ namespace ts { export function hasChangesInResolutions( names: ReadonlyArray, newResolutions: ReadonlyArray, - oldResolutions: ReadonlyMap, + oldResolutions: ReadonlyMap | undefined, comparer: (oldResolution: T, newResolution: T) => boolean): boolean { Debug.assert(names.length === newResolutions.length); @@ -162,6 +162,8 @@ namespace ts { } } + export function getSourceFileOfNode(node: Node): SourceFile; + export function getSourceFileOfNode(node: Node | undefined): SourceFile | undefined; export function getSourceFileOfNode(node: Node): SourceFile { while (node && node.kind !== SyntaxKind.SourceFile) { node = node.parent; @@ -240,7 +242,7 @@ namespace ts { // code). So the parser will attempt to parse out a type, and will create an actual node. // However, this node will be 'missing' in the sense that no actual source-code/tokens are // contained within it. - export function nodeIsMissing(node: Node) { + export function nodeIsMissing(node: Node | undefined): boolean { if (node === undefined) { return true; } @@ -248,7 +250,7 @@ namespace ts { return node.pos === node.end && node.pos >= 0 && node.kind !== SyntaxKind.EndOfFileToken; } - export function nodeIsPresent(node: Node) { + export function nodeIsPresent(node: Node | undefined): boolean { return !nodeIsMissing(node); } @@ -290,7 +292,7 @@ namespace ts { } if (includeJsDoc && hasJSDocNodes(node)) { - return getTokenPosOfNode(node.jsDoc[0]); + return getTokenPosOfNode(node.jsDoc![0]); } // For a syntax list, it is possible that one of its children has JSDocComment nodes, while @@ -343,9 +345,9 @@ namespace ts { /** * Gets flags that control emit behavior of a node. */ - export function getEmitFlags(node: Node): EmitFlags | undefined { + export function getEmitFlags(node: Node): EmitFlags { const emitNode = node.emitNode; - return emitNode && emitNode.flags; + return emitNode && emitNode.flags || 0; } export function getLiteralText(node: LiteralLikeNode, sourceFile: SourceFile) { @@ -382,7 +384,7 @@ namespace ts { return node.text; } - Debug.fail(`Literal kind '${node.kind}' not accounted for.`); + return Debug.fail(`Literal kind '${node.kind}' not accounted for.`); } export function getTextOfConstantValue(value: string | number) { @@ -471,7 +473,7 @@ namespace ts { return isExternalModule(node) || compilerOptions.isolatedModules || ((getEmitModuleKind(compilerOptions) === ModuleKind.CommonJS) && !!node.commonJsModuleIndicator); } - export function isBlockScope(node: Node, parentNode: Node) { + export function isBlockScope(node: Node, parentNode: Node): boolean { switch (node.kind) { case SyntaxKind.SourceFile: case SyntaxKind.CaseBlock: @@ -492,7 +494,7 @@ namespace ts { case SyntaxKind.Block: // function block is not considered block-scope container // see comment in binder.ts: bind(...), case for SyntaxKind.Block - return parentNode && !isFunctionLike(parentNode); + return !isFunctionLike(parentNode); } return false; @@ -564,7 +566,7 @@ namespace ts { // Gets the nearest enclosing block scope container that has the provided node // as a descendant, that is not the provided node. export function getEnclosingBlockScopeContainer(node: Node): Node { - return findAncestor(node.parent, current => isBlockScope(current, current.parent)); + return findAncestor(node.parent, current => isBlockScope(current, current.parent))!; } // Return display name of an identifier @@ -586,7 +588,7 @@ namespace ts { case SyntaxKind.NumericLiteral: return escapeLeadingUnderscores(name.text); case SyntaxKind.ComputedPropertyName: - return isStringOrNumericLiteral(name.expression) ? escapeLeadingUnderscores(name.expression.text) : undefined; + return isStringOrNumericLiteral(name.expression) ? escapeLeadingUnderscores(name.expression.text) : undefined!; // TODO: GH#18217 Almost all uses of this assume the result to be defined! default: Debug.assertNever(name); } @@ -600,6 +602,8 @@ namespace ts { return entityNameToString(name.left) + "." + entityNameToString(name.right); case SyntaxKind.PropertyAccessExpression: return entityNameToString(name.expression) + "." + entityNameToString(name.name); + default: + throw Debug.assertNever(name); } } @@ -658,7 +662,7 @@ namespace ts { } export function getErrorSpanForNode(sourceFile: SourceFile, node: Node): TextSpan { - let errorNode = node; + let errorNode: Node | undefined = node; switch (node.kind) { case SyntaxKind.SourceFile: const pos = skipTrivia(sourceFile.text, 0, /*stopAfterLineBreak*/ false); @@ -817,8 +821,8 @@ namespace ts { // falls through case SyntaxKind.QualifiedName: case SyntaxKind.PropertyAccessExpression: - case SyntaxKind.ThisKeyword: - const parent = node.parent; + case SyntaxKind.ThisKeyword: { + const { parent } = node; if (parent.kind === SyntaxKind.TypeQuery) { return false; } @@ -866,6 +870,7 @@ namespace ts { // TODO (drosen): TaggedTemplateExpressions may eventually support type arguments. return false; } + } } return false; @@ -883,11 +888,11 @@ namespace ts { // Warning: This has the same semantics as the forEach family of functions, // in that traversal terminates in the event that 'visitor' supplies a truthy value. - export function forEachReturnStatement(body: Block, visitor: (stmt: ReturnStatement) => T): T { + export function forEachReturnStatement(body: Block, visitor: (stmt: ReturnStatement) => T): T | undefined { return traverse(body); - function traverse(node: Node): T { + function traverse(node: Node): T | undefined { switch (node.kind) { case SyntaxKind.ReturnStatement: return visitor(node); @@ -958,7 +963,7 @@ namespace ts { * * @param node The type node. */ - export function getRestParameterElementType(node: TypeNode) { + export function getRestParameterElementType(node: TypeNode | undefined) { if (node && node.kind === SyntaxKind.ArrayType) { return (node).elementType; } @@ -1008,7 +1013,7 @@ namespace ts { && node.parent.parent.kind === SyntaxKind.VariableStatement; } - export function isValidESSymbolDeclaration(node: Node) { + export function isValidESSymbolDeclaration(node: Node): node is VariableDeclaration | PropertyDeclaration | SignatureDeclaration { return isVariableDeclaration(node) ? isConst(node) && isIdentifier(node.name) && isVariableDeclarationInVariableStatement(node) : isPropertyDeclaration(node) ? hasReadonlyModifier(node) && hasStaticModifier(node) : isPropertySignature(node) && hasReadonlyModifier(node); @@ -1028,7 +1033,7 @@ namespace ts { return false; } - export function unwrapInnermostStatementOfLabel(node: LabeledStatement, beforeUnwrapLabelCallback?: (node: LabeledStatement) => void) { + export function unwrapInnermostStatementOfLabel(node: LabeledStatement, beforeUnwrapLabelCallback?: (node: LabeledStatement) => void): Statement { while (true) { if (beforeUnwrapLabelCallback) { beforeUnwrapLabelCallback(node); @@ -1040,7 +1045,7 @@ namespace ts { } } - export function isFunctionBlock(node: Node) { + export function isFunctionBlock(node: Node): boolean { return node && node.kind === SyntaxKind.Block && isFunctionLike(node.parent); } @@ -1066,15 +1071,16 @@ namespace ts { return filter(objectLiteral.properties, (property): property is PropertyAssignment => { if (property.kind === SyntaxKind.PropertyAssignment) { const propName = getTextOfPropertyName(property.name); - return key === propName || (key2 && key2 === propName); + return key === propName || (!!key2 && key2 === propName); } + return false; }); } - export function getTsConfigObjectLiteralExpression(tsConfigSourceFile: TsConfigSourceFile | undefined) { + export function getTsConfigObjectLiteralExpression(tsConfigSourceFile: TsConfigSourceFile | undefined): ObjectLiteralExpression | undefined { if (tsConfigSourceFile && tsConfigSourceFile.statements.length) { const expression = tsConfigSourceFile.statements[0].expression; - return isObjectLiteralExpression(expression) && expression; + return tryCast(expression, isObjectLiteralExpression); } } @@ -1087,19 +1093,20 @@ namespace ts { undefined); } - export function getContainingFunction(node: Node): SignatureDeclaration { + export function getContainingFunction(node: Node): SignatureDeclaration | undefined { return findAncestor(node.parent, isFunctionLike); } - export function getContainingClass(node: Node): ClassLikeDeclaration { + export function getContainingClass(node: Node): ClassLikeDeclaration | undefined { return findAncestor(node.parent, isClassLike); } export function getThisContainer(node: Node, includeArrowFunctions: boolean): Node { + Debug.assert(node.kind !== SyntaxKind.SourceFile); while (true) { node = node.parent; if (!node) { - return undefined; + return Debug.fail(); // If we never pass in a SourceFile, this should be unreachable, since we'll stop when we reach that. } switch (node.kind) { case SyntaxKind.ComputedPropertyName: @@ -1219,7 +1226,7 @@ namespace ts { } } - export function getImmediatelyInvokedFunctionExpression(func: Node): CallExpression { + export function getImmediatelyInvokedFunctionExpression(func: Node): CallExpression | undefined { if (func.kind === SyntaxKind.FunctionExpression || func.kind === SyntaxKind.ArrowFunction) { let prev = func; let parent = func.parent; @@ -1251,7 +1258,7 @@ namespace ts { && (node).expression.kind === SyntaxKind.ThisKeyword; } - export function getEntityNameFromTypeNode(node: TypeNode): EntityNameOrEntityNameExpression { + export function getEntityNameFromTypeNode(node: TypeNode): EntityNameOrEntityNameExpression | undefined { switch (node.kind) { case SyntaxKind.TypeReference: return (node).typeName; @@ -1292,22 +1299,22 @@ namespace ts { case SyntaxKind.PropertyDeclaration: // property declarations are valid if their parent is a class declaration. - return parent.kind === SyntaxKind.ClassDeclaration; + return parent!.kind === SyntaxKind.ClassDeclaration; case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: case SyntaxKind.MethodDeclaration: // if this method has a body and its parent is a class declaration, this is a valid target. return (node).body !== undefined - && parent.kind === SyntaxKind.ClassDeclaration; + && parent!.kind === SyntaxKind.ClassDeclaration; case SyntaxKind.Parameter: // if the parameter's parent has a body and its grandparent is a class declaration, this is a valid target; return (parent).body !== undefined - && (parent.kind === SyntaxKind.Constructor - || parent.kind === SyntaxKind.MethodDeclaration - || parent.kind === SyntaxKind.SetAccessor) - && grandparent.kind === SyntaxKind.ClassDeclaration; + && (parent!.kind === SyntaxKind.Constructor + || parent!.kind === SyntaxKind.MethodDeclaration + || parent!.kind === SyntaxKind.SetAccessor) + && grandparent!.kind === SyntaxKind.ClassDeclaration; } return false; @@ -1318,14 +1325,14 @@ namespace ts { export function nodeIsDecorated(node: Node, parent: Node, grandparent: Node): boolean; export function nodeIsDecorated(node: Node, parent?: Node, grandparent?: Node): boolean { return node.decorators !== undefined - && nodeCanBeDecorated(node, parent, grandparent); + && nodeCanBeDecorated(node, parent!, grandparent!); // TODO: GH#18217 } export function nodeOrChildIsDecorated(node: ClassDeclaration): boolean; export function nodeOrChildIsDecorated(node: ClassElement, parent: Node): boolean; export function nodeOrChildIsDecorated(node: Node, parent: Node, grandparent: Node): boolean; export function nodeOrChildIsDecorated(node: Node, parent?: Node, grandparent?: Node): boolean { - return nodeIsDecorated(node, parent, grandparent) || childIsDecorated(node, parent); + return nodeIsDecorated(node, parent!, grandparent!) || childIsDecorated(node, parent!); // TODO: GH#18217 } export function childIsDecorated(node: ClassDeclaration): boolean; @@ -1333,15 +1340,17 @@ namespace ts { export function childIsDecorated(node: Node, parent?: Node): boolean { switch (node.kind) { case SyntaxKind.ClassDeclaration: - return forEach((node).members, m => nodeOrChildIsDecorated(m, node, parent)); + return some((node).members, m => nodeOrChildIsDecorated(m, node, parent!)); // TODO: GH#18217 case SyntaxKind.MethodDeclaration: case SyntaxKind.SetAccessor: - return forEach((node).parameters, p => nodeIsDecorated(p, node, parent)); + return some((node).parameters, p => nodeIsDecorated(p, node, parent!)); // TODO: GH#18217 + default: + return false; } } export function isJSXTagName(node: Node) { - const parent = node.parent; + const { parent } = node; if (parent.kind === SyntaxKind.JsxOpeningElement || parent.kind === SyntaxKind.JsxSelfClosingElement || parent.kind === SyntaxKind.JsxClosingElement) { @@ -1409,7 +1418,7 @@ namespace ts { } export function isInExpressionContext(node: Node): boolean { - const parent = node.parent; + const { parent } = node; switch (parent.kind) { case SyntaxKind.VariableDeclaration: case SyntaxKind.Parameter: @@ -1480,15 +1489,15 @@ namespace ts { } export function isInJavaScriptFile(node: Node | undefined): boolean { - return node && !!(node.flags & NodeFlags.JavaScriptFile); + return !!node && !!(node.flags & NodeFlags.JavaScriptFile); } export function isInJsonFile(node: Node | undefined): boolean { - return node && !!(node.flags & NodeFlags.JsonFile); + return !!node && !!(node.flags & NodeFlags.JsonFile); } export function isInJSDoc(node: Node | undefined): boolean { - return node && !!(node.flags & NodeFlags.JSDoc); + return !!node && !!(node.flags & NodeFlags.JSDoc); } export function isJSDocIndexSignature(node: TypeReferenceNode | ExpressionWithTypeArguments) { @@ -1538,7 +1547,7 @@ namespace ts { * Container-like initializer behave like namespaces, so the binder needs to add contained symbols * to their exports. An example is a function with assignments to `this` inside. */ - export function getJSInitializerSymbol(symbol: Symbol) { + export function getJSInitializerSymbol(symbol: Symbol | undefined) { if (!symbol || !symbol.valueDeclaration) { return symbol; } @@ -1577,7 +1586,7 @@ namespace ts { * * This function returns the provided initializer, or undefined if it is not valid. */ - export function getJavascriptInitializer(initializer: Node, isPrototypeAssignment: boolean): Expression { + export function getJavascriptInitializer(initializer: Node, isPrototypeAssignment: boolean): Expression | undefined { if (isCallExpression(initializer)) { const e = skipParentheses(initializer.expression); return e.kind === SyntaxKind.FunctionExpression || e.kind === SyntaxKind.ArrowFunction ? initializer : undefined; @@ -1744,7 +1753,7 @@ namespace ts { } } - export function getExternalModuleName(node: AnyImportOrReExport | ImportTypeNode): Expression { + export function getExternalModuleName(node: AnyImportOrReExport | ImportTypeNode): Expression | undefined { switch (node.kind) { case SyntaxKind.ImportDeclaration: case SyntaxKind.ExportDeclaration: @@ -1758,7 +1767,7 @@ namespace ts { } } - export function getNamespaceDeclarationNode(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration): ImportEqualsDeclaration | NamespaceImport { + export function getNamespaceDeclarationNode(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration): ImportEqualsDeclaration | NamespaceImport | undefined { switch (node.kind) { case SyntaxKind.ImportDeclaration: return node.importClause && tryCast(node.importClause.namedBindings, isNamespaceImport); @@ -1771,8 +1780,8 @@ namespace ts { } } - export function isDefaultImport(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration) { - return node.kind === SyntaxKind.ImportDeclaration && node.importClause && !!node.importClause.name; + export function isDefaultImport(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration): boolean { + return node.kind === SyntaxKind.ImportDeclaration && !!node.importClause && !!node.importClause.name; } export function hasQuestionToken(node: Node) { @@ -1807,20 +1816,22 @@ namespace ts { return isJSDocTypeAlias(node) || isTypeAliasDeclaration(node); } - function getSourceOfAssignment(node: Node): Node { + function getSourceOfAssignment(node: Node): Node | undefined { return isExpressionStatement(node) && node.expression && isBinaryExpression(node.expression) && - node.expression.operatorToken.kind === SyntaxKind.EqualsToken && - node.expression.right; + node.expression.operatorToken.kind === SyntaxKind.EqualsToken + ? node.expression.right + : undefined; } - function getSourceOfDefaultedAssignment(node: Node): Node { + function getSourceOfDefaultedAssignment(node: Node): Node | undefined { return isExpressionStatement(node) && isBinaryExpression(node.expression) && getSpecialPropertyAssignmentKind(node.expression) !== SpecialPropertyAssignmentKind.None && isBinaryExpression(node.expression.right) && - node.expression.right.operatorToken.kind === SyntaxKind.BarBarToken && - node.expression.right.right; + node.expression.right.operatorToken.kind === SyntaxKind.BarBarToken + ? node.expression.right.right + : undefined; } function getSingleInitializerOfVariableStatementOrPropertyDeclaration(node: Node): Expression | undefined { @@ -1836,16 +1847,15 @@ namespace ts { } function getSingleVariableOfVariableStatement(node: Node): VariableDeclaration | undefined { - return isVariableStatement(node) && - node.declarationList.declarations.length > 0 && - node.declarationList.declarations[0]; + return isVariableStatement(node) ? firstOrUndefined(node.declarationList.declarations) : undefined; } - function getNestedModuleDeclaration(node: Node): Node { - return node.kind === SyntaxKind.ModuleDeclaration && - (node as ModuleDeclaration).body && - (node as ModuleDeclaration).body.kind === SyntaxKind.ModuleDeclaration && - (node as ModuleDeclaration).body; + function getNestedModuleDeclaration(node: Node): Node | undefined { + return isModuleDeclaration(node) && + node.body && + node.body.kind === SyntaxKind.ModuleDeclaration + ? node.body + : undefined; } export function getJSDocCommentsAndTags(hostNode: Node): ReadonlyArray { @@ -1885,8 +1895,8 @@ namespace ts { result = addRange(result, getJSDocParameterTags(node as ParameterDeclaration)); } - if (isVariableLike(node) && hasInitializer(node) && node.initializer !== hostNode && hasJSDocNodes(node.initializer)) { - result = addRange(result, node.initializer.jsDoc); + if (isVariableLike(node) && hasInitializer(node) && node.initializer !== hostNode && hasJSDocNodes(node.initializer!)) { + result = addRange(result, (node.initializer as HasJSDoc).jsDoc); } if (hasJSDocNodes(node)) { @@ -1933,17 +1943,17 @@ namespace ts { export function getTypeParameterFromJsDoc(node: TypeParameterDeclaration & { parent: JSDocTemplateTag }): TypeParameterDeclaration | undefined { const name = node.name.escapedText; const { typeParameters } = (node.parent.parent.parent as SignatureDeclaration | InterfaceDeclaration | ClassDeclaration); - return find(typeParameters, p => p.name.escapedText === name); + return find(typeParameters!, p => p.name.escapedText === name); } export function hasRestParameter(s: SignatureDeclaration | JSDocSignature): boolean { const last = lastOrUndefined(s.parameters); - return last && isRestParameter(last); + return !!last && isRestParameter(last); } export function isRestParameter(node: ParameterDeclaration | JSDocParameterTag): boolean { const type = isJSDocParameterTag(node) ? (node.typeExpression && node.typeExpression.type) : node.type; - return (node as ParameterDeclaration).dotDotDotToken !== undefined || type && type.kind === SyntaxKind.JSDocVariadicType; + return (node as ParameterDeclaration).dotDotDotToken !== undefined || !!type && type.kind === SyntaxKind.JSDocVariadicType; } export const enum AssignmentKind { @@ -2108,9 +2118,10 @@ namespace ts { switch (name.kind) { case SyntaxKind.Identifier: case SyntaxKind.StringLiteral: - case SyntaxKind.NumericLiteral: - if (isDeclaration(name.parent)) { - return name.parent.name === name; + case SyntaxKind.NumericLiteral: { + const parent = name.parent; + if (isDeclaration(parent)) { + return parent.name === name; } else if (isQualifiedName(name.parent)) { const tag = name.parent.parent; @@ -2120,6 +2131,7 @@ namespace ts { const binExp = name.parent.parent; return isBinaryExpression(binExp) && getSpecialPropertyAssignmentKind(binExp) !== SpecialPropertyAssignmentKind.None && getNameOfDeclaration(binExp) === name; } + } default: return false; } @@ -2213,7 +2225,7 @@ namespace ts { return heritageClause ? heritageClause.types : undefined; } - export function getHeritageClause(clauses: NodeArray, kind: SyntaxKind) { + export function getHeritageClause(clauses: NodeArray | undefined, kind: SyntaxKind) { if (clauses) { for (const clause of clauses) { if (clause.token === kind) { @@ -2333,7 +2345,7 @@ namespace ts { */ export function hasDynamicName(declaration: Declaration): declaration is DynamicNamedDeclaration { const name = getNameOfDeclaration(declaration); - return name && isDynamicName(name); + return !!name && isDynamicName(name); } export function isDynamicName(name: DeclarationName): boolean { @@ -2351,7 +2363,7 @@ namespace ts { return isPropertyAccessExpression(node) && isESSymbolIdentifier(node.expression); } - export function getPropertyNameForPropertyNameNode(name: DeclarationName): __String { + export function getPropertyNameForPropertyNameNode(name: DeclarationName): __String | undefined { if (name.kind === SyntaxKind.Identifier) { return name.escapedText; } @@ -2643,8 +2655,8 @@ namespace ts { } export function createDiagnosticCollection(): DiagnosticCollection { - let nonFileDiagnostics = [] as SortedArray; - const filesWithDiagnostics = [] as SortedArray; + let nonFileDiagnostics = [] as Diagnostic[] as SortedArray; // See GH#19873 + const filesWithDiagnostics = [] as string[] as SortedArray; const fileDiagnostics = createMap>(); let hasReadNonFileDiagnostics = false; @@ -2660,11 +2672,11 @@ namespace ts { } function add(diagnostic: Diagnostic): void { - let diagnostics: SortedArray; + let diagnostics: SortedArray | undefined; if (diagnostic.file) { diagnostics = fileDiagnostics.get(diagnostic.file.fileName); if (!diagnostics) { - diagnostics = [] as SortedArray; + diagnostics = [] as Diagnostic[] as SortedArray; // See GH#19873 fileDiagnostics.set(diagnostic.file.fileName, diagnostics as SortedArray); insertSorted(filesWithDiagnostics, diagnostic.file.fileName, compareStringsCaseSensitive); } @@ -2826,7 +2838,7 @@ namespace ts { const lineStartsOfS = computeLineStarts(s); if (lineStartsOfS.length > 1) { lineCount = lineCount + lineStartsOfS.length - 1; - linePos = output.length - s.length + lastOrUndefined(lineStartsOfS); + linePos = output.length - s.length + last(lineStartsOfS); } } } @@ -2880,7 +2892,7 @@ namespace ts { return file.moduleName || getExternalModuleNameFromPath(host, file.fileName, referenceFile && referenceFile.fileName); } - export function getExternalModuleNameFromDeclaration(host: ModuleNameResolverHost, resolver: EmitResolver, declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration | ImportTypeNode): string { + export function getExternalModuleNameFromDeclaration(host: ModuleNameResolverHost, resolver: EmitResolver, declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration | ImportTypeNode): string | undefined { const file = resolver.getExternalModuleFileFromDeclaration(declaration); if (!file || file.isDeclarationFile) { return undefined; @@ -2983,7 +2995,7 @@ namespace ts { return computeLineAndCharacterOfPosition(lineMap, pos).line; } - export function getFirstConstructorWithBody(node: ClassLikeDeclaration): ConstructorDeclaration { + export function getFirstConstructorWithBody(node: ClassLikeDeclaration): ConstructorDeclaration | undefined { return find(node.members, (member): member is ConstructorDeclaration => isConstructorDeclaration(member) && nodeIsPresent(member.body)); } @@ -2995,7 +3007,7 @@ namespace ts { } /** Get the type annotation for the value parameter. */ - export function getSetAccessorTypeAnnotationNode(accessor: SetAccessorDeclaration): TypeNode { + export function getSetAccessorTypeAnnotationNode(accessor: SetAccessorDeclaration): TypeNode | undefined { const parameter = getSetAccessorValueParameter(accessor); return parameter && parameter.type; } @@ -3015,7 +3027,7 @@ namespace ts { } export function isThisIdentifier(node: Node | undefined): boolean { - return node && node.kind === SyntaxKind.Identifier && identifierIsThisKeyword(node as Identifier); + return !!node && node.kind === SyntaxKind.Identifier && identifierIsThisKeyword(node as Identifier); } export function identifierIsThisKeyword(id: Identifier): boolean { @@ -3023,10 +3035,11 @@ namespace ts { } export function getAllAccessorDeclarations(declarations: NodeArray, accessor: AccessorDeclaration): AllAccessorDeclarations { - let firstAccessor: AccessorDeclaration; - let secondAccessor: AccessorDeclaration; - let getAccessor: AccessorDeclaration; - let setAccessor: AccessorDeclaration; + // TODO: GH#18217 + let firstAccessor!: AccessorDeclaration; + let secondAccessor!: AccessorDeclaration; + let getAccessor!: AccessorDeclaration; + let setAccessor!: AccessorDeclaration; if (hasDynamicName(accessor)) { firstAccessor = accessor; if (accessor.kind === SyntaxKind.GetAccessor) { @@ -3043,7 +3056,7 @@ namespace ts { forEach(declarations, (member: Declaration) => { if ((member.kind === SyntaxKind.GetAccessor || member.kind === SyntaxKind.SetAccessor) && hasModifier(member, ModifierFlags.Static) === hasModifier(accessor, ModifierFlags.Static)) { - const memberName = getPropertyNameForPropertyNameNode((member as NamedDeclaration).name); + const memberName = getPropertyNameForPropertyNameNode((member as NamedDeclaration).name!); const accessorName = getPropertyNameForPropertyNameNode(accessor.name); if (memberName === accessorName) { if (!firstAccessor) { @@ -3126,16 +3139,16 @@ namespace ts { * Gets the effective type annotation of the value parameter of a set accessor. If the node * was parsed in a JavaScript file, gets the type annotation from JSDoc. */ - export function getEffectiveSetAccessorTypeAnnotationNode(node: SetAccessorDeclaration): TypeNode { + export function getEffectiveSetAccessorTypeAnnotationNode(node: SetAccessorDeclaration): TypeNode | undefined { const parameter = getSetAccessorValueParameter(node); return parameter && getEffectiveTypeAnnotationNode(parameter); } - export function emitNewLineBeforeLeadingComments(lineMap: ReadonlyArray, writer: EmitTextWriter, node: TextRange, leadingComments: ReadonlyArray) { + export function emitNewLineBeforeLeadingComments(lineMap: ReadonlyArray, writer: EmitTextWriter, node: TextRange, leadingComments: ReadonlyArray | undefined) { emitNewLineBeforeLeadingCommentsOfPosition(lineMap, writer, node.pos, leadingComments); } - export function emitNewLineBeforeLeadingCommentsOfPosition(lineMap: ReadonlyArray, writer: EmitTextWriter, pos: number, leadingComments: ReadonlyArray) { + export function emitNewLineBeforeLeadingCommentsOfPosition(lineMap: ReadonlyArray, writer: EmitTextWriter, pos: number, leadingComments: ReadonlyArray | undefined) { // If the leading comments start on different line than the start of node, write new line if (leadingComments && leadingComments.length && pos !== leadingComments[0].pos && getLineOfLocalPositionFromLineMap(lineMap, pos) !== getLineOfLocalPositionFromLineMap(lineMap, leadingComments[0].pos)) { @@ -3155,7 +3168,7 @@ namespace ts { text: string, lineMap: ReadonlyArray, writer: EmitTextWriter, - comments: ReadonlyArray, + comments: ReadonlyArray | undefined, leadingSeparator: boolean, trailingSeparator: boolean, newLine: string, @@ -3194,8 +3207,8 @@ namespace ts { export function emitDetachedComments(text: string, lineMap: ReadonlyArray, writer: EmitTextWriter, writeComment: (text: string, lineMap: ReadonlyArray, writer: EmitTextWriter, commentPos: number, commentEnd: number, newLine: string) => void, node: TextRange, newLine: string, removeComments: boolean) { - let leadingComments: CommentRange[]; - let currentDetachedCommentInfo: { nodePos: number, detachedCommentEndPos: number }; + let leadingComments: CommentRange[] | undefined; + let currentDetachedCommentInfo: { nodePos: number, detachedCommentEndPos: number } | undefined; if (removeComments) { // removeComments is true, only reserve pinned comment at the top of file // For example: @@ -3213,7 +3226,7 @@ namespace ts { if (leadingComments) { const detachedComments: CommentRange[] = []; - let lastComment: CommentRange; + let lastComment: CommentRange | undefined; for (const comment of leadingComments) { if (lastComment) { @@ -3236,13 +3249,13 @@ namespace ts { // All comments look like they could have been part of the copyright header. Make // sure there is at least one blank line between it and the node. If not, it's not // a copyright header. - const lastCommentLine = getLineOfLocalPositionFromLineMap(lineMap, lastOrUndefined(detachedComments).end); + const lastCommentLine = getLineOfLocalPositionFromLineMap(lineMap, last(detachedComments).end); const nodeLine = getLineOfLocalPositionFromLineMap(lineMap, skipTrivia(text, node.pos)); if (nodeLine >= lastCommentLine + 2) { // Valid detachedComments emitNewLineBeforeLeadingComments(lineMap, writer, node, leadingComments); emitComments(text, lineMap, writer, detachedComments, /*leadingSeparator*/ false, /*trailingSeparator*/ true, newLine, writeComment); - currentDetachedCommentInfo = { nodePos: node.pos, detachedCommentEndPos: lastOrUndefined(detachedComments).end }; + currentDetachedCommentInfo = { nodePos: node.pos, detachedCommentEndPos: last(detachedComments).end }; } } } @@ -3259,7 +3272,7 @@ namespace ts { if (text.charCodeAt(commentPos + 1) === CharacterCodes.asterisk) { const firstCommentLineAndCharacter = computeLineAndCharacterOfPosition(lineMap, commentPos); const lineCount = lineMap.length; - let firstCommentLineIndent: number; + let firstCommentLineIndent: number | undefined; for (let pos = commentPos, currentLine = firstCommentLineAndCharacter.line; pos < commentEnd; currentLine++) { const nextLineStart = (currentLine + 1) === lineCount ? text.length + 1 @@ -3373,8 +3386,8 @@ namespace ts { } export function getModifierFlags(node: Node): ModifierFlags { - if (node.modifierFlagsCache & ModifierFlags.HasComputedFlags) { - return node.modifierFlagsCache & ~ModifierFlags.HasComputedFlags; + if (node.modifierFlagsCache! & ModifierFlags.HasComputedFlags) { + return node.modifierFlagsCache! & ~ModifierFlags.HasComputedFlags; } const flags = getModifierFlagsNoCache(node); @@ -3427,8 +3440,8 @@ namespace ts { /** Get `C` given `N` if `N` is in the position `class C extends N` where `N` is an ExpressionWithTypeArguments. */ export function tryGetClassExtendingExpressionWithTypeArguments(node: Node): ClassLikeDeclaration | undefined { - if (node.kind === SyntaxKind.ExpressionWithTypeArguments && - (node.parent).token === SyntaxKind.ExtendsKeyword && + if (isExpressionWithTypeArguments(node) && + node.parent.token === SyntaxKind.ExtendsKeyword && isClassLike(node.parent.parent)) { return node.parent.parent; } @@ -3714,31 +3727,31 @@ namespace ts { return stableSort<[number, string]>(result, (x, y) => compareValues(x[0], y[0])); } - export function formatSyntaxKind(kind: SyntaxKind): string { + export function formatSyntaxKind(kind: SyntaxKind | undefined): string { return formatEnum(kind, (ts).SyntaxKind, /*isFlags*/ false); } - export function formatModifierFlags(flags: ModifierFlags): string { + export function formatModifierFlags(flags: ModifierFlags | undefined): string { return formatEnum(flags, (ts).ModifierFlags, /*isFlags*/ true); } - export function formatTransformFlags(flags: TransformFlags): string { + export function formatTransformFlags(flags: TransformFlags | undefined): string { return formatEnum(flags, (ts).TransformFlags, /*isFlags*/ true); } - export function formatEmitFlags(flags: EmitFlags): string { + export function formatEmitFlags(flags: EmitFlags | undefined): string { return formatEnum(flags, (ts).EmitFlags, /*isFlags*/ true); } - export function formatSymbolFlags(flags: SymbolFlags): string { + export function formatSymbolFlags(flags: SymbolFlags | undefined): string { return formatEnum(flags, (ts).SymbolFlags, /*isFlags*/ true); } - export function formatTypeFlags(flags: TypeFlags): string { + export function formatTypeFlags(flags: TypeFlags | undefined): string { return formatEnum(flags, (ts).TypeFlags, /*isFlags*/ true); } - export function formatObjectFlags(flags: ObjectFlags): string { + export function formatObjectFlags(flags: ObjectFlags | undefined): string { return formatEnum(flags, (ts).ObjectFlags, /*isFlags*/ true); } @@ -3806,7 +3819,7 @@ namespace ts { * @param token The token. */ export function createTokenRange(pos: number, token: SyntaxKind): TextRange { - return createRange(pos, pos + tokenToString(token).length); + return createRange(pos, pos + tokenToString(token)!.length); } export function rangeIsOnSingleLine(range: TextRange, sourceFile: SourceFile) { @@ -4055,7 +4068,7 @@ namespace ts { return !!forEachAncestorDirectory(directory, d => callback(d) ? true : undefined); } - export function isUMDExportSymbol(symbol: Symbol) { + export function isUMDExportSymbol(symbol: Symbol | undefined) { return symbol && symbol.declarations && symbol.declarations[0] && isNamespaceExportDeclaration(symbol.declarations[0]); } @@ -4135,7 +4148,7 @@ namespace ts { return textSpanOverlap(span, other) !== undefined; } - export function textSpanOverlap(span1: TextSpan, span2: TextSpan) { + export function textSpanOverlap(span1: TextSpan, span2: TextSpan): TextSpan | undefined { const overlap = textSpanIntersection(span1, span2); return overlap && overlap.length === 0 ? undefined : overlap; } @@ -4158,7 +4171,7 @@ namespace ts { return position <= textSpanEnd(span) && position >= span.start; } - export function textSpanIntersection(span1: TextSpan, span2: TextSpan) { + export function textSpanIntersection(span1: TextSpan, span2: TextSpan): TextSpan | undefined { const start = Math.max(span1.start, span2.start); const end = Math.min(textSpanEnd(span1), textSpanEnd(span2)); return start <= end ? createTextSpanFromBounds(start, end) : undefined; @@ -4327,7 +4340,7 @@ namespace ts { return createTextChangeRange(createTextSpanFromBounds(oldStartN, oldEndN), /*newLength*/ newEndN - oldStartN); } - export function getTypeParameterOwner(d: Declaration): Declaration { + export function getTypeParameterOwner(d: Declaration): Declaration | undefined { if (d && d.kind === SyntaxKind.TypeParameter) { for (let current: Node = d; current; current = current.parent) { if (isFunctionLike(current) || isClassLike(current) || current.kind === SyntaxKind.InterfaceDeclaration) { @@ -4439,7 +4452,7 @@ namespace ts { // Set the UI locale for string collation setUILocale(locale); - function trySetLanguageAndTerritory(language: string, territory: string, errors?: Push): boolean { + function trySetLanguageAndTerritory(language: string, territory: string | undefined, errors?: Push): boolean { const compilerFilePath = normalizePath(sys.getExecutingFilePath()); const containingDirectoryPath = getDirectoryPath(compilerFilePath); @@ -4456,7 +4469,7 @@ namespace ts { } // TODO: Add codePage support for readFile? - let fileContents = ""; + let fileContents: string | undefined = ""; try { fileContents = sys.readFile(filePath); } @@ -4468,9 +4481,9 @@ namespace ts { } try { // tslint:disable-next-line no-unnecessary-qualifier (making clear this is a global mutation!) - ts.localizedDiagnosticMessages = JSON.parse(fileContents); + ts.localizedDiagnosticMessages = JSON.parse(fileContents!); } - catch (e) { + catch { if (errors) { errors.push(createCompilerDiagnostic(Diagnostics.Corrupted_locale_file_0, filePath)); } @@ -4483,7 +4496,9 @@ namespace ts { export function getOriginalNode(node: Node): Node; export function getOriginalNode(node: Node, nodeTest: (node: Node) => node is T): T; - export function getOriginalNode(node: Node, nodeTest?: (node: Node) => boolean): Node { + export function getOriginalNode(node: Node | undefined): Node | undefined; + export function getOriginalNode(node: Node | undefined, nodeTest: (node: Node | undefined) => node is T): T | undefined; + export function getOriginalNode(node: Node | undefined, nodeTest?: (node: Node | undefined) => boolean): Node | undefined { if (node) { while (node.original !== undefined) { node = node.original; @@ -4517,8 +4532,8 @@ namespace ts { * @param nodeTest A callback used to ensure the correct type of parse tree node is returned. * @returns The original parse tree node if found; otherwise, undefined. */ - export function getParseTreeNode(node: Node, nodeTest?: (node: Node) => node is T): T; - export function getParseTreeNode(node: Node, nodeTest?: (node: Node) => boolean): Node { + export function getParseTreeNode(node: Node | undefined, nodeTest?: (node: Node) => node is T): T | undefined; + export function getParseTreeNode(node: Node | undefined, nodeTest?: (node: Node) => boolean): Node | undefined { if (node === undefined || isParseTreeNode(node)) { return node; } @@ -4609,7 +4624,7 @@ namespace ts { } } - function getDeclarationIdentifier(node: Declaration | Expression) { + function getDeclarationIdentifier(node: Declaration | Expression): Identifier | undefined { const name = getNameOfDeclaration(node); return isIdentifier(name) ? name : undefined; } @@ -4623,15 +4638,16 @@ namespace ts { return !!(node as NamedDeclaration).name; // A 'name' property should always be a DeclarationName. } - export function getNameOfDeclaration(declaration: Declaration | Expression): DeclarationName | undefined { + // TODO: GH#18217 This is often used as if it returns a defined result + export function getNameOfDeclaration(declaration: Declaration | Expression): DeclarationName { if (!declaration) { - return undefined; + return undefined!; } switch (declaration.kind) { case SyntaxKind.ClassExpression: case SyntaxKind.FunctionExpression: if (!(declaration as ClassExpression | FunctionExpression).name) { - return getAssignedName(declaration); + return getAssignedName(declaration)!; } break; case SyntaxKind.Identifier: @@ -4653,22 +4669,22 @@ namespace ts { case SpecialPropertyAssignmentKind.PrototypeProperty: return (expr.left as PropertyAccessExpression).name; default: - return undefined; + return undefined!; } } case SyntaxKind.JSDocCallbackTag: - return (declaration as JSDocCallbackTag).name; + return (declaration as JSDocCallbackTag).name!; case SyntaxKind.JSDocTypedefTag: - return getNameOfJSDocTypedef(declaration as JSDocTypedefTag); + return getNameOfJSDocTypedef(declaration as JSDocTypedefTag)!; case SyntaxKind.ExportAssignment: { const { expression } = declaration as ExportAssignment; - return isIdentifier(expression) ? expression : undefined; + return isIdentifier(expression) ? expression : undefined!; } } - return (declaration as NamedDeclaration).name; + return (declaration as NamedDeclaration).name!; } - function getAssignedName(node: Node): DeclarationName { + function getAssignedName(node: Node): DeclarationName | undefined { if (!node.parent) { return undefined; } @@ -5573,8 +5589,7 @@ namespace ts { /* @internal */ export function isGeneratedIdentifier(node: Node): node is GeneratedIdentifier { - // Using `>` here catches both `GeneratedIdentifierKind.None` and `undefined`. - return isIdentifier(node) && (node.autoGenerateFlags & GeneratedIdentifierFlags.KindMask) > GeneratedIdentifierFlags.None; + return isIdentifier(node) && (node.autoGenerateFlags! & GeneratedIdentifierFlags.KindMask) > GeneratedIdentifierFlags.None; } // Keywords @@ -5785,7 +5800,7 @@ namespace ts { // Binding patterns /* @internal */ - export function isBindingPattern(node: Node): node is BindingPattern { + export function isBindingPattern(node: Node | undefined): node is BindingPattern { if (node) { const kind = node.kind; return kind === SyntaxKind.ArrayBindingPattern @@ -6303,8 +6318,10 @@ namespace ts { /** True if has jsdoc nodes attached to it. */ /* @internal */ + // TODO: GH#19856 Would like to return `node is Node & { jsDoc: JSDoc[] }` but it causes long compile times export function hasJSDocNodes(node: Node): node is HasJSDoc { - return !!(node as JSDocContainer).jsDoc && (node as JSDocContainer).jsDoc.length > 0; + const { jsDoc } = node as JSDocContainer; + return !!jsDoc && jsDoc.length > 0; } /** True if has type node attached to it. */ diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index 6c1864cd627e5..1b9853e9f860e 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -9,7 +9,7 @@ namespace ts { * @param test A callback to execute to verify the Node is valid. * @param lift An optional callback to execute to lift a NodeArray into a valid Node. */ - export function visitNode(node: T, visitor: Visitor, test?: (node: Node) => boolean, lift?: (node: NodeArray) => T): T; + export function visitNode(node: T | undefined, visitor: Visitor | undefined, test?: (node: Node) => boolean, lift?: (node: NodeArray) => T): T; /** * Visits a Node using the supplied visitor, possibly returning a new Node in its place. @@ -19,9 +19,9 @@ namespace ts { * @param test A callback to execute to verify the Node is valid. * @param lift An optional callback to execute to lift a NodeArray into a valid Node. */ - export function visitNode(node: T | undefined, visitor: Visitor, test?: (node: Node) => boolean, lift?: (node: NodeArray) => T): T | undefined; + export function visitNode(node: T | undefined, visitor: Visitor | undefined, test?: (node: Node) => boolean, lift?: (node: NodeArray) => T): T | undefined; - export function visitNode(node: T | undefined, visitor: Visitor, test?: (node: Node) => boolean, lift?: (node: NodeArray) => T): T | undefined { + export function visitNode(node: T | undefined, visitor: Visitor | undefined, test?: (node: Node) => boolean, lift?: (node: NodeArray) => T): T | undefined { if (node === undefined || visitor === undefined) { return node; } @@ -32,7 +32,7 @@ namespace ts { return node; } - let visitedNode: Node; + let visitedNode: Node | undefined; if (visited === undefined) { return undefined; } @@ -44,7 +44,7 @@ namespace ts { } Debug.assertNode(visitedNode, test); - aggregateTransformFlags(visitedNode); + aggregateTransformFlags(visitedNode!); return visitedNode; } @@ -57,7 +57,7 @@ namespace ts { * @param start An optional value indicating the starting offset at which to start visiting. * @param count An optional value indicating the maximum number of nodes to visit. */ - export function visitNodes(nodes: NodeArray, visitor: Visitor, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray; + export function visitNodes(nodes: NodeArray | undefined, visitor: Visitor, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray; /** * Visits a NodeArray using the supplied visitor, possibly returning a new NodeArray in its place. @@ -84,7 +84,7 @@ namespace ts { return nodes; } - let updated: MutableNodeArray; + let updated: MutableNodeArray | undefined; // Ensure start and count have valid values const length = nodes.length; @@ -152,7 +152,7 @@ namespace ts { * Starts a new lexical environment and visits a parameter list, suspending the lexical * environment upon completion. */ - export function visitParameterList(nodes: NodeArray, visitor: Visitor, context: TransformationContext, nodesVisitor = visitNodes) { + export function visitParameterList(nodes: NodeArray | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor = visitNodes) { context.startLexicalEnvironment(); const updated = nodesVisitor(nodes, visitor, isParameterDeclaration); context.suspendLexicalEnvironment(); @@ -174,7 +174,7 @@ namespace ts { * environment and merging hoisted declarations upon completion. */ export function visitFunctionBody(node: ConciseBody, visitor: Visitor, context: TransformationContext): ConciseBody; - export function visitFunctionBody(node: ConciseBody, visitor: Visitor, context: TransformationContext): ConciseBody { + export function visitFunctionBody(node: ConciseBody | undefined, visitor: Visitor, context: TransformationContext): ConciseBody | undefined { context.resumeLexicalEnvironment(); const updated = visitNode(node, visitor, isConciseBody); const declarations = context.endLexicalEnvironment(); @@ -204,7 +204,7 @@ namespace ts { */ export function visitEachChild(node: T | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: typeof visitNodes, tokenVisitor?: Visitor): T | undefined; - export function visitEachChild(node: Node, visitor: Visitor, context: TransformationContext, nodesVisitor = visitNodes, tokenVisitor?: Visitor): Node { + export function visitEachChild(node: Node | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor = visitNodes, tokenVisitor?: Visitor): Node | undefined { if (node === undefined) { return undefined; } @@ -290,14 +290,14 @@ namespace ts { nodesVisitor((node).typeParameters, visitor, isTypeParameterDeclaration), visitParameterList((node).parameters, visitor, context, nodesVisitor), visitNode((node).type, visitor, isTypeNode), - visitFunctionBody((node).body, visitor, context)); + visitFunctionBody((node).body!, visitor, context)); case SyntaxKind.Constructor: return updateConstructor(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitParameterList((node).parameters, visitor, context, nodesVisitor), - visitFunctionBody((node).body, visitor, context)); + visitFunctionBody((node).body!, visitor, context)); case SyntaxKind.GetAccessor: return updateGetAccessor(node, @@ -306,7 +306,7 @@ namespace ts { visitNode((node).name, visitor, isPropertyName), visitParameterList((node).parameters, visitor, context, nodesVisitor), visitNode((node).type, visitor, isTypeNode), - visitFunctionBody((node).body, visitor, context)); + visitFunctionBody((node).body!, visitor, context)); case SyntaxKind.SetAccessor: return updateSetAccessor(node, @@ -314,7 +314,7 @@ namespace ts { nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).name, visitor, isPropertyName), visitParameterList((node).parameters, visitor, context, nodesVisitor), - visitFunctionBody((node).body, visitor, context)); + visitFunctionBody((node).body!, visitor, context)); case SyntaxKind.CallSignature: return updateCallSignature(node, @@ -333,7 +333,7 @@ namespace ts { nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), nodesVisitor((node).parameters, visitor, isParameterDeclaration), - visitNode((node).type, visitor, isTypeNode)); + visitNode((node).type!, visitor, isTypeNode)); // Types @@ -555,7 +555,7 @@ namespace ts { case SyntaxKind.YieldExpression: return updateYield(node, visitNode((node).asteriskToken, tokenVisitor, isToken), - visitNode((node).expression, visitor, isExpression)); + visitNode((node).expression!, visitor, isExpression)); case SyntaxKind.SpreadElement: return updateSpread(node, @@ -674,7 +674,7 @@ namespace ts { case SyntaxKind.ThrowStatement: return updateThrow(node, - visitNode((node).expression, visitor, isExpression)); + visitNode((node).expression!, visitor, isExpression)); case SyntaxKind.TryStatement: return updateTry(node, @@ -848,7 +848,7 @@ namespace ts { case SyntaxKind.JsxAttribute: return updateJsxAttribute(node, visitNode((node).name, visitor, isIdentifier), - visitNode((node).initializer, visitor, isStringLiteralOrJsxExpression)); + visitNode((node).initializer!, visitor, isStringLiteralOrJsxExpression)); case SyntaxKind.JsxAttributes: return updateJsxAttributes(node, @@ -930,7 +930,7 @@ namespace ts { * * @param nodes The NodeArray. */ - function extractSingleNode(nodes: ReadonlyArray): Node { + function extractSingleNode(nodes: ReadonlyArray): Node | undefined { Debug.assert(nodes.length <= 1, "Too many nodes written to output."); return singleOrUndefined(nodes); } @@ -938,11 +938,11 @@ namespace ts { /* @internal */ namespace ts { - function reduceNode(node: Node, f: (memo: T, node: Node) => T, initial: T) { + function reduceNode(node: Node | undefined, f: (memo: T, node: Node) => T, initial: T) { return node ? f(initial, node) : initial; } - function reduceNodeArray(nodes: NodeArray, f: (memo: T, nodes: NodeArray) => T, initial: T) { + function reduceNodeArray(nodes: NodeArray | undefined, f: (memo: T, nodes: NodeArray) => T, initial: T) { return nodes ? f(initial, nodes) : initial; } @@ -954,12 +954,12 @@ namespace ts { * @param initial The initial value to supply to the reduction. * @param f The callback function */ - export function reduceEachChild(node: Node, initial: T, cbNode: (memo: T, node: Node) => T, cbNodeArray?: (memo: T, nodes: NodeArray) => T): T { + export function reduceEachChild(node: Node | undefined, initial: T, cbNode: (memo: T, node: Node) => T, cbNodeArray?: (memo: T, nodes: NodeArray) => T): T { if (node === undefined) { return initial; } - const reduceNodes: (nodes: NodeArray, f: ((memo: T, node: Node) => T) | ((memo: T, node: NodeArray) => T), initial: T) => T = cbNodeArray ? reduceNodeArray : reduceLeft; + const reduceNodes: (nodes: NodeArray | undefined, f: ((memo: T, node: Node) => T) | ((memo: T, node: NodeArray) => T), initial: T) => T = cbNodeArray ? reduceNodeArray : reduceLeft; const cbNodes = cbNodeArray || cbNode; const kind = node.kind; @@ -1456,13 +1456,13 @@ namespace ts { /** * Merges generated lexical declarations into a new statement list. */ - export function mergeLexicalEnvironment(statements: NodeArray, declarations: ReadonlyArray): NodeArray; + export function mergeLexicalEnvironment(statements: NodeArray, declarations: ReadonlyArray | undefined): NodeArray; /** * Appends generated lexical declarations to an array of statements. */ - export function mergeLexicalEnvironment(statements: Statement[], declarations: ReadonlyArray): Statement[]; - export function mergeLexicalEnvironment(statements: Statement[] | NodeArray, declarations: ReadonlyArray) { + export function mergeLexicalEnvironment(statements: Statement[], declarations: ReadonlyArray | undefined): Statement[]; + export function mergeLexicalEnvironment(statements: Statement[] | NodeArray, declarations: ReadonlyArray | undefined) { if (!some(declarations)) { return statements; } @@ -1566,10 +1566,10 @@ namespace ts { : noop; export const assertNode = shouldAssert(AssertionLevel.Normal) - ? (node: Node, test: (node: Node) => boolean, message?: string): void => assert( + ? (node: Node | undefined, test: ((node: Node | undefined) => boolean) | undefined, message?: string): void => assert( test === undefined || test(node), message || "Unexpected node.", - () => `Node ${formatSyntaxKind(node.kind)} did not pass test '${getFunctionName(test)}'.`, + () => `Node ${formatSyntaxKind(node!.kind)} did not pass test '${getFunctionName(test!)}'.`, assertNode) : noop; diff --git a/src/compiler/watch.ts b/src/compiler/watch.ts index 3c5646cc48bff..e869dfc966cfb 100644 --- a/src/compiler/watch.ts +++ b/src/compiler/watch.ts @@ -4,7 +4,7 @@ namespace ts { getCurrentDirectory: () => sys.getCurrentDirectory(), getNewLine: () => sys.newLine, getCanonicalFileName: createGetCanonicalFileName(sys.useCaseSensitiveFileNames) - } : undefined; + } : undefined!; // TODO: GH#18217 /** * Create a function that reports error by writing to the system and handles the formating of the diagnostic @@ -23,7 +23,7 @@ namespace ts { return diagnostic => { diagnostics[0] = diagnostic; system.write(formatDiagnosticsWithColorAndContext(diagnostics, host) + host.getNewLine()); - diagnostics[0] = undefined; + diagnostics[0] = undefined!; // TODO: GH#18217 }; } @@ -91,7 +91,7 @@ namespace ts { const host: ParseConfigFileHost = system; host.onUnRecoverableConfigFileDiagnostic = diagnostic => reportUnrecoverableDiagnostic(sys, reportDiagnostic, diagnostic); const result = getParsedCommandLineOfConfigFile(configFileName, optionsToExtend, host); - host.onUnRecoverableConfigFileDiagnostic = undefined; + host.onUnRecoverableConfigFileDiagnostic = undefined!; // TODO: GH#18217 return result; } @@ -177,9 +177,9 @@ namespace ts { /** * Creates the watch compiler host that can be extended with config file or root file names and options host */ - function createWatchCompilerHost(system = sys, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHost { + function createWatchCompilerHost(system = sys, createProgram: CreateProgram | undefined, reportDiagnostic: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHost { if (!createProgram) { - createProgram = createEmitAndSemanticDiagnosticsBuilderProgram as any; + createProgram = createEmitAndSemanticDiagnosticsBuilderProgram as any as CreateProgram; } let host: DirectoryStructureHost = system; @@ -197,18 +197,18 @@ namespace ts { directoryExists: path => system.directoryExists(path), getDirectories: path => system.getDirectories(path), readDirectory: (path, extensions, exclude, include, depth) => system.readDirectory(path, extensions, exclude, include, depth), - realpath: system.realpath && (path => system.realpath(path)), + realpath: system.realpath && (path => system.realpath!(path)), getEnvironmentVariable: system.getEnvironmentVariable && (name => system.getEnvironmentVariable(name)), - watchFile: system.watchFile ? ((path, callback, pollingInterval) => system.watchFile(path, callback, pollingInterval)) : () => noopFileWatcher, - watchDirectory: system.watchDirectory ? ((path, callback, recursive) => system.watchDirectory(path, callback, recursive)) : () => noopFileWatcher, - setTimeout: system.setTimeout ? ((callback, ms, ...args: any[]) => system.setTimeout.call(system, callback, ms, ...args)) : noop, - clearTimeout: system.clearTimeout ? (timeoutId => system.clearTimeout(timeoutId)) : noop, + watchFile: system.watchFile ? ((path, callback, pollingInterval) => system.watchFile!(path, callback, pollingInterval)) : () => noopFileWatcher, + watchDirectory: system.watchDirectory ? ((path, callback, recursive) => system.watchDirectory!(path, callback, recursive)) : () => noopFileWatcher, + setTimeout: system.setTimeout ? ((callback, ms, ...args: any[]) => system.setTimeout!.call(system, callback, ms, ...args)) : noop, + clearTimeout: system.clearTimeout ? (timeoutId => system.clearTimeout!(timeoutId)) : noop, trace: s => system.write(s), onWatchStatusChange, createDirectory: path => system.createDirectory(path), writeFile: (path, data, writeByteOrderMark) => system.writeFile(path, data, writeByteOrderMark), onCachedDirectoryStructureHostCreate: cacheHost => host = cacheHost || system, - createHash: system.createHash && (s => system.createHash(s)), + createHash: system.createHash && (s => system.createHash!(s)), createProgram, afterProgramCreate: emitFilesAndReportErrorUsingBuilder }; @@ -246,9 +246,9 @@ namespace ts { * Creates the watch compiler host from system for config file in watch mode */ export function createWatchCompilerHostOfConfigFile(configFileName: string, optionsToExtend: CompilerOptions | undefined, system: System, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHostOfConfigFile { - reportDiagnostic = reportDiagnostic || createDiagnosticReporter(system); - const host = createWatchCompilerHost(system, createProgram, reportDiagnostic, reportWatchStatus) as WatchCompilerHostOfConfigFile; - host.onUnRecoverableConfigFileDiagnostic = diagnostic => reportUnrecoverableDiagnostic(system, reportDiagnostic, diagnostic); + const diagnosticReporter = reportDiagnostic || createDiagnosticReporter(system); + const host = createWatchCompilerHost(system, createProgram, diagnosticReporter, reportWatchStatus) as WatchCompilerHostOfConfigFile; + host.onUnRecoverableConfigFileDiagnostic = diagnostic => reportUnrecoverableDiagnostic(system, diagnosticReporter, diagnostic); host.configFileName = configFileName; host.optionsToExtend = optionsToExtend; return host; @@ -270,6 +270,8 @@ namespace ts { /** Create the program with rootNames and options, if they are undefined, oldProgram and new configFile diagnostics create new program */ export type CreateProgram = (rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: T, configFileParsingDiagnostics?: ReadonlyArray) => T; export interface WatchCompilerHost { + // TODO: GH#18217 Optional methods are frequently asserted + /** * Used to create the program when need for program creation or recreation detected */ @@ -314,12 +316,12 @@ namespace ts { /** If provided would be used to write log about compilation */ trace?(s: string): void; /** If provided is used to get the environment variable */ - getEnvironmentVariable?(name: string): string; + getEnvironmentVariable?(name: string): string | undefined; /** If provided, used to resolve the module names, otherwise typescript's default module resolution */ resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[]): ResolvedModule[]; /** If provided, used to resolve type reference directives, otherwise typescript's default resolution */ - resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): (ResolvedTypeReferenceDirective | undefined)[]; + resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[]; /** Used to watch changes in source files, missing files needed to update the program or config file */ watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher; @@ -334,6 +336,7 @@ namespace ts { /** Internal interface used to wire emit through same host */ /*@internal*/ export interface WatchCompilerHost { + // TODO: GH#18217 Optional methods are frequently asserted createDirectory?(path: string): void; writeFile?(path: string, data: string, writeByteOrderMark?: boolean): void; onCachedDirectoryStructureHostCreate?(host: CachedDirectoryStructureHost): void; @@ -405,7 +408,7 @@ namespace ts { export function createWatchCompilerHost(configFileName: string, optionsToExtend: CompilerOptions | undefined, system: System, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHostOfConfigFile; export function createWatchCompilerHost(rootFilesOrConfigFileName: string | string[], options: CompilerOptions | undefined, system: System, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHostOfFilesAndCompilerOptions | WatchCompilerHostOfConfigFile { if (isArray(rootFilesOrConfigFileName)) { - return createWatchCompilerHostOfFilesAndCompilerOptions(rootFilesOrConfigFileName, options, system, createProgram, reportDiagnostic, reportWatchStatus); + return createWatchCompilerHostOfFilesAndCompilerOptions(rootFilesOrConfigFileName, options!, system, createProgram, reportDiagnostic, reportWatchStatus); // TODO: GH#18217 } else { return createWatchCompilerHostOfConfigFile(rootFilesOrConfigFileName, options, system, createProgram, reportDiagnostic, reportWatchStatus); @@ -442,7 +445,7 @@ namespace ts { let timerToUpdateProgram: any; // timer callback to recompile the program const sourceFilesCache = createMap(); // Cache that stores the source file and version info - let missingFilePathsRequestedForRelease: Path[]; // These paths are held temparirly so that we can remove the entry from source file cache if the file is not tracked by missing files + let missingFilePathsRequestedForRelease: Path[] | undefined; // These paths are held temparirly so that we can remove the entry from source file cache if the file is not tracked by missing files let hasChangedCompilerOptions = false; // True if the compiler options have changed between compilations let hasChangedAutomaticTypeDirectiveNames = false; // True if the automatic type directives have changed @@ -456,14 +459,14 @@ namespace ts { let configFileParsingDiagnostics: ReadonlyArray | undefined; let hasChangedConfigFileParsingErrors = false; - const cachedDirectoryStructureHost = configFileName && createCachedDirectoryStructureHost(host, currentDirectory, useCaseSensitiveFileNames); + const cachedDirectoryStructureHost = configFileName === undefined ? undefined : createCachedDirectoryStructureHost(host, currentDirectory, useCaseSensitiveFileNames); if (cachedDirectoryStructureHost && host.onCachedDirectoryStructureHostCreate) { host.onCachedDirectoryStructureHostCreate(cachedDirectoryStructureHost); } const directoryStructureHost: DirectoryStructureHost = cachedDirectoryStructureHost || host; const parseConfigFileHost: ParseConfigFileHost = { useCaseSensitiveFileNames, - readDirectory: (path, extensions, exclude, include, depth) => directoryStructureHost.readDirectory(path, extensions, exclude, include, depth), + readDirectory: (path, extensions, exclude, include, depth) => directoryStructureHost.readDirectory!(path, extensions, exclude, include, depth), fileExists: path => host.fileExists(path), readFile, getCurrentDirectory, @@ -485,10 +488,10 @@ namespace ts { newLine = updateNewLine(); } - const trace = host.trace && ((s: string) => { host.trace(s + newLine); }); + const trace = host.trace && ((s: string) => { host.trace!(s + newLine); }); const watchLogLevel = trace ? compilerOptions.extendedDiagnostics ? WatchLogLevel.Verbose : compilerOptions.diagnostis ? WatchLogLevel.TriggerOnly : WatchLogLevel.None : WatchLogLevel.None; - const writeLog: (s: string) => void = watchLogLevel !== WatchLogLevel.None ? trace : noop; + const writeLog: (s: string) => void = watchLogLevel !== WatchLogLevel.None ? trace! : noop; // TODO: GH#18217 const { watchFile, watchFilePath, watchDirectory } = getWatchFactory(watchLogLevel, writeLog); const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames); @@ -502,7 +505,7 @@ namespace ts { // Members for CompilerHost getSourceFile: (fileName, languageVersion, onError?, shouldCreateNewSourceFile?) => getVersionedSourceFileByPath(fileName, toPath(fileName), languageVersion, onError, shouldCreateNewSourceFile), getSourceFileByPath: getVersionedSourceFileByPath, - getDefaultLibLocation: host.getDefaultLibLocation && (() => host.getDefaultLibLocation()), + getDefaultLibLocation: host.getDefaultLibLocation && (() => host.getDefaultLibLocation!()), getDefaultLibFileName: options => host.getDefaultLibFileName(options), writeFile, getCurrentDirectory, @@ -512,12 +515,12 @@ namespace ts { fileExists, readFile, trace, - directoryExists: directoryStructureHost.directoryExists && (path => directoryStructureHost.directoryExists(path)), - getDirectories: directoryStructureHost.getDirectories && (path => directoryStructureHost.getDirectories(path)), - realpath: host.realpath && (s => host.realpath(s)), - getEnvironmentVariable: host.getEnvironmentVariable ? (name => host.getEnvironmentVariable(name)) : (() => ""), + directoryExists: directoryStructureHost.directoryExists && (path => directoryStructureHost.directoryExists!(path)), + getDirectories: (directoryStructureHost.getDirectories && ((path: string) => directoryStructureHost.getDirectories!(path)))!, // TODO: GH#18217 + realpath: host.realpath && (s => host.realpath!(s)), + getEnvironmentVariable: host.getEnvironmentVariable ? (name => host.getEnvironmentVariable!(name)) : (() => ""), onReleaseOldSourceFile, - createHash: host.createHash && (data => host.createHash(data)), + createHash: host.createHash && (data => host.createHash!(data)), // Members for ResolutionCacheHost toPath, getCompilationSettings: () => compilerOptions, @@ -541,10 +544,10 @@ namespace ts { ); // Resolve module using host module resolution strategy if provided otherwise use resolution cache to resolve module names compilerHost.resolveModuleNames = host.resolveModuleNames ? - ((moduleNames, containingFile, reusedNames) => host.resolveModuleNames(moduleNames, containingFile, reusedNames)) : + ((moduleNames, containingFile, reusedNames) => host.resolveModuleNames!(moduleNames, containingFile, reusedNames)) : ((moduleNames, containingFile, reusedNames) => resolutionCache.resolveModuleNames(moduleNames, containingFile, reusedNames)); compilerHost.resolveTypeReferenceDirectives = host.resolveTypeReferenceDirectives ? - ((typeDirectiveNames, containingFile) => host.resolveTypeReferenceDirectives(typeDirectiveNames, containingFile)) : + ((typeDirectiveNames, containingFile) => host.resolveTypeReferenceDirectives!(typeDirectiveNames, containingFile)) : ((typeDirectiveNames, containingFile) => resolutionCache.resolveTypeReferenceDirectives(typeDirectiveNames, containingFile)); const userProvidedResolution = !!host.resolveModuleNames || !!host.resolveTypeReferenceDirectives; @@ -659,15 +662,15 @@ namespace ts { const path = toPath(fileName); // If file is missing on host from cache, we can definitely say file doesnt exist // otherwise we need to ensure from the disk - if (isFileMissingOnHost(sourceFilesCache.get(path))) { + if (isFileMissingOnHost(sourceFilesCache.get(path)!)) { return true; } return directoryStructureHost.fileExists(fileName); } - function getVersionedSourceFileByPath(fileName: string, path: Path, languageVersion: ScriptTarget, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile { - const hostSourceFile = sourceFilesCache.get(path); + function getVersionedSourceFileByPath(fileName: string, path: Path, languageVersion: ScriptTarget, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined { + const hostSourceFile = sourceFilesCache.get(path)!; // No source file on the host if (isFileMissingOnHost(hostSourceFile)) { return undefined; @@ -712,7 +715,7 @@ namespace ts { return hostSourceFile.sourceFile; function getNewSourceFile() { - let text: string; + let text: string | undefined; try { performance.mark("beforeIORead"); text = host.readFile(fileName, compilerOptions.charset); @@ -742,7 +745,7 @@ namespace ts { } } - function getSourceVersion(path: Path): string { + function getSourceVersion(path: Path): string | undefined { const hostSourceFile = sourceFilesCache.get(path); return !hostSourceFile || isFileMissingOnHost(hostSourceFile) ? undefined : hostSourceFile.version.toString(); } @@ -843,13 +846,13 @@ namespace ts { } function parseConfigFile() { - setConfigFileParsingResult(getParsedCommandLineOfConfigFile(configFileName, optionsToExtendForConfigFile, parseConfigFileHost)); + setConfigFileParsingResult(getParsedCommandLineOfConfigFile(configFileName, optionsToExtendForConfigFile, parseConfigFileHost)!); // TODO: GH#18217 } function setConfigFileParsingResult(configFileParseResult: ParsedCommandLine) { rootFileNames = configFileParseResult.fileNames; compilerOptions = configFileParseResult.options; - configFileSpecs = configFileParseResult.configFileSpecs; + configFileSpecs = configFileParseResult.configFileSpecs!; // TODO: GH#18217 configFileParsingDiagnostics = getConfigFileParsingDiagnostics(configFileParseResult); hasChangedConfigFileParsingErrors = true; } @@ -881,7 +884,7 @@ namespace ts { updateCachedSystemWithFile(fileName, missingFilePath, eventKind); if (eventKind === FileWatcherEventKind.Created && missingFilesMap.has(missingFilePath)) { - missingFilesMap.get(missingFilePath).close(); + missingFilesMap.get(missingFilePath)!.close(); missingFilesMap.delete(missingFilePath); // Delete the entry in the source files cache so that new source file is created @@ -941,10 +944,10 @@ namespace ts { } function ensureDirectoriesExist(directoryPath: string) { - if (directoryPath.length > getRootLength(directoryPath) && !host.directoryExists(directoryPath)) { + if (directoryPath.length > getRootLength(directoryPath) && !host.directoryExists!(directoryPath)) { const parentDirectory = getDirectoryPath(directoryPath); ensureDirectoriesExist(parentDirectory); - host.createDirectory(directoryPath); + host.createDirectory!(directoryPath); } } @@ -953,7 +956,7 @@ namespace ts { performance.mark("beforeIOWrite"); ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName))); - host.writeFile(fileName, text, writeByteOrderMark); + host.writeFile!(fileName, text, writeByteOrderMark); performance.mark("afterIOWrite"); performance.measure("I/O Write", "beforeIOWrite", "afterIOWrite"); diff --git a/src/compiler/watchUtilities.ts b/src/compiler/watchUtilities.ts index b7b8e57e8726c..45ae2e3547828 100644 --- a/src/compiler/watchUtilities.ts +++ b/src/compiler/watchUtilities.ts @@ -7,6 +7,7 @@ namespace ts { fileExists(path: string): boolean; readFile(path: string, encoding?: string): string | undefined; + // TODO: GH#18217 Optional methods are frequently used as non-optional directoryExists?(path: string): boolean; getDirectories?(path: string): string[]; readDirectory?(path: string, extensions?: ReadonlyArray, exclude?: ReadonlyArray, include?: ReadonlyArray, depth?: number): string[]; @@ -76,8 +77,8 @@ namespace ts { function createCachedFileSystemEntries(rootDir: string, rootDirPath: Path) { const resultFromHost: MutableFileSystemEntries = { - files: map(host.readDirectory(rootDir, /*extensions*/ undefined, /*exclude*/ undefined, /*include*/["*.*"]), getBaseNameOfFileName) || [], - directories: host.getDirectories(rootDir) || [] + files: map(host.readDirectory!(rootDir, /*extensions*/ undefined, /*exclude*/ undefined, /*include*/["*.*"]), getBaseNameOfFileName) || [], + directories: host.getDirectories!(rootDir) || [] }; cachedReadDirectoryResult.set(ensureTrailingDirectorySeparator(rootDirPath), resultFromHost); @@ -131,7 +132,7 @@ namespace ts { if (result) { updateFilesOfFileSystemEntry(result, getBaseNameOfFileName(fileName), /*fileExists*/ true); } - return host.writeFile(fileName, data, writeByteOrderMark); + return host.writeFile!(fileName, data, writeByteOrderMark); } function fileExists(fileName: string): boolean { @@ -143,7 +144,7 @@ namespace ts { function directoryExists(dirPath: string): boolean { const path = toPath(dirPath); - return cachedReadDirectoryResult.has(ensureTrailingDirectorySeparator(path)) || host.directoryExists(dirPath); + return cachedReadDirectoryResult.has(ensureTrailingDirectorySeparator(path)) || host.directoryExists!(dirPath); } function createDirectory(dirPath: string) { @@ -153,7 +154,7 @@ namespace ts { if (result) { updateFileSystemEntry(result.directories, baseFileName, /*isValid*/ true); } - host.createDirectory(dirPath); + host.createDirectory!(dirPath); } function getDirectories(rootDir: string): string[] { @@ -162,7 +163,7 @@ namespace ts { if (result) { return result.directories.slice(); } - return host.getDirectories(rootDir); + return host.getDirectories!(rootDir); } function readDirectory(rootDir: string, extensions?: ReadonlyArray, excludes?: ReadonlyArray, includes?: ReadonlyArray, depth?: number): string[] { @@ -171,12 +172,12 @@ namespace ts { if (result) { return matchFiles(rootDir, extensions, excludes, includes, useCaseSensitiveFileNames, currentDirectory, depth, getFileSystemEntries); } - return host.readDirectory(rootDir, extensions, excludes, includes, depth); + return host.readDirectory!(rootDir, extensions, excludes, includes, depth); - function getFileSystemEntries(dir: string) { + function getFileSystemEntries(dir: string): FileSystemEntries { const path = toPath(dir); if (path === rootDirPath) { - return result; + return result!; } return tryReadDirectory(dir, path) || emptyFileSystemEntries; } @@ -387,7 +388,7 @@ namespace ts { type WatchCallback = (fileName: string, cbOptional?: T, passThrough?: U) => void; type AddWatch = (host: H, file: string, cb: WatchCallback, flags: T, passThrough?: V, detailInfo1?: undefined, detailInfo2?: undefined) => FileWatcher; - export type GetDetailWatchInfo = (detailInfo1: X, detailInfo2: Y) => string; + export type GetDetailWatchInfo = (detailInfo1: X, detailInfo2: Y | undefined) => string; type CreateFileWatcher = (host: H, file: string, cb: WatchCallback, flags: T, passThrough: V | undefined, detailInfo1: X | undefined, detailInfo2: Y | undefined, addWatch: AddWatch, log: (s: string) => void, watchCaption: string, getDetailWatchInfo: GetDetailWatchInfo | undefined) => FileWatcher; function getCreateFileWatcher(watchLogLevel: WatchLogLevel, addWatch: AddWatch): CreateFileWatcher { diff --git a/src/harness/compiler.ts b/src/harness/compiler.ts index 2900c8edbc823..95a7d85fe58f4 100644 --- a/src/harness/compiler.ts +++ b/src/harness/compiler.ts @@ -182,8 +182,8 @@ namespace compiler { } public getSourceMapRecord(): string | undefined { - if (this.result.sourceMaps && this.result.sourceMaps.length > 0) { - return Harness.SourceMapRecorder.getSourceMapRecord(this.result.sourceMaps, this.program, Array.from(this.js.values()), Array.from(this.dts.values())); + if (this.result!.sourceMaps && this.result!.sourceMaps!.length > 0) { + return Harness.SourceMapRecorder.getSourceMapRecord(this.result!.sourceMaps!, this.program!, Array.from(this.js.values()), Array.from(this.dts.values())); } } diff --git a/src/harness/compilerRunner.ts b/src/harness/compilerRunner.ts index b899f3107c578..99191b66c262f 100644 --- a/src/harness/compilerRunner.ts +++ b/src/harness/compilerRunner.ts @@ -81,7 +81,7 @@ class CompilerBaselineRunner extends RunnerBase { private runSuite(fileName: string, test?: CompilerFileBasedTest, configuration?: Harness.FileBasedTestConfiguration) { // Mocha holds onto the closure environment of the describe callback even after the test is done. // Everything declared here should be cleared out in the "after" callback. - let compilerTest: CompilerTest | undefined; + let compilerTest!: CompilerTest; before(() => { compilerTest = new CompilerTest(fileName, test && test.payload, configuration); }); it(`Correct errors for ${fileName}`, () => { compilerTest.verifyDiagnostics(); }); it(`Correct module resolution tracing for ${fileName}`, () => { compilerTest.verifyModuleResolution(); }); @@ -89,7 +89,7 @@ class CompilerBaselineRunner extends RunnerBase { it(`Correct JS output for ${fileName}`, () => { if (this.emit) compilerTest.verifyJavaScriptOutput(); }); it(`Correct Sourcemap output for ${fileName}`, () => { compilerTest.verifySourceMapOutput(); }); it(`Correct type/symbol baselines for ${fileName}`, () => { compilerTest.verifyTypesAndSymbols(); }); - after(() => { compilerTest = undefined; }); + after(() => { compilerTest = undefined!; }); } private parseOptions() { @@ -131,7 +131,7 @@ class CompilerTest { const rootDir = fileName.indexOf("conformance") === -1 ? "tests/cases/compiler/" : ts.getDirectoryPath(fileName) + "/"; if (testCaseContent === undefined) { - testCaseContent = Harness.TestCaseParser.makeUnitsFromTest(Harness.IO.readFile(fileName), fileName, rootDir); + testCaseContent = Harness.TestCaseParser.makeUnitsFromTest(Harness.IO.readFile(fileName)!, fileName, rootDir); } if (configurationOverrides) { @@ -140,13 +140,13 @@ class CompilerTest { const units = testCaseContent.testUnitData; this.harnessSettings = testCaseContent.settings; - let tsConfigOptions: ts.CompilerOptions; + let tsConfigOptions: ts.CompilerOptions | undefined; this.tsConfigFiles = []; if (testCaseContent.tsConfig) { assert.equal(testCaseContent.tsConfig.fileNames.length, 0, `list of files in tsconfig is not currently supported`); tsConfigOptions = ts.cloneCompilerOptions(testCaseContent.tsConfig.options); - this.tsConfigFiles.push(this.createHarnessTestFile(testCaseContent.tsConfigFileUnitData, rootDir, ts.combinePaths(rootDir, tsConfigOptions.configFilePath))); + this.tsConfigFiles.push(this.createHarnessTestFile(testCaseContent.tsConfigFileUnitData!, rootDir, ts.combinePaths(rootDir, tsConfigOptions.configFilePath!))); } else { const baseUrl = this.harnessSettings.baseUrl; @@ -156,7 +156,7 @@ class CompilerTest { } this.lastUnit = units[units.length - 1]; - this.hasNonDtsFiles = ts.forEach(units, unit => !ts.fileExtensionIs(unit.name, ts.Extension.Dts)); + this.hasNonDtsFiles = units.some(unit => !ts.fileExtensionIs(unit.name, ts.Extension.Dts)); // We need to assemble the list of input files for the compiler and other related files on the 'filesystem' (ie in a multi-file test) // If the last file in a test uses require or a triple slash reference we'll assume all other files will be brought in via references, // otherwise, assume all files are just meant to be in the same compilation session without explicit references to one another. @@ -179,7 +179,7 @@ class CompilerTest { if (tsConfigOptions && tsConfigOptions.configFilePath !== undefined) { tsConfigOptions.configFilePath = ts.combinePaths(rootDir, tsConfigOptions.configFilePath); - tsConfigOptions.configFile.fileName = tsConfigOptions.configFilePath; + tsConfigOptions.configFile!.fileName = tsConfigOptions.configFilePath; } this.result = Harness.Compiler.compileFiles( @@ -194,7 +194,7 @@ class CompilerTest { public static getConfigurations(file: string): CompilerFileBasedTest { // also see `parseCompilerTestConfigurations` in tests/webTestServer.ts - const content = Harness.IO.readFile(file); + const content = Harness.IO.readFile(file)!; const rootDir = file.indexOf("conformance") === -1 ? "tests/cases/compiler/" : ts.getDirectoryPath(file) + "/"; const payload = Harness.TestCaseParser.makeUnitsFromTest(content, file, rootDir); const settings = Harness.TestCaseParser.extractCompilerSettings(content); @@ -222,7 +222,7 @@ class CompilerTest { public verifySourceMapRecord() { if (this.options.sourceMap || this.options.inlineSourceMap || this.options.declarationMap) { Harness.Baseline.runBaseline(this.justName.replace(/\.tsx?$/, ".sourcemap.txt"), () => { - const record = utils.removeTestPathPrefixes(this.result.getSourceMapRecord()); + const record = utils.removeTestPathPrefixes(this.result.getSourceMapRecord()!); if ((this.options.noEmitOnError && this.result.diagnostics.length !== 0) || record === undefined) { // Because of the noEmitOnError option no files are created. We need to return null because baselining isn't required. /* tslint:disable:no-null-keyword */ @@ -263,8 +263,8 @@ class CompilerTest { Harness.Compiler.doTypeAndSymbolBaseline( this.justName, - this.result.program, - this.toBeCompiled.concat(this.otherFiles).filter(file => !!this.result.program.getSourceFile(file.unitName))); + this.result.program!, + this.toBeCompiled.concat(this.otherFiles).filter(file => !!this.result.program!.getSourceFile(file.unitName))); } private makeUnitName(name: string, root: string) { diff --git a/src/harness/documents.ts b/src/harness/documents.ts index f521902910984..52773bf774ae4 100644 --- a/src/harness/documents.ts +++ b/src/harness/documents.ts @@ -151,9 +151,9 @@ namespace documents { return match ? new SourceMap(/*mapFile*/ undefined, new Buffer(match[1], "base64").toString("utf8")) : undefined; } - public static fromSource(text: string) { + public static fromSource(text: string): SourceMap | undefined { const url = this.getUrl(text); - return url && this.fromUrl(url); + return url === undefined ? undefined : this.fromUrl(url); } public getMappingsForEmittedLine(emittedLine: number): ReadonlyArray | undefined { diff --git a/src/harness/externalCompileRunner.ts b/src/harness/externalCompileRunner.ts index 8fed742d9223d..2e24400fed553 100644 --- a/src/harness/externalCompileRunner.ts +++ b/src/harness/externalCompileRunner.ts @@ -16,7 +16,7 @@ interface UserConfig { abstract class ExternalCompileRunnerBase extends RunnerBase { abstract testDir: string; - abstract report(result: ExecResult, cwd: string): string; + abstract report(result: ExecResult, cwd: string): string | null; enumerateTestFiles() { return Harness.IO.getDirectories(this.testDir); } @@ -48,7 +48,7 @@ abstract class ExternalCompileRunnerBase extends RunnerBase { let cwd = path.join(Harness.IO.getWorkspaceRoot(), cls.testDir, directoryName); const originalCwd = cwd; const stdio = isWorker ? "pipe" : "inherit"; - let types: string[]; + let types: string[] | undefined; if (fs.existsSync(path.join(cwd, "test.json"))) { const submoduleDir = path.join(cwd, directoryName); const reset = cp.spawnSync("git", ["reset", "HEAD", "--hard"], { cwd: submoduleDir, timeout, shell: true, stdio }); diff --git a/src/harness/fakes.ts b/src/harness/fakes.ts index 4fdd30c940e26..84d9f1013f285 100644 --- a/src/harness/fakes.ts +++ b/src/harness/fakes.ts @@ -19,7 +19,7 @@ namespace fakes { public readonly output: string[] = []; public readonly newLine: string; public readonly useCaseSensitiveFileNames: boolean; - public exitCode: number; + public exitCode: number | undefined; private readonly _executingFilePath: string | undefined; private readonly _env: Record | undefined; @@ -128,7 +128,7 @@ namespace fakes { public getModifiedTime(path: string) { const stats = this._getStats(path); - return stats ? stats.mtime : undefined; + return stats ? stats.mtime : undefined!; // TODO: GH#18217 } public createHash(data: string): string { @@ -144,8 +144,8 @@ namespace fakes { } } - public getEnvironmentVariable(name: string): string | undefined { - return this._env && this._env[name]; + public getEnvironmentVariable(name: string): string { + return (this._env && this._env[name])!; // TODO: GH#18217 } private _getStats(path: string) { @@ -275,7 +275,7 @@ namespace fakes { this._outputsMap.set(document.file, this.outputs.length); this.outputs.push(document); } - this.outputs[this._outputsMap.get(document.file)] = document; + this.outputs[this._outputsMap.get(document.file)!] = document; } public trace(s: string): void { @@ -332,7 +332,7 @@ namespace fakes { let fs = this.vfs; while (fs.shadowRoot) { try { - const shadowRootStats = fs.shadowRoot.existsSync(canonicalFileName) && fs.shadowRoot.statSync(canonicalFileName); + const shadowRootStats = fs.shadowRoot.existsSync(canonicalFileName) ? fs.shadowRoot.statSync(canonicalFileName) : undefined!; // TODO: GH#18217 if (shadowRootStats.dev !== stats.dev || shadowRootStats.ino !== stats.ino || shadowRootStats.mtimeMs !== stats.mtimeMs) { diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index b501e437384dc..16295828d05d4 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -184,7 +184,7 @@ namespace FourSlash { private inputFiles = ts.createMap(); // Map between inputFile's fileName and its content for easily looking up when resolving references - private static getDisplayPartsJson(displayParts: ts.SymbolDisplayPart[]) { + private static getDisplayPartsJson(displayParts: ts.SymbolDisplayPart[] | undefined) { let result = ""; ts.forEach(displayParts, part => { if (result) { @@ -204,7 +204,7 @@ namespace FourSlash { // Add input file which has matched file name with the given reference-file path. // This is necessary when resolveReference flag is specified - private addMatchedInputFile(referenceFilePath: string, extensions: ReadonlyArray) { + private addMatchedInputFile(referenceFilePath: string, extensions: ReadonlyArray | undefined) { const inputFiles = this.inputFiles; const languageServiceAdapterHost = this.languageServiceAdapterHost; const didAdd = tryAdd(referenceFilePath); @@ -243,16 +243,16 @@ namespace FourSlash { compilationOptions.skipDefaultLibCheck = true; // Initialize the language service with all the scripts - let startResolveFileRef: FourSlashFile; + let startResolveFileRef: FourSlashFile | undefined; - let configFileName: string; + let configFileName: string | undefined; for (const file of testData.files) { // Create map between fileName and its content for easily looking up when resolveReference flag is specified this.inputFiles.set(file.fileName, file.content); if (isConfig(file)) { const configJson = ts.parseConfigFileTextToJson(file.fileName, file.content); if (configJson.config === undefined) { - throw new Error(`Failed to parse test ${file.fileName}: ${configJson.error.messageText}`); + throw new Error(`Failed to parse test ${file.fileName}: ${configJson.error!.messageText}`); } // Extend our existing compiler options so that we can also support tsconfig only options @@ -280,12 +280,12 @@ namespace FourSlash { const baseDir = ts.normalizePath(ts.getDirectoryPath(configFileName)); const files: vfs.FileSet = { [baseDir]: {} }; this.inputFiles.forEach((data, path) => { - const scriptInfo = new Harness.LanguageService.ScriptInfo(path, undefined, /*isRootFile*/ false); + const scriptInfo = new Harness.LanguageService.ScriptInfo(path, undefined!, /*isRootFile*/ false); // TODO: GH#18217 files[path] = new vfs.File(data, { meta: { scriptInfo } }); }); const fs = new vfs.FileSystem(/*ignoreCase*/ true, { cwd: baseDir, files }); const host = new fakes.ParseConfigHost(fs); - const jsonSourceFile = ts.parseJsonText(configFileName, this.inputFiles.get(configFileName)); + const jsonSourceFile = ts.parseJsonText(configFileName, this.inputFiles.get(configFileName)!); compilationOptions = ts.parseJsonSourceFileConfigFileContent(jsonSourceFile, host, baseDir, compilationOptions, configFileName).options; } @@ -323,7 +323,7 @@ namespace FourSlash { // Check if no-default-lib flag is false and if so add default library if (!resolvedResult.isLibFile) { this.languageServiceAdapterHost.addScript(Harness.Compiler.defaultLibFileName, - Harness.Compiler.getDefaultLibrarySourceFile().text, /*isRootFile*/ false); + Harness.Compiler.getDefaultLibrarySourceFile()!.text, /*isRootFile*/ false); } } else { @@ -335,7 +335,7 @@ namespace FourSlash { }); if (!compilationOptions.noLib) { this.languageServiceAdapterHost.addScript(Harness.Compiler.defaultLibFileName, - Harness.Compiler.getDefaultLibrarySourceFile().text, /*isRootFile*/ false); + Harness.Compiler.getDefaultLibrarySourceFile()!.text, /*isRootFile*/ false); } } @@ -393,7 +393,7 @@ namespace FourSlash { (...args) => args.join("|,|") ); proxy[key] = (...args: any[]) => memo( - target.languageServiceAdapterHost.getScriptInfo(target.activeFile.fileName).version, + target.languageServiceAdapterHost.getScriptInfo(target.activeFile.fileName)!.version, target.activeFile.fileName, target.currentCaretPosition, target.selectionEnd, @@ -406,7 +406,7 @@ namespace FourSlash { } private getFileContent(fileName: string): string { - const script = this.languageServiceAdapterHost.getScriptInfo(fileName); + const script = this.languageServiceAdapterHost.getScriptInfo(fileName)!; return script.content; } @@ -548,9 +548,9 @@ namespace FourSlash { } } - private anyErrorInRange(predicate: (errorMinChar: number, errorLimChar: number, startPos: number, endPos: number) => boolean, startMarker: Marker, endMarker?: Marker): boolean { + private anyErrorInRange(predicate: (errorMinChar: number, errorLimChar: number, startPos: number, endPos: number | undefined) => boolean, startMarker: Marker, endMarker?: Marker): boolean { return this.getDiagnostics(startMarker.fileName).some(({ start, length }) => - predicate(start, start + length, startMarker.position, endMarker === undefined ? undefined : endMarker.position)); + predicate(start!, start! + length!, startMarker.position, endMarker === undefined ? undefined : endMarker.position)); // TODO: GH#18217 } private printErrorLog(expectErrors: boolean, errors: ts.Diagnostic[]) { @@ -562,12 +562,12 @@ namespace FourSlash { } for (const { start, length, messageText, file } of errors) { - Harness.IO.log(" " + this.formatRange(file, start, length) + + Harness.IO.log(" " + this.formatRange(file, start!, length!) + // TODO: GH#18217 ", message: " + ts.flattenDiagnosticMessageText(messageText, Harness.IO.newLine()) + "\n"); } } - private formatRange(file: ts.SourceFile, start: number, length: number) { + private formatRange(file: ts.SourceFile | undefined, start: number, length: number) { if (file) { return `from: ${this.formatLineAndCharacterOfPosition(file, start)}, to: ${this.formatLineAndCharacterOfPosition(file, start + length)}`; } @@ -597,7 +597,7 @@ namespace FourSlash { if (errors.length) { this.printErrorLog(/*expectErrors*/ false, errors); const error = errors[0]; - this.raiseError(`Found an error: ${this.formatPosition(error.file, error.start)}: ${error.messageText}`); + this.raiseError(`Found an error: ${this.formatPosition(error.file!, error.start!)}: ${error.messageText}`); } }); } @@ -635,11 +635,11 @@ namespace FourSlash { } private getGoToDefinition(): ts.DefinitionInfo[] { - return this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition); + return this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition)!; } private getGoToDefinitionAndBoundSpan(): ts.DefinitionInfoAndBoundSpan { - return this.languageService.getDefinitionAndBoundSpan(this.activeFile.fileName, this.currentCaretPosition); + return this.languageService.getDefinitionAndBoundSpan(this.activeFile.fileName, this.currentCaretPosition)!; } public verifyGoToType(arg0: any, endMarkerNames?: ArrayOrSingle) { @@ -694,9 +694,9 @@ namespace FourSlash { testName = "goToDefinitions"; } else { - this.verifyDefinitionTextSpan(defs, startMarkerName); + this.verifyDefinitionTextSpan(defs, startMarkerName!); - definitions = defs.definitions; + definitions = defs.definitions!; // TODO: GH#18217 testName = "goToDefinitionsAndBoundSpan"; } @@ -713,7 +713,7 @@ namespace FourSlash { } private verifyDefinitionTextSpan(defs: ts.DefinitionInfoAndBoundSpan, startMarkerName: string) { - const range = this.testData.ranges.find(range => this.markerName(range.marker) === startMarkerName); + const range = this.testData.ranges.find(range => this.markerName(range.marker!) === startMarkerName); if (!range && !defs.textSpan) { return; @@ -791,7 +791,7 @@ namespace FourSlash { return; } - const entries = this.getCompletionListAtCaret().entries; + const entries = this.getCompletionListAtCaret()!.entries; assert.isTrue(items.length <= entries.length, `Amount of expected items in completion list [ ${items.length} ] is greater than actual number of items in list [ ${entries.length} ]`); ts.zipWith(entries, items, (entry, item) => { assert.equal(entry.name, item, `Unexpected item in completion list`); @@ -799,7 +799,7 @@ namespace FourSlash { } public noItemsWithSameNameButDifferentKind(): void { - const completions = this.getCompletionListAtCaret(); + const completions = this.getCompletionListAtCaret()!; const uniqueItems = ts.createMap(); for (const item of completions.entries) { const uniqueItem = uniqueItems.get(item.name); @@ -854,7 +854,7 @@ namespace FourSlash { } private verifyCompletionsWorker(options: FourSlashInterface.VerifyCompletionsOptions): void { - const actualCompletions = this.getCompletionListAtCaret({ ...options.preferences, triggerCharacter: options.triggerCharacter }); + const actualCompletions = this.getCompletionListAtCaret({ ...options.preferences, triggerCharacter: options.triggerCharacter })!; if (!actualCompletions) { if (options.exact === undefined) return; this.raiseError(`No completions at position '${this.currentCaretPosition}'.`); @@ -877,7 +877,7 @@ namespace FourSlash { if ("exact" in options) { ts.Debug.assert(!("includes" in options) && !("excludes" in options)); - if (options.exact === undefined) this.raiseError("Expected no completions"); + if (options.exact === undefined) throw this.raiseError("Expected no completions"); this.verifyCompletionsAreExactly(actualCompletions.entries, toArray(options.exact)); } else { @@ -885,7 +885,7 @@ namespace FourSlash { for (const include of toArray(options.includes)) { const name = typeof include === "string" ? include : include.name; const found = actualByName.get(name); - if (!found) this.raiseError(`No completion ${name} found`); + if (!found) throw this.raiseError(`No completion ${name} found`); this.verifyCompletionEntry(found, include); } } @@ -929,7 +929,7 @@ namespace FourSlash { assert.equal(actual.isRecommended, isRecommended); if (text) { - const actualDetails = this.getCompletionEntryDetails(actual.name, actual.source); + const actualDetails = this.getCompletionEntryDetails(actual.name, actual.source)!; assert.equal(ts.displayPartsToString(actualDetails.displayParts), text); assert.equal(ts.displayPartsToString(actualDetails.documentation), documentation || ""); // TODO: GH#23587 @@ -962,8 +962,7 @@ namespace FourSlash { exact: expected, isNewIdentifierLocation: options && options.isNewIdentifierLocation, preferences: options, - // TODO: GH#20090 - triggerCharacter: (options && options.triggerCharacter) as ts.CompletionsTriggerCharacter | undefined, + triggerCharacter: options && options.triggerCharacter, }); } @@ -989,7 +988,7 @@ namespace FourSlash { * @param spanIndex the index of the range that the completion item's replacement text span should match */ public verifyCompletionListDoesNotContain(entryId: ts.Completions.CompletionEntryIdentifier, expectedText?: string, expectedDocumentation?: string, expectedKind?: string | { kind?: string, kindModifiers?: string }, spanIndex?: number, options?: FourSlashInterface.CompletionsAtOptions) { - let replacementSpan: ts.TextSpan; + let replacementSpan: ts.TextSpan | undefined; if (spanIndex !== undefined) { replacementSpan = this.getTextSpanForRangeAtIndex(spanIndex); } @@ -1022,7 +1021,7 @@ namespace FourSlash { // then these symbols must meet the criterion for Not supposed to be in the list. So we // raise an error let error = `Completion list did contain '${JSON.stringify(entryId)}\'.`; - const details = this.getCompletionEntryDetails(filterCompletions[0].name); + const details = this.getCompletionEntryDetails(filterCompletions[0].name)!; if (expectedText) { error += "Expected text: " + expectedText + " to equal: " + ts.displayPartsToString(details.displayParts) + "."; } @@ -1045,7 +1044,7 @@ namespace FourSlash { } public verifyCompletionEntryDetails(entryName: string, expectedText: string, expectedDocumentation?: string, kind?: string, tags?: ts.JSDocTagInfo[]) { - const details = this.getCompletionEntryDetails(entryName); + const details = this.getCompletionEntryDetails(entryName)!; assert(details, "no completion entry available"); @@ -1060,8 +1059,8 @@ namespace FourSlash { } if (tags !== undefined) { - assert.equal(details.tags.length, tags.length, this.messageAtLastKnownMarker("QuickInfo tags")); - ts.zipWith(tags, details.tags, (expectedTag, actualTag) => { + assert.equal(details.tags!.length, tags.length, this.messageAtLastKnownMarker("QuickInfo tags")); + ts.zipWith(tags, details.tags!, (expectedTag, actualTag) => { assert.equal(actualTag.name, expectedTag.name); assert.equal(actualTag.text, expectedTag.text, this.messageAtLastKnownMarker("QuickInfo tag " + actualTag.name)); }); @@ -1074,7 +1073,7 @@ namespace FourSlash { private _checker: ts.TypeChecker; private getProgram(): ts.Program { - return this._program || (this._program = this.languageService.getProgram()); + return this._program || (this._program = this.languageService.getProgram()!); // TODO: GH#18217 } private getChecker() { @@ -1122,7 +1121,7 @@ namespace FourSlash { public verifySymbolAtLocation(startRange: Range, declarationRanges: Range[]): void { const node = this.goToAndGetNode(startRange); - const symbol = this.getChecker().getSymbolAtLocation(node); + const symbol = this.getChecker().getSymbolAtLocation(node)!; if (!symbol) { this.raiseError("Could not get symbol at location"); } @@ -1153,14 +1152,14 @@ namespace FourSlash { const startFile = this.activeFile.fileName; for (const fileName of files) { const searchFileNames = startFile === fileName ? [startFile] : [startFile, fileName]; - const highlights = this.getDocumentHighlightsAtCurrentPosition(searchFileNames); + const highlights = this.getDocumentHighlightsAtCurrentPosition(searchFileNames)!; if (!highlights.every(dh => ts.contains(searchFileNames, dh.fileName))) { this.raiseError(`When asking for document highlights only in files ${searchFileNames}, got document highlights in ${unique(highlights, dh => dh.fileName)}`); } } } - public verifyReferenceGroups(starts: ArrayOrSingle | ArrayOrSingle, parts: ReadonlyArray | undefined): void { + public verifyReferenceGroups(starts: ArrayOrSingle | ArrayOrSingle, parts: ReadonlyArray): void { interface ReferenceGroupJson { definition: string | { text: string, range: ts.TextSpan }; references: ts.ReferenceEntry[]; @@ -1220,7 +1219,7 @@ namespace FourSlash { // Necessary to have this function since `findReferences` isn't implemented in `client.ts` public verifyGetReferencesForServerTest(expected: ReadonlyArray): void { const refs = this.getReferencesAtCaret(); - assert.deepEqual(refs, expected); + assert.deepEqual | undefined>(refs, expected); } public verifySingleReferenceGroup(definition: FourSlashInterface.ReferenceGroupDefinition, ranges?: Range[]) { @@ -1274,7 +1273,7 @@ Actual: ${stringify(fullActual)}`); } public verifyDisplayPartsOfReferencedSymbol(expected: ts.SymbolDisplayPart[]) { - const referencedSymbols = this.findReferencesAtCaret(); + const referencedSymbols = this.findReferencesAtCaret()!; if (referencedSymbols.length === 0) { this.raiseError("No referenced symbols found at current caret position"); @@ -1287,11 +1286,11 @@ Actual: ${stringify(fullActual)}`); TestState.getDisplayPartsJson(expected), this.messageAtLastKnownMarker("referenced symbol definition display parts")); } - private getCompletionListAtCaret(options?: ts.GetCompletionsAtPositionOptions): ts.CompletionInfo { + private getCompletionListAtCaret(options?: ts.GetCompletionsAtPositionOptions): ts.CompletionInfo | undefined { return this.languageService.getCompletionsAtPosition(this.activeFile.fileName, this.currentCaretPosition, options); } - private getCompletionEntryDetails(entryName: string, source?: string, preferences?: ts.UserPreferences): ts.CompletionEntryDetails { + private getCompletionEntryDetails(entryName: string, source?: string, preferences?: ts.UserPreferences): ts.CompletionEntryDetails | undefined { return this.languageService.getCompletionEntryDetails(this.activeFile.fileName, this.currentCaretPosition, entryName, this.formatCodeSettings, source, preferences); } @@ -1366,14 +1365,14 @@ Actual: ${stringify(fullActual)}`); tags: ts.JSDocTagInfo[] ) { - const actualQuickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition); + const actualQuickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition)!; assert.equal(actualQuickInfo.kind, kind, this.messageAtLastKnownMarker("QuickInfo kind")); assert.equal(actualQuickInfo.kindModifiers, kindModifiers, this.messageAtLastKnownMarker("QuickInfo kindModifiers")); assert.equal(JSON.stringify(actualQuickInfo.textSpan), JSON.stringify(textSpan), this.messageAtLastKnownMarker("QuickInfo textSpan")); assert.equal(TestState.getDisplayPartsJson(actualQuickInfo.displayParts), TestState.getDisplayPartsJson(displayParts), this.messageAtLastKnownMarker("QuickInfo displayParts")); assert.equal(TestState.getDisplayPartsJson(actualQuickInfo.documentation), TestState.getDisplayPartsJson(documentation), this.messageAtLastKnownMarker("QuickInfo documentation")); - assert.equal(actualQuickInfo.tags.length, tags.length, this.messageAtLastKnownMarker("QuickInfo tags")); - ts.zipWith(tags, actualQuickInfo.tags, (expectedTag, actualTag) => { + assert.equal(actualQuickInfo.tags!.length, tags.length, this.messageAtLastKnownMarker("QuickInfo tags")); + ts.zipWith(tags, actualQuickInfo.tags!, (expectedTag, actualTag) => { assert.equal(expectedTag.name, actualTag.name); assert.equal(expectedTag.text, actualTag.text, this.messageAtLastKnownMarker("QuickInfo tag " + actualTag.name)); }); @@ -1481,10 +1480,10 @@ Actual: ${stringify(fullActual)}`); } private verifySignatureHelpWorker(options: FourSlashInterface.VerifySignatureHelpOptions) { - const help = this.getSignatureHelp(); + const help = this.getSignatureHelp()!; const selectedItem = help.items[help.selectedItemIndex]; // Argument index may exceed number of parameters - const currentParameter: ts.SignatureHelpParameter | undefined = selectedItem.parameters[help.argumentIndex]; + const currentParameter = selectedItem.parameters[help.argumentIndex] as ts.SignatureHelpParameter | undefined; assert.equal(help.items.length, options.overloadsCount || 1, this.assertionMessageAtLastKnownMarker("signature help overloads count")); @@ -1539,7 +1538,7 @@ Actual: ${stringify(fullActual)}`); } } - private validate(name: string, expected: string, actual: string) { + private validate(name: string, expected: string | undefined, actual: string | undefined) { if (expected && expected !== actual) { this.raiseError("Expected " + name + " '" + expected + "'. Got '" + actual + "' instead."); } @@ -1601,19 +1600,19 @@ Actual: ${stringify(fullActual)}`); let nextLine = 0; let resultString = ""; let currentLine: string; - let previousSpanInfo: string; - let startColumn: number; - let length: number; + let previousSpanInfo: string | undefined; + let startColumn: number | undefined; + let length: number | undefined; const prefixString = " >"; let pos = 0; const addSpanInfoString = () => { if (previousSpanInfo) { resultString += currentLine; - let thisLineMarker = ts.repeatString(" ", startColumn) + ts.repeatString("~", length); + let thisLineMarker = ts.repeatString(" ", startColumn!) + ts.repeatString("~", length!); thisLineMarker += ts.repeatString(" ", this.alignmentForExtraInfo - thisLineMarker.length - prefixString.length + 1); resultString += thisLineMarker; - resultString += "=> Pos: (" + (pos - length) + " to " + (pos - 1) + ") "; + resultString += "=> Pos: (" + (pos - length!) + " to " + (pos - 1) + ") "; resultString += " " + previousSpanInfo; previousSpanInfo = undefined; } @@ -1634,12 +1633,12 @@ Actual: ${stringify(fullActual)}`); if (previousSpanInfo && previousSpanInfo !== spanInfo) { addSpanInfoString(); previousSpanInfo = spanInfo; - startColumn = startColumn + length; + startColumn = startColumn! + length!; length = 1; } else { previousSpanInfo = spanInfo; - length++; + length!++; } } addSpanInfoString(); @@ -1660,7 +1659,7 @@ Actual: ${stringify(fullActual)}`); Harness.Baseline.runBaseline( baselineFile, () => { - return this.baselineCurrentFileLocations(pos => this.getBreakpointStatementLocation(pos)); + return this.baselineCurrentFileLocations(pos => this.getBreakpointStatementLocation(pos)!); }); } @@ -1693,10 +1692,10 @@ Actual: ${stringify(fullActual)}`); if (emitOutput.emitSkipped) { resultString += "Diagnostics:" + Harness.IO.newLine(); - const diagnostics = ts.getPreEmitDiagnostics(this.languageService.getProgram()); + const diagnostics = ts.getPreEmitDiagnostics(this.languageService.getProgram()!); // TODO: GH#18217 for (const diagnostic of diagnostics) { if (!ts.isString(diagnostic.messageText)) { - let chainedMessage = diagnostic.messageText; + let chainedMessage: ts.DiagnosticMessageChain | undefined = diagnostic.messageText; let indentation = " "; while (chainedMessage) { resultString += indentation + chainedMessage.messageText + Harness.IO.newLine(); @@ -1741,7 +1740,7 @@ Actual: ${stringify(fullActual)}`); } public printBreakpointLocation(pos: number) { - Harness.IO.log("\n**Pos: " + pos + " " + this.spanInfoToString(this.getBreakpointStatementLocation(pos), " ")); + Harness.IO.log("\n**Pos: " + pos + " " + this.spanInfoToString(this.getBreakpointStatementLocation(pos)!, " ")); } public printBreakpointAtCurrentLocation() { @@ -1754,8 +1753,8 @@ Actual: ${stringify(fullActual)}`); } public printCurrentQuickInfo() { - const quickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition); - Harness.IO.log("Quick Info: " + quickInfo.displayParts.map(part => part.text).join("")); + const quickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition)!; + Harness.IO.log("Quick Info: " + quickInfo.displayParts!.map(part => part.text).join("")); } public printErrorList() { @@ -1790,7 +1789,7 @@ Actual: ${stringify(fullActual)}`); } public printCurrentSignatureHelp() { - const help = this.getSignatureHelp(); + const help = this.getSignatureHelp()!; Harness.IO.log(stringify(help.items[help.selectedItemIndex])); } @@ -1803,7 +1802,7 @@ Actual: ${stringify(fullActual)}`); this.printMembersOrCompletions(completions); } - private printMembersOrCompletions(info: ts.CompletionInfo) { + private printMembersOrCompletions(info: ts.CompletionInfo | undefined) { if (info === undefined) { return "No completion info."; } const { entries } = info; @@ -2087,7 +2086,7 @@ Actual: ${stringify(fullActual)}`); } public goToTypeDefinition(definitionIndex: number) { - const definitions = this.languageService.getTypeDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition); + const definitions = this.languageService.getTypeDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition)!; if (!definitions || !definitions.length) { this.raiseError("goToTypeDefinition failed - expected to find at least one definition location but got 0"); } @@ -2130,7 +2129,7 @@ Actual: ${stringify(fullActual)}`); } public goToImplementation() { - const implementations = this.languageService.getImplementationAtPosition(this.activeFile.fileName, this.currentCaretPosition); + const implementations = this.languageService.getImplementationAtPosition(this.activeFile.fileName, this.currentCaretPosition)!; if (!implementations || !implementations.length) { this.raiseError("goToImplementation failed - expected to find at least one implementation location but got 0"); } @@ -2145,7 +2144,7 @@ Actual: ${stringify(fullActual)}`); public verifyRangesInImplementationList(markerName: string) { this.goToMarker(markerName); - const implementations: ImplementationLocationInformation[] = this.languageService.getImplementationAtPosition(this.activeFile.fileName, this.currentCaretPosition); + const implementations: ImplementationLocationInformation[] = this.languageService.getImplementationAtPosition(this.activeFile.fileName, this.currentCaretPosition)!; if (!implementations || !implementations.length) { this.raiseError("verifyRangesInImplementationList failed - expected to find at least one implementation location but got 0"); } @@ -2321,7 +2320,7 @@ Actual: ${stringify(fullActual)}`); public verifyCurrentNameOrDottedNameSpanText(text: string) { const span = this.languageService.getNameOrDottedNameSpan(this.activeFile.fileName, this.currentCaretPosition, this.currentCaretPosition); if (!span) { - this.raiseError("verifyCurrentNameOrDottedNameSpanText\n" + + return this.raiseError("verifyCurrentNameOrDottedNameSpanText\n" + "\tExpected: \"" + text + "\"\n" + "\t Actual: undefined"); } @@ -2343,12 +2342,12 @@ Actual: ${stringify(fullActual)}`); this.testData.globalOptions[MetadataOptionNames.baselineFile], () => { return this.baselineCurrentFileLocations(pos => - this.getNameOrDottedNameSpan(pos)); + this.getNameOrDottedNameSpan(pos)!); }); } public printNameOrDottedNameSpans(pos: number) { - Harness.IO.log(this.spanInfoToString(this.getNameOrDottedNameSpan(pos), "**")); + Harness.IO.log(this.spanInfoToString(this.getNameOrDottedNameSpan(pos)!, "**")); } private verifyClassifications(expected: { classificationType: string; text: string; textSpan?: TextSpan }[], actual: ts.ClassifiedSpan[], sourceFileText: string) { @@ -2407,7 +2406,7 @@ Actual: ${stringify(fullActual)}`); ); assert.equal( expected.join(","), - actual.fileNames.map(file => { + actual.fileNames!.map(file => { return file.replace(this.basePath + "/", ""); }).join(",") ); @@ -2482,18 +2481,19 @@ Actual: ${stringify(fullActual)}`); public applyCodeActionFromCompletion(markerName: string, options: FourSlashInterface.VerifyCompletionActionOptions) { this.goToMarker(markerName); - const details = this.getCompletionEntryDetails(options.name, options.source, options.preferences); - if (details.codeActions.length !== 1) { - this.raiseError(`Expected one code action, got ${details.codeActions.length}`); + const details = this.getCompletionEntryDetails(options.name, options.source, options.preferences)!; + const codeActions = details.codeActions!; + if (codeActions.length !== 1) { + this.raiseError(`Expected one code action, got ${codeActions.length}`); } - if (details.codeActions[0].description !== options.description) { - this.raiseError(`Expected description to be:\n${options.description}\ngot:\n${details.codeActions[0].description}`); + if (codeActions[0].description !== options.description) { + this.raiseError(`Expected description to be:\n${options.description}\ngot:\n${codeActions[0].description}`); } - this.applyCodeActions(details.codeActions); + this.applyCodeActions(codeActions); - this.verifyNewContent(options, ts.flatMap(details.codeActions, a => a.changes.map(c => c.fileName))); + this.verifyNewContent(options, ts.flatMap(codeActions, a => a.changes.map(c => c.fileName))); } public verifyRangeIs(expectedText: string, includeWhiteSpace?: boolean) { @@ -2527,10 +2527,10 @@ Actual: ${stringify(fullActual)}`); const fixWithId = ts.find(this.getCodeFixes(this.activeFile.fileName), a => a.fixId === fixId); ts.Debug.assert(fixWithId !== undefined, "No available code fix has that group id.", () => `Expected '${fixId}'. Available action ids: ${ts.mapDefined(this.getCodeFixes(this.activeFile.fileName), a => a.fixId)}`); - ts.Debug.assertEqual(fixWithId.fixAllDescription, fixAllDescription); + ts.Debug.assertEqual(fixWithId!.fixAllDescription, fixAllDescription); const { changes, commands } = this.languageService.getCombinedCodeFix({ type: "file", fileName: this.activeFile.fileName }, fixId, this.formatCodeSettings, ts.defaultPreferences); - assert.deepEqual(commands, expectedCommands); + assert.deepEqual | undefined>(commands, expectedCommands); assert(changes.every(c => c.fileName === this.activeFile.fileName), "TODO: support testing codefixes that touch multiple files"); this.applyChanges(changes); this.verifyCurrentFileContent(newFileContent); @@ -2601,7 +2601,7 @@ Actual: ${stringify(fullActual)}`); } } else { - this.verifyRangeIs(options.newRangeContent, /*includeWhitespace*/ true); + this.verifyRangeIs(options.newRangeContent!, /*includeWhitespace*/ true); } } @@ -2621,7 +2621,7 @@ Actual: ${stringify(fullActual)}`); return; } - return this.languageService.getCodeFixesAtPosition(fileName, diagnostic.start, diagnostic.start + diagnostic.length, [diagnostic.code], this.formatCodeSettings, preferences); + return this.languageService.getCodeFixesAtPosition(fileName, diagnostic.start!, diagnostic.start! + diagnostic.length!, [diagnostic.code], this.formatCodeSettings, preferences); }); } @@ -2665,7 +2665,7 @@ Actual: ${stringify(fullActual)}`); } const actualTextArray: string[] = []; - const scriptInfo = this.languageServiceAdapterHost.getScriptInfo(fileName); + const scriptInfo = this.languageServiceAdapterHost.getScriptInfo(fileName)!; const originalContent = scriptInfo.content; for (const codeFix of codeFixes) { ts.Debug.assert(codeFix.changes.length === 1); @@ -2688,7 +2688,7 @@ Actual: ${stringify(fullActual)}`); public verifyDocCommentTemplate(expected: ts.TextInsertion | undefined) { const name = "verifyDocCommentTemplate"; - const actual = this.languageService.getDocCommentTemplateAtPosition(this.activeFile.fileName, this.currentCaretPosition); + const actual = this.languageService.getDocCommentTemplateAtPosition(this.activeFile.fileName, this.currentCaretPosition)!; if (expected === undefined) { if (actual) { @@ -2727,7 +2727,7 @@ Actual: ${stringify(fullActual)}`); const charCode = openBraceMap.get(openingBrace); if (!charCode) { - this.raiseError(`Invalid openingBrace '${openingBrace}' specified.`); + throw this.raiseError(`Invalid openingBrace '${openingBrace}' specified.`); } const position = this.currentCaretPosition; @@ -2899,7 +2899,7 @@ Actual: ${stringify(fullActual)}`); const occurrences = this.getOccurrencesAtCurrentPosition(); if (!occurrences || occurrences.length === 0) { - this.raiseError("verifyOccurrencesAtPositionListContains failed - found 0 references, expected at least one."); + return this.raiseError("verifyOccurrencesAtPositionListContains failed - found 0 references, expected at least one."); } for (const occurrence of occurrences) { @@ -3091,13 +3091,13 @@ Actual: ${stringify(fullActual)}`); const action = ts.firstDefined(refactorsWithName, refactor => refactor.actions.find(a => a.name === actionName)); if (!action) { - this.raiseError(`The expected action: ${actionName} is not included in: ${ts.flatMap(refactorsWithName, r => r.actions.map(a => a.name))}`); + throw this.raiseError(`The expected action: ${actionName} is not included in: ${ts.flatMap(refactorsWithName, r => r.actions.map(a => a.name))}`); } if (action.description !== actionDescription) { this.raiseError(`Expected action description to be ${JSON.stringify(actionDescription)}, got: ${JSON.stringify(action.description)}`); } - const editInfo = this.languageService.getEditsForRefactor(this.activeFile.fileName, this.formatCodeSettings, range, refactorName, actionName, ts.defaultPreferences); + const editInfo = this.languageService.getEditsForRefactor(this.activeFile.fileName, this.formatCodeSettings, range, refactorName, actionName, ts.defaultPreferences)!; for (const edit of editInfo.edits) { this.applyEdits(edit.fileName, edit.textChanges, /*isFormattingEdit*/ false); } @@ -3144,12 +3144,12 @@ Actual: ${stringify(fullActual)}`); public moveToNewFile(options: FourSlashInterface.MoveToNewFileOptions): void { assert(this.getRanges().length === 1); const range = this.getRanges()[0]; - const refactor = ts.find(this.getApplicableRefactors(range, { allowTextChangesInNewFiles: true }), r => r.name === "Move to a new file"); + const refactor = ts.find(this.getApplicableRefactors(range, { allowTextChangesInNewFiles: true }), r => r.name === "Move to a new file")!; assert(refactor.actions.length === 1); const action = ts.first(refactor.actions); assert(action.name === "Move to a new file" && action.description === "Move to a new file"); - const editInfo = this.languageService.getEditsForRefactor(this.activeFile.fileName, this.formatCodeSettings, range, refactor.name, action.name, ts.defaultPreferences); + const editInfo = this.languageService.getEditsForRefactor(this.activeFile.fileName, this.formatCodeSettings, range, refactor.name, action.name, ts.defaultPreferences)!; for (const edit of editInfo.edits) { const newContent = options.newFileContents[edit.fileName]; if (newContent === undefined) { @@ -3190,7 +3190,7 @@ Actual: ${stringify(fullActual)}`); this.raiseError(`The expected refactor: ${refactorNameToApply} is not available at the marker location.`); } - const editInfo = this.languageService.getEditsForRefactor(this.activeFile.fileName, formattingOptions, markerPos, refactorNameToApply, actionName, ts.defaultPreferences); + const editInfo = this.languageService.getEditsForRefactor(this.activeFile.fileName, formattingOptions, markerPos, refactorNameToApply, actionName, ts.defaultPreferences)!; for (const edit of editInfo.edits) { this.applyEdits(edit.fileName, edit.textChanges, /*isFormattingEdit*/ false); @@ -3260,7 +3260,7 @@ Actual: ${stringify(fullActual)}`); const item = matchingItems[0]; if (documentation !== undefined || text !== undefined || entryId.source !== undefined) { - const details = this.getCompletionEntryDetails(item.name, item.source); + const details = this.getCompletionEntryDetails(item.name, item.source)!; if (documentation !== undefined) { eq(ts.displayPartsToString(details.documentation), documentation, "completion item documentation"); @@ -3348,11 +3348,11 @@ Actual: ${stringify(fullActual)}`); private getTextSpanForRangeAtIndex(index: number): ts.TextSpan { const ranges = this.getRanges(); - if (ranges && ranges.length > index) { + if (ranges.length > index) { return ts.createTextSpanFromRange(ranges[index]); } else { - this.raiseError("Supplied span index: " + index + " does not exist in range list of size: " + (ranges ? 0 : ranges.length)); + throw this.raiseError("Supplied span index: " + index + " does not exist in range list of size: " + ranges.length); } } @@ -3374,8 +3374,8 @@ Actual: ${stringify(fullActual)}`); this.cancellationToken.resetCancelled(); } - private static textSpansEqual(a: ts.TextSpan, b: ts.TextSpan) { - return a && b && a.start === b.start && a.length === b.length; + private static textSpansEqual(a: ts.TextSpan | undefined, b: ts.TextSpan | undefined): boolean { + return !!a && !!b && a.start === b.start && a.length === b.length; } public getEditsForFileRename(options: FourSlashInterface.GetEditsForFileRenameOptions): void { @@ -3393,7 +3393,7 @@ Actual: ${stringify(fullActual)}`); } export function runFourSlashTest(basePath: string, testType: FourSlashTestType, fileName: string) { - const content = Harness.IO.readFile(fileName); + const content = Harness.IO.readFile(fileName)!; runFourSlashTestContent(basePath, testType, content, fileName); } @@ -3406,8 +3406,8 @@ Actual: ${stringify(fullActual)}`); const testData = parseTestData(absoluteBasePath, content, absoluteFileName); const state = new TestState(absoluteBasePath, testType, testData); const output = ts.transpileModule(content, { reportDiagnostics: true }); - if (output.diagnostics.length > 0) { - throw new Error(`Syntax error in ${absoluteBasePath}: ${output.diagnostics[0].messageText}`); + if (output.diagnostics!.length > 0) { + throw new Error(`Syntax error in ${absoluteBasePath}: ${output.diagnostics![0].messageText}`); } runCode(output.outputText, state); } @@ -3558,11 +3558,11 @@ ${code} return Harness.getConfigNameFromFileName(file.fileName) !== undefined; } - function getNonFileNameOptionInFileList(files: FourSlashFile[]): string { + function getNonFileNameOptionInFileList(files: FourSlashFile[]): string | undefined { return ts.forEach(files, f => getNonFileNameOptionInObject(f.fileOptions)); } - function getNonFileNameOptionInObject(optionObject: { [s: string]: string }): string { + function getNonFileNameOptionInObject(optionObject: { [s: string]: string }): string | undefined { for (const option in optionObject) { if (option !== MetadataOptionNames.fileName) { return option; @@ -3582,7 +3582,7 @@ ${code} throw new Error(errorMessage); } - function recordObjectMarker(fileName: string, location: LocationInformation, text: string, markerMap: ts.Map, markers: Marker[]): Marker { + function recordObjectMarker(fileName: string, location: LocationInformation, text: string, markerMap: ts.Map, markers: Marker[]): Marker | undefined { let markerValue: any; try { // Attempt to parse the marker value as JSON @@ -3613,7 +3613,7 @@ ${code} return marker; } - function recordMarker(fileName: string, location: LocationInformation, name: string, markerMap: ts.Map, markers: Marker[]): Marker { + function recordMarker(fileName: string, location: LocationInformation, name: string, markerMap: ts.Map, markers: Marker[]): Marker | undefined { const marker: Marker = { fileName, position: location.position @@ -3642,7 +3642,7 @@ ${code} let output = ""; /// The current marker (or maybe multi-line comment?) we're parsing, possibly - let openMarker: LocationInformation; + let openMarker: LocationInformation | undefined; /// A stack of the open range markers that are still unclosed const openRanges: RangeLocationInformation[] = []; @@ -3663,7 +3663,7 @@ ${code} let line = 1; let column = 1; - const flush = (lastSafeCharIndex: number) => { + const flush = (lastSafeCharIndex: number | undefined) => { output = output + content.substr(lastNormalCharPosition, lastSafeCharIndex === undefined ? undefined : lastSafeCharIndex - lastNormalCharPosition); }; @@ -3690,7 +3690,7 @@ ${code} // found a range end const rangeStart = openRanges.pop(); if (!rangeStart) { - reportError(fileName, line, column, "Found range end with no matching start."); + throw reportError(fileName, line, column, "Found range end with no matching start."); } const range: Range = { @@ -3733,8 +3733,8 @@ ${code} // Object markers are only ever terminated by |} and have no content restrictions if (previousChar === "|" && currentChar === "}") { // Record the marker - const objectMarkerNameText = content.substring(openMarker.sourcePosition + 2, i - 1).trim(); - const marker = recordObjectMarker(fileName, openMarker, objectMarkerNameText, markerMap, markers); + const objectMarkerNameText = content.substring(openMarker!.sourcePosition + 2, i - 1).trim(); + const marker = recordObjectMarker(fileName, openMarker!, objectMarkerNameText, markerMap, markers); if (openRanges.length > 0) { openRanges[openRanges.length - 1].marker = marker; @@ -3742,7 +3742,7 @@ ${code} // Set the current start to point to the end of the current marker to ignore its text lastNormalCharPosition = i + 1; - difference += i + 1 - openMarker.sourcePosition; + difference += i + 1 - openMarker!.sourcePosition; // Reset the state openMarker = undefined; @@ -3754,17 +3754,17 @@ ${code} if (previousChar === "*" && currentChar === "/") { // Record the marker // start + 2 to ignore the */, -1 on the end to ignore the * (/ is next) - const markerNameText = content.substring(openMarker.sourcePosition + 2, i - 1).trim(); - const marker = recordMarker(fileName, openMarker, markerNameText, markerMap, markers); + const markerNameText = content.substring(openMarker!.sourcePosition + 2, i - 1).trim(); + const marker = recordMarker(fileName, openMarker!, markerNameText, markerMap, markers); if (openRanges.length > 0) { openRanges[openRanges.length - 1].marker = marker; } // Set the current start to point to the end of the current marker to ignore its text - flush(openMarker.sourcePosition); + flush(openMarker!.sourcePosition); lastNormalCharPosition = i + 1; - difference += i + 1 - openMarker.sourcePosition; + difference += i + 1 - openMarker!.sourcePosition; // Reset the state openMarker = undefined; @@ -3865,7 +3865,7 @@ ${code} return s.replace(/\s/g, ""); } - function findDuplicatedElement(a: ReadonlyArray, equal: (a: T, b: T) => boolean): T { + function findDuplicatedElement(a: ReadonlyArray, equal: (a: T, b: T) => boolean): T | undefined { for (let i = 0; i < a.length; i++) { for (let j = i + 1; j < a.length; j++) { if (equal(a[i], a[j])) { @@ -3889,7 +3889,7 @@ namespace FourSlashInterface { return this.state.getMarkerNames(); } - public marker(name?: string): FourSlash.Marker { + public marker(name: string): FourSlash.Marker { return this.state.getMarkerByName(name); } @@ -3936,7 +3936,7 @@ namespace FourSlashInterface { public eachMarker(action: (marker: FourSlash.Marker, index: number) => void): void; public eachMarker(a: ReadonlyArray | ((marker: FourSlash.Marker, index: number) => void), b?: (marker: FourSlash.Marker, index: number) => void): void { const markers = typeof a === "function" ? this.state.getMarkers() : a.map(m => this.state.getMarkerByName(m)); - this.state.goToEachMarker(markers, typeof a === "function" ? a : b); + this.state.goToEachMarker(markers, typeof a === "function" ? a : b!); } @@ -4146,7 +4146,7 @@ namespace FourSlashInterface { this.state.verifyQuickInfoString(expectedText, expectedDocumentation); } - public quickInfoAt(markerName: string, expectedText?: string, expectedDocumentation?: string) { + public quickInfoAt(markerName: string, expectedText: string, expectedDocumentation?: string) { this.state.verifyQuickInfoAt(markerName, expectedText, expectedDocumentation); } @@ -4765,7 +4765,7 @@ namespace FourSlashInterface { readonly exact?: ArrayOrSingle; readonly includes?: ArrayOrSingle; readonly excludes?: ArrayOrSingle; - readonly preferences: ts.UserPreferences; + readonly preferences?: ts.UserPreferences; readonly triggerCharacter?: ts.CompletionsTriggerCharacter; } diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 96d7a01eaae68..1adf661226eca 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -148,7 +148,7 @@ namespace Utils { path = "tests/" + path; } - let content: string; + let content: string | undefined; try { content = Harness.IO.readFile(Harness.userSpecifiedRoot + path); } @@ -177,7 +177,7 @@ namespace Utils { export const canonicalizeForHarness = ts.createGetCanonicalFileName(/*caseSensitive*/ false); // This is done so tests work on windows _and_ linux - export function assertInvariants(node: ts.Node, parent: ts.Node): void { + export function assertInvariants(node: ts.Node | undefined, parent: ts.Node | undefined): void { if (node) { assert.isFalse(node.pos < 0, "node.pos < 0"); assert.isFalse(node.end < 0, "node.end < 0"); @@ -504,11 +504,11 @@ namespace Harness { newLine(): string; getCurrentDirectory(): string; useCaseSensitiveFileNames(): boolean; - resolvePath(path: string): string; + resolvePath(path: string): string | undefined; getFileSize(path: string): number; readFile(path: string): string | undefined; writeFile(path: string, contents: string): void; - directoryName(path: string): string; + directoryName(path: string): string | undefined; getDirectories(path: string): string[]; createDirectory(path: string): void; fileExists(fileName: string): boolean; @@ -525,7 +525,7 @@ namespace Harness { getAccessibleFileSystemEntries(dirname: string): ts.FileSystemEntries; tryEnableSourceMapsForHost?(): void; getEnvironmentVariable?(name: string): string; - getMemoryUsage?(): number; + getMemoryUsage?(): number | undefined; } export let IO: IO; @@ -564,9 +564,7 @@ namespace Harness { return runner.enumerateTestFiles(); } - function listFiles(path: string, spec: RegExp, options?: { recursive?: boolean }) { - options = options || {}; - + function listFiles(path: string, spec: RegExp, options: { recursive?: boolean } = {}) { function filesInFolder(folder: string): string[] { let paths: string[] = []; @@ -634,7 +632,7 @@ namespace Harness { getCurrentDirectory: () => ts.sys.getCurrentDirectory(), useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames, resolvePath: (path: string) => ts.sys.resolvePath(path), - getFileSize: (path: string) => ts.sys.getFileSize(path), + getFileSize: (path: string) => ts.sys.getFileSize!(path), readFile: path => ts.sys.readFile(path), writeFile: (path, content) => ts.sys.writeFile(path, content), directoryName, @@ -692,7 +690,7 @@ namespace Harness { } } - public static combine(left: HttpHeaders | undefined, right: HttpHeaders | undefined): HttpHeaders { + public static combine(left: HttpHeaders | undefined, right: HttpHeaders | undefined): HttpHeaders | undefined { if (!left && !right) return undefined; const headers = new HttpHeaders(); if (left) left.forEach((value, key) => { headers.set(key, value); }); @@ -768,8 +766,8 @@ namespace Harness { public static readResponseContent(xhr: XMLHttpRequest) { if (typeof xhr.responseText === "string") { return new HttpContent({ - "Content-Type": xhr.getResponseHeader("Content-Type") || undefined, - "Content-Length": xhr.getResponseHeader("Content-Length") || undefined + "Content-Type": xhr.getResponseHeader("Content-Type") || undefined!, // TODO: GH#18217 + "Content-Length": xhr.getResponseHeader("Content-Length") || undefined!, // TODO: GH#18217 }, xhr.responseText); } return undefined; @@ -888,7 +886,7 @@ namespace Harness { function getFileSize(path: string): number { const response = send(HttpRequestMessage.head(new URL(path, serverRoot))); - return HttpResponseMessage.hasSuccessStatusCode(response) ? +response.headers.get("Content-Length").toString() : 0; + return HttpResponseMessage.hasSuccessStatusCode(response) ? +response.headers.get("Content-Length")!.toString() : 0; } function readFile(path: string): string | undefined { @@ -998,7 +996,7 @@ namespace Harness { } } -if (Harness.IO.tryEnableSourceMapsForHost && /^development$/i.test(Harness.IO.getEnvironmentVariable("NODE_ENV"))) { +if (Harness.IO.tryEnableSourceMapsForHost && /^development$/i.test(Harness.IO.getEnvironmentVariable!("NODE_ENV"))) { Harness.IO.tryEnableSourceMapsForHost(); } @@ -1030,7 +1028,7 @@ namespace Harness { */ export class WriterAggregator { public lines: string[] = []; - public currentLine = undefined; + public currentLine: string = undefined!; public Write(str: string) { // out of memory usage concerns avoid using + or += if we're going to do any manipulation of this string later @@ -1040,17 +1038,17 @@ namespace Harness { public WriteLine(str: string) { // out of memory usage concerns avoid using + or += if we're going to do any manipulation of this string later this.lines.push([(this.currentLine || ""), str].join("")); - this.currentLine = undefined; + this.currentLine = undefined!; } public Close() { if (this.currentLine !== undefined) { this.lines.push(this.currentLine); } - this.currentLine = undefined; + this.currentLine = undefined!; } public reset() { this.lines = []; - this.currentLine = undefined; + this.currentLine = undefined!; } } @@ -1077,20 +1075,20 @@ namespace Harness { // Cache of lib files from "built/local" let libFileNameSourceFileMap: ts.Map | undefined; - export function getDefaultLibrarySourceFile(fileName = defaultLibFileName): ts.SourceFile { + export function getDefaultLibrarySourceFile(fileName = defaultLibFileName): ts.SourceFile | undefined { if (!isDefaultLibraryFile(fileName)) { return undefined; } if (!libFileNameSourceFileMap) { libFileNameSourceFileMap = ts.createMapFromTemplate({ - [defaultLibFileName]: createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + "lib.es5.d.ts"), /*languageVersion*/ ts.ScriptTarget.Latest) + [defaultLibFileName]: createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + "lib.es5.d.ts")!, /*languageVersion*/ ts.ScriptTarget.Latest) }); } let sourceFile = libFileNameSourceFileMap.get(fileName); if (!sourceFile) { - libFileNameSourceFileMap.set(fileName, sourceFile = createSourceFileAndAssertInvariants(fileName, IO.readFile(libFolder + fileName), ts.ScriptTarget.Latest)); + libFileNameSourceFileMap.set(fileName, sourceFile = createSourceFileAndAssertInvariants(fileName, IO.readFile(libFolder + fileName)!, ts.ScriptTarget.Latest)); } return sourceFile; } @@ -1206,10 +1204,10 @@ namespace Harness { export function compileFiles( inputFiles: TestFile[], otherFiles: TestFile[], - harnessSettings: TestCaseParser.CompilerSettings, - compilerOptions: ts.CompilerOptions, + harnessSettings: TestCaseParser.CompilerSettings | undefined, + compilerOptions: ts.CompilerOptions | undefined, // Current directory is needed for rwcRunner to be able to use currentDirectory defined in json file - currentDirectory: string): compiler.CompilationResult { + currentDirectory: string | undefined): compiler.CompilationResult { const options: ts.CompilerOptions & HarnessOptions = compilerOptions ? ts.cloneCompilerOptions(compilerOptions) : { noResolve: false }; options.target = options.target || ts.ScriptTarget.ES3; options.newLine = options.newLine || ts.NewLineKind.CarriageReturnLineFeed; @@ -1225,7 +1223,7 @@ namespace Harness { setCompilerOptionsFromHarnessSetting(harnessSettings, options); } if (options.rootDirs) { - options.rootDirs = ts.map(options.rootDirs, d => ts.getNormalizedAbsolutePath(d, currentDirectory)); + options.rootDirs = ts.map(options.rootDirs, d => ts.getNormalizedAbsolutePath(d, currentDirectory!)); } const useCaseSensitiveFileNames = options.useCaseSensitiveFileNames !== undefined ? options.useCaseSensitiveFileNames : true; @@ -1253,7 +1251,7 @@ namespace Harness { export interface DeclarationCompilationContext { declInputFiles: TestFile[]; declOtherFiles: TestFile[]; - harnessSettings: TestCaseParser.CompilerSettings & HarnessOptions; + harnessSettings: TestCaseParser.CompilerSettings & HarnessOptions | undefined; options: ts.CompilerOptions; currentDirectory: string; } @@ -1264,7 +1262,7 @@ namespace Harness { harnessSettings: TestCaseParser.CompilerSettings & HarnessOptions, options: ts.CompilerOptions, // Current directory is needed for rwcRunner to be able to use currentDirectory defined in json file - currentDirectory: string): DeclarationCompilationContext | undefined { + currentDirectory: string | undefined): DeclarationCompilationContext | undefined { if (options.declaration && result.diagnostics.length === 0) { if (options.emitDeclarationOnly) { @@ -1300,7 +1298,7 @@ namespace Harness { } function findResultCodeFile(fileName: string) { - const sourceFile = result.program.getSourceFile(fileName); + const sourceFile = result.program!.getSourceFile(fileName)!; assert(sourceFile, "Program has no source file with name '" + fileName + "'"); // Is this file going to be emitted separately let sourceFileName: string; @@ -1308,7 +1306,7 @@ namespace Harness { if (!outFile) { if (options.outDir) { let sourceFilePath = ts.getNormalizedAbsolutePath(sourceFile.fileName, result.vfs.cwd()); - sourceFilePath = sourceFilePath.replace(result.program.getCommonSourceDirectory(), ""); + sourceFilePath = sourceFilePath.replace(result.program!.getCommonSourceDirectory(), ""); sourceFileName = ts.combinePaths(options.outDir, sourceFilePath); } else { @@ -1408,7 +1406,7 @@ namespace Harness { // Filter down to the errors in the file const fileErrors = diagnostics.filter((e): e is ts.DiagnosticWithLocation => { const errFn = e.file; - return errFn && utils.removeTestPathPrefixes(errFn.fileName) === utils.removeTestPathPrefixes(inputFile.unitName); + return !!errFn && utils.removeTestPathPrefixes(errFn.fileName) === utils.removeTestPathPrefixes(inputFile.unitName); }); @@ -1443,7 +1441,8 @@ namespace Harness { } // Emit this line from the original file outputLines += (newLine() + " " + line); - fileErrors.forEach(err => { + fileErrors.forEach(errDiagnostic => { + const err = errDiagnostic as ts.TextSpan; // TODO: GH#18217 // Does any error start or continue on to this line? Emit squiggles const end = ts.textSpanEnd(err); if ((end >= thisLineStart) && ((err.start < nextLineStart) || (lineIndex === lines.length - 1))) { @@ -1461,7 +1460,7 @@ namespace Harness { // Just like above, we need to do a split on a string instead of on a regex // because the JS engine does regexes wrong - outputErrorText(err); + outputErrorText(errDiagnostic); markedErrorCount++; } } @@ -1476,12 +1475,12 @@ namespace Harness { } const numLibraryDiagnostics = ts.countWhere(diagnostics, diagnostic => { - return diagnostic.file && (isDefaultLibraryFile(diagnostic.file.fileName) || isBuiltFile(diagnostic.file.fileName)); + return !!diagnostic.file && (isDefaultLibraryFile(diagnostic.file.fileName) || isBuiltFile(diagnostic.file.fileName)); }); const numTest262HarnessDiagnostics = ts.countWhere(diagnostics, diagnostic => { // Count an error generated from tests262-harness folder.This should only apply for test262 - return diagnostic.file && diagnostic.file.fileName.indexOf("test262-harness") >= 0; + return !!diagnostic.file && diagnostic.file.fileName.indexOf("test262-harness") >= 0; }); // Verify we didn't miss any errors in total @@ -1489,7 +1488,7 @@ namespace Harness { } export function doErrorBaseline(baselinePath: string, inputFiles: ReadonlyArray, errors: ReadonlyArray, pretty?: boolean) { - Baseline.runBaseline(baselinePath.replace(/\.tsx?$/, ".errors.txt"), (): string => { + Baseline.runBaseline(baselinePath.replace(/\.tsx?$/, ".errors.txt"), (): string | null => { if (!errors || (errors.length === 0)) { /* tslint:disable:no-null-keyword */ return null; @@ -1519,7 +1518,7 @@ namespace Harness { // Produce baselines. The first gives the types for all expressions. // The second gives symbols for all identifiers. - let typesError: Error, symbolsError: Error; + let typesError: Error | undefined, symbolsError: Error | undefined; try { checkBaseLines(/*isSymbolBaseLine*/ false); } @@ -1567,7 +1566,7 @@ namespace Harness { } } - function generateBaseLine(isSymbolBaseline: boolean, skipBaseline?: boolean): string { + function generateBaseLine(isSymbolBaseline: boolean, skipBaseline?: boolean): string | null { let result = ""; const gen = iterateBaseLine(isSymbolBaseline, skipBaseline); for (let {done, value} = gen.next(); !done; { done, value } = gen.next()) { @@ -1754,7 +1753,7 @@ namespace Harness { resultName = sanitizeTestFilePath(resultName); if (dupeCase.has(resultName)) { // A different baseline filename should be manufactured if the names differ only in case, for windows compat - const count = 1 + dupeCase.get(resultName); + const count = 1 + dupeCase.get(resultName)!; dupeCase.set(resultName, count); resultName = `${resultName}.dupe${count}`; } @@ -1862,7 +1861,7 @@ namespace Harness { export function extractCompilerSettings(content: string): CompilerSettings { const opts: CompilerSettings = {}; - let match: RegExpExecArray; + let match: RegExpExecArray | null; /* tslint:disable:no-null-keyword */ while ((match = optionRegex.exec(content)) !== null) { /* tslint:enable:no-null-keyword */ @@ -1875,8 +1874,8 @@ namespace Harness { export interface TestCaseContent { settings: CompilerSettings; testUnitData: TestUnitData[]; - tsConfig: ts.ParsedCommandLine; - tsConfigFileUnitData: TestUnitData; + tsConfig: ts.ParsedCommandLine | undefined; + tsConfigFileUnitData: TestUnitData | undefined; } /** Given a test file containing // @FileName directives, return an array of named units of code to be added to an existing compiler instance */ @@ -1887,7 +1886,7 @@ namespace Harness { const lines = Utils.splitContentByNewlines(code); // Stuff related to the subfile we're parsing - let currentFileContent: string; + let currentFileContent: string | undefined; let currentFileOptions: any = {}; let currentFileName: any; let refs: string[] = []; @@ -1907,7 +1906,7 @@ namespace Harness { if (currentFileName) { // Store result file const newTestFile = { - content: currentFileContent, + content: currentFileContent!, // TODO: GH#18217 name: currentFileName, fileOptions: currentFileOptions, originalFilePath: fileName, @@ -1962,8 +1961,8 @@ namespace Harness { }; // check if project has tsconfig.json in the list of files - let tsConfig: ts.ParsedCommandLine; - let tsConfigFileUnitData: TestUnitData; + let tsConfig: ts.ParsedCommandLine | undefined; + let tsConfigFileUnitData: TestUnitData | undefined; for (let i = 0; i < testUnitData.length; i++) { const data = testUnitData[i]; if (getConfigNameFromFileName(data.name)) { @@ -2024,7 +2023,7 @@ namespace Harness { } const fileCache: { [idx: string]: boolean } = {}; - function generateActual(generateContent: () => string): string { + function generateActual(generateContent: () => string | null): string | null { const actual = generateContent(); @@ -2035,12 +2034,12 @@ namespace Harness { return actual; } - function compareToBaseline(actual: string, relativeFileName: string, opts: BaselineOptions) { + function compareToBaseline(actual: string | null, relativeFileName: string, opts: BaselineOptions | undefined) { // actual is now either undefined (the generator had an error), null (no file requested), // or some real output of the function if (actual === undefined) { // Nothing to do - return; + return undefined!; // TODO: GH#18217 } const refFileName = referencePath(relativeFileName, opts && opts.Baselinefolder, opts && opts.Subfolder); @@ -2053,7 +2052,7 @@ namespace Harness { let expected = ""; if (IO.fileExists(refFileName)) { - expected = IO.readFile(refFileName); + expected = IO.readFile(refFileName)!; // TODO: GH#18217 } return { expected, actual }; @@ -2069,7 +2068,7 @@ namespace Harness { return; } - const parentDirectory = IO.directoryName(dirName); + const parentDirectory = IO.directoryName(dirName)!; // TODO: GH#18217 if (parentDirectory !== "" && parentDirectory !== dirName) { createDirectoryStructure(parentDirectory); } @@ -2078,7 +2077,7 @@ namespace Harness { } // Create folders if needed - createDirectoryStructure(IO.directoryName(actualFileName)); + createDirectoryStructure(IO.directoryName(actualFileName)!); // TODO: GH#18217 // Delete the actual file in case it fails if (IO.fileExists(actualFileName)) { @@ -2097,14 +2096,14 @@ namespace Harness { } } - export function runBaseline(relativeFileName: string, generateContent: () => string, opts?: BaselineOptions): void { + export function runBaseline(relativeFileName: string, generateContent: () => string | null, opts?: BaselineOptions): void { const actualFileName = localPath(relativeFileName, opts && opts.Baselinefolder, opts && opts.Subfolder); const actual = generateActual(generateContent); const comparison = compareToBaseline(actual, relativeFileName, opts); writeComparison(comparison.expected, comparison.actual, relativeFileName, actualFileName); } - export function runMultifileBaseline(relativeFileBase: string, extension: string, generateContent: () => IterableIterator<[string, string, number]> | IterableIterator<[string, string]>, opts?: BaselineOptions, referencedExtensions?: string[]): void { + export function runMultifileBaseline(relativeFileBase: string, extension: string, generateContent: () => IterableIterator<[string, string, number]> | IterableIterator<[string, string]> | null, opts?: BaselineOptions, referencedExtensions?: string[]): void { const gen = generateContent(); const writtenFiles = ts.createMap(); const errors: Error[] = []; @@ -2175,7 +2174,7 @@ namespace Harness { export function getDefaultLibraryFile(filePath: string, io: IO): Compiler.TestFile { const libFile = userSpecifiedRoot + libFolder + ts.getBaseFileName(ts.normalizeSlashes(filePath)); - return { unitName: libFile, content: io.readFile(libFile) }; + return { unitName: libFile, content: io.readFile(libFile)! }; } export function getConfigNameFromFileName(filename: string): "tsconfig.json" | "jsconfig.json" | undefined { diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index 8c30f9411e671..8d1322abfd7c3 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -7,7 +7,7 @@ namespace Harness.LanguageService { export class ScriptInfo { public version = 1; public editRanges: { length: number; textChangeRange: ts.TextChangeRange; }[] = []; - private lineMap: number[] = undefined; + private lineMap: number[] | undefined; constructor(public fileName: string, public content: string, public isRootFile: boolean) { this.setContent(content); @@ -95,7 +95,7 @@ namespace Harness.LanguageService { return this.scriptSnapshot.getLength(); } - public getChangeRange(oldScript: ts.ScriptSnapshotShim): string { + public getChangeRange(oldScript: ts.ScriptSnapshotShim): string | undefined { const range = this.scriptSnapshot.getChangeRange((oldScript as ScriptSnapshotProxy).scriptSnapshot); return range && JSON.stringify(range); } @@ -146,7 +146,7 @@ namespace Harness.LanguageService { return fileNames; } - public getScriptInfo(fileName: string): ScriptInfo { + public getScriptInfo(fileName: string): ScriptInfo | undefined { return this.scriptInfos.get(vpath.resolve(this.vfs.cwd(), fileName)); } @@ -175,9 +175,8 @@ namespace Harness.LanguageService { * @param col 0 based index */ public positionToLineAndCharacter(fileName: string, position: number): ts.LineAndCharacter { - const script: ScriptInfo = this.getScriptInfo(fileName); + const script: ScriptInfo = this.getScriptInfo(fileName)!; assert.isOk(script); - return ts.computeLineAndCharacterOfPosition(script.getLineMap(), position); } } @@ -185,7 +184,7 @@ namespace Harness.LanguageService { /// Native adapter class NativeLanguageServiceHost extends LanguageServiceAdapterHost implements ts.LanguageServiceHost, LanguageServiceAdapterHost { isKnownTypesPackageName(name: string): boolean { - return this.typesRegistry && this.typesRegistry.has(name); + return !!this.typesRegistry && this.typesRegistry.has(name); } installPackage = ts.notImplemented; @@ -206,7 +205,7 @@ namespace Harness.LanguageService { return this.getFilenames().filter(ts.isAnySupportedFileExtension); } - getScriptSnapshot(fileName: string): ts.IScriptSnapshot { + getScriptSnapshot(fileName: string): ts.IScriptSnapshot | undefined { const script = this.getScriptInfo(fileName); return script ? new ScriptSnapshot(script) : undefined; } @@ -215,7 +214,7 @@ namespace Harness.LanguageService { getScriptVersion(fileName: string): string { const script = this.getScriptInfo(fileName); - return script ? script.version.toString() : undefined; + return script ? script.version.toString() : undefined!; // TODO: GH#18217 } directoryExists(dirName: string): boolean { @@ -280,7 +279,7 @@ namespace Harness.LanguageService { } }; this.getModuleResolutionsForFile = (fileName) => { - const scriptInfo = this.getScriptInfo(fileName); + const scriptInfo = this.getScriptInfo(fileName)!; const preprocessInfo = ts.preProcessFile(scriptInfo.content, /*readImportFiles*/ true); const imports: ts.MapLike = {}; for (const module of preprocessInfo.importedFiles) { @@ -299,8 +298,8 @@ namespace Harness.LanguageService { const settings = this.nativeHost.getCompilationSettings(); for (const typeReferenceDirective of preprocessInfo.typeReferenceDirectives) { const resolutionInfo = ts.resolveTypeReferenceDirective(typeReferenceDirective.fileName, fileName, settings, moduleResolutionHost); - if (resolutionInfo.resolvedTypeReferenceDirective.resolvedFileName) { - resolutions[typeReferenceDirective.fileName] = resolutionInfo.resolvedTypeReferenceDirective; + if (resolutionInfo.resolvedTypeReferenceDirective!.resolvedFileName) { + resolutions[typeReferenceDirective.fileName] = resolutionInfo.resolvedTypeReferenceDirective!; } } return JSON.stringify(resolutions); @@ -313,7 +312,7 @@ namespace Harness.LanguageService { } getFilenames(): string[] { return this.nativeHost.getFilenames(); } - getScriptInfo(fileName: string): ScriptInfo { return this.nativeHost.getScriptInfo(fileName); } + getScriptInfo(fileName: string): ScriptInfo | undefined { return this.nativeHost.getScriptInfo(fileName); } addScript(fileName: string, content: string, isRootFile: boolean): void { this.nativeHost.addScript(fileName, content, isRootFile); } editScript(fileName: string, start: number, end: number, newText: string): void { this.nativeHost.editScript(fileName, start, end, newText); } positionToLineAndCharacter(fileName: string, position: number): ts.LineAndCharacter { return this.nativeHost.positionToLineAndCharacter(fileName, position); } @@ -325,7 +324,7 @@ namespace Harness.LanguageService { getDefaultLibFileName(): string { return this.nativeHost.getDefaultLibFileName(); } getScriptFileNames(): string { return JSON.stringify(this.nativeHost.getScriptFileNames()); } getScriptSnapshot(fileName: string): ts.ScriptSnapshotShim { - const nativeScriptSnapshot = this.nativeHost.getScriptSnapshot(fileName); + const nativeScriptSnapshot = this.nativeHost.getScriptSnapshot(fileName)!; // TODO: GH#18217 return nativeScriptSnapshot && new ScriptSnapshotProxy(nativeScriptSnapshot); } getScriptKind(): ts.ScriptKind { return this.nativeHost.getScriptKind(); } @@ -504,7 +503,7 @@ namespace Harness.LanguageService { getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: ts.FormatCodeOptions): ts.TextChange[] { return unwrapJSONCallResult(this.shim.getFormattingEditsAfterKeystroke(fileName, position, key, JSON.stringify(options))); } - getDocCommentTemplateAtPosition(fileName: string, position: number): ts.TextInsertion | undefined { + getDocCommentTemplateAtPosition(fileName: string, position: number): ts.TextInsertion { return unwrapJSONCallResult(this.shim.getDocCommentTemplateAtPosition(fileName, position)); } isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean { @@ -608,7 +607,7 @@ namespace Harness.LanguageService { class SessionClientHost extends NativeLanguageServiceHost implements ts.server.SessionClientHost { private client: ts.server.SessionClient; - constructor(cancellationToken: ts.HostCancellationToken, settings: ts.CompilerOptions) { + constructor(cancellationToken: ts.HostCancellationToken | undefined, settings: ts.CompilerOptions | undefined) { super(cancellationToken, settings); } @@ -715,7 +714,7 @@ namespace Harness.LanguageService { return true; } - getLogFileName(): string { + getLogFileName(): string | undefined { return undefined; } @@ -850,7 +849,7 @@ namespace Harness.LanguageService { cancellationToken: ts.server.nullCancellationToken, useSingleInferredProject: false, useInferredProjectPerProjectRoot: false, - typingsInstaller: undefined, + typingsInstaller: undefined!, // TODO: GH#18217 byteLength: Utils.byteLength, hrtime: process.hrtime, logger: serverHost, diff --git a/src/harness/loggedIO.ts b/src/harness/loggedIO.ts index 9a5e13b107abd..1e55b3e1a6463 100644 --- a/src/harness/loggedIO.ts +++ b/src/harness/loggedIO.ts @@ -68,10 +68,10 @@ interface IoLog { }[]; directoriesRead: { path: string, - extensions: ReadonlyArray, - exclude: ReadonlyArray, - include: ReadonlyArray, - depth: number, + extensions: ReadonlyArray | undefined, + exclude: ReadonlyArray | undefined, + include: ReadonlyArray | undefined, + depth: number | undefined, result: ReadonlyArray, }[]; useCaseSensitiveFileNames?: boolean; @@ -87,8 +87,8 @@ interface PlaybackControl { } namespace Playback { - let recordLog: IoLog; - let replayLog: IoLog; + let recordLog: IoLog | undefined; + let replayLog: IoLog | undefined; let replayFilesRead: ts.Map | undefined; let recordLogFileNameBase = ""; @@ -104,7 +104,7 @@ namespace Playback { return lookup[s] = func(s); }); run.reset = () => { - lookup = undefined; + lookup = undefined!; // TODO: GH#18217 }; return run; @@ -148,11 +148,12 @@ namespace Playback { } } for (const file of log.filesRead) { - if (file.result.contentsPath) { + const result = file.result!; // TODO: GH#18217 + if (result.contentsPath) { // `readFile` strips away a BOM (and actually reinerprets the file contents according to the correct encoding) // - but this has the unfortunate sideeffect of removing the BOM from any outputs based on the file, so we readd it here. - file.result.contents = (file.result.bom || "") + host.readFile(ts.combinePaths(baseName, file.result.contentsPath)); - delete file.result.contentsPath; + result.contents = (result.bom || "") + host.readFile(ts.combinePaths(baseName, result.contentsPath)); + delete result.contentsPath; } } return log; @@ -188,21 +189,22 @@ namespace Playback { } if (log.filesRead) { for (const file of log.filesRead) { - const { contents } = file.result; + const result = file.result!; // TODO: GH#18217 + const { contents } = result; if (contents !== undefined) { - file.result.contentsPath = ts.combinePaths("read", sanitizeTestFilePath(file.path)); - writeFile(ts.combinePaths(baseTestName, file.result.contentsPath), contents); + result.contentsPath = ts.combinePaths("read", sanitizeTestFilePath(file.path)); + writeFile(ts.combinePaths(baseTestName, result.contentsPath), contents); const len = contents.length; if (len >= 2 && contents.charCodeAt(0) === 0xfeff) { - file.result.bom = "\ufeff"; + result.bom = "\ufeff"; } if (len >= 2 && contents.charCodeAt(0) === 0xfffe) { - file.result.bom = "\ufffe"; + result.bom = "\ufffe"; } if (len >= 3 && contents.charCodeAt(0) === 0xefbb && contents.charCodeAt(1) === 0xbf) { - file.result.bom = "\uefbb\xbf"; + result.bom = "\uefbb\xbf"; } - delete file.result.contents; + delete result.contents; } } } @@ -222,7 +224,7 @@ namespace Playback { wrapper.startReplayFromData = log => { replayLog = log; // Remove non-found files from the log (shouldn't really need them, but we still record them for diagnostic purposes) - replayLog.filesRead = replayLog.filesRead.filter(f => f.result.contents !== undefined); + replayLog.filesRead = replayLog.filesRead.filter(f => f.result!.contents !== undefined); replayFilesRead = ts.createMap(); for (const file of replayLog.filesRead) { replayFilesRead.set(ts.normalizeSlashes(file.path).toLowerCase(), file); @@ -244,7 +246,7 @@ namespace Playback { }; wrapper.startReplayFromFile = logFn => { - wrapper.startReplayFromString(underlying.readFile(logFn)); + wrapper.startReplayFromString(underlying.readFile(logFn)!); }; wrapper.endRecord = () => { if (recordLog !== undefined) { @@ -267,24 +269,25 @@ namespace Playback { } const files = []; for (const file of newLog.filesRead) { - if (file.result.contentsPath && - Harness.isDefaultLibraryFile(file.result.contentsPath) && - /\.[tj]s$/.test(file.result.contentsPath)) { - files.push(file.result.contentsPath); + const result = file.result!; + if (result.contentsPath && + Harness.isDefaultLibraryFile(result.contentsPath) && + /\.[tj]s$/.test(result.contentsPath)) { + files.push(result.contentsPath); } } return { compilerOptions: ts.parseCommandLine(newLog.arguments).options, files }; } wrapper.fileExists = recordReplay(wrapper.fileExists, underlying)( - path => callAndRecord(underlying.fileExists(path), recordLog.fileExists, { path }), + path => callAndRecord(underlying.fileExists(path), recordLog!.fileExists, { path }), memoize(path => { // If we read from the file, it must exist if (findFileByPath(path, /*throwFileNotFoundError*/ false)) { return true; } else { - return findResultByFields(replayLog.fileExists, { path }, /*defaultValue*/ false); + return findResultByFields(replayLog!.fileExists, { path }, /*defaultValue*/ false)!; } }) ); @@ -314,22 +317,22 @@ namespace Playback { }; wrapper.resolvePath = recordReplay(wrapper.resolvePath, underlying)( - path => callAndRecord(underlying.resolvePath(path), recordLog.pathsResolved, { path }), - memoize(path => findResultByFields(replayLog.pathsResolved, { path }, !ts.isRootedDiskPath(ts.normalizeSlashes(path)) && replayLog.currentDirectory ? replayLog.currentDirectory + "/" + path : ts.normalizeSlashes(path)))); + path => callAndRecord(underlying.resolvePath(path), recordLog!.pathsResolved, { path }), + memoize(path => findResultByFields(replayLog!.pathsResolved, { path }, !ts.isRootedDiskPath(ts.normalizeSlashes(path)) && replayLog!.currentDirectory ? replayLog!.currentDirectory + "/" + path : ts.normalizeSlashes(path)))); wrapper.readFile = recordReplay(wrapper.readFile, underlying)( (path: string) => { const result = underlying.readFile(path); const logEntry = { path, codepage: 0, result: { contents: result, codepage: 0 } }; - recordLog.filesRead.push(logEntry); + recordLog!.filesRead.push(logEntry); return result; }, - memoize(path => findFileByPath(path, /*throwFileNotFoundError*/ true).contents)); + memoize(path => findFileByPath(path, /*throwFileNotFoundError*/ true)!.contents)); wrapper.readDirectory = recordReplay(wrapper.readDirectory, underlying)( (path, extensions, exclude, include, depth) => { const result = (underlying).readDirectory(path, extensions, exclude, include, depth); - recordLog.directoriesRead.push({ path, extensions, exclude, include, depth, result }); + recordLog!.directoriesRead.push({ path, extensions, exclude, include, depth, result }); return result; }, path => { @@ -338,7 +341,7 @@ namespace Playback { // different entry). // TODO (yuisu): We can certainly remove these once we recapture the RWC using new API const normalizedPath = ts.normalizePath(path).toLowerCase(); - return ts.flatMap(replayLog.directoriesRead, directory => { + return ts.flatMap(replayLog!.directoriesRead, directory => { if (ts.normalizeSlashes(directory.path).toLowerCase() === normalizedPath) { return directory.result; } @@ -346,7 +349,7 @@ namespace Playback { }); wrapper.writeFile = recordReplay(wrapper.writeFile, underlying)( - (path: string, contents: string) => callAndRecord(underlying.writeFile(path, contents), recordLog.filesWritten, { path, contents, bom: false }), + (path: string, contents: string) => callAndRecord(underlying.writeFile(path, contents), recordLog!.filesWritten, { path, contents, bom: false }), () => noOpReplay("writeFile")); wrapper.exit = (exitCode) => { @@ -390,7 +393,7 @@ namespace Playback { return underlyingResult; } - function findResultByFields(logArray: { result?: T }[], expectedFields: {}, defaultValue?: T): T { + function findResultByFields(logArray: { result?: T }[], expectedFields: {}, defaultValue?: T): T | undefined { const predicate = (entry: { result?: T }) => { return Object.getOwnPropertyNames(expectedFields).every((name) => (entry)[name] === (expectedFields)[name]); }; @@ -406,10 +409,10 @@ namespace Playback { return results[0].result; } - function findFileByPath(expectedPath: string, throwFileNotFoundError: boolean): FileInformation { + function findFileByPath(expectedPath: string, throwFileNotFoundError: boolean): FileInformation | undefined { const normalizedName = ts.normalizePath(expectedPath).toLowerCase(); // Try to find the result through normal fileName - const result = replayFilesRead.get(normalizedName); + const result = replayFilesRead!.get(normalizedName); if (result) { return result.result; } diff --git a/src/harness/parallel/host.ts b/src/harness/parallel/host.ts index 6a8b21c970279..2ecccf9454035 100644 --- a/src/harness/parallel/host.ts +++ b/src/harness/parallel/host.ts @@ -1,3 +1,5 @@ +// tslint:disable no-unnecessary-type-assertion (TODO: tslint can't find node types) + if (typeof describe === "undefined") { (global as any).describe = undefined; // If launched without mocha for parallel mode, we still need a global describe visible to satisfy the parsing of the unit tests (global as any).it = undefined; @@ -32,7 +34,7 @@ namespace Harness.Parallel.Host { function perfdataFileName(target?: string) { return `${perfdataFileNameFragment}${target ? `.${target}` : ""}.json`; } - function readSavedPerfData(target?: string): {[testHash: string]: number} { + function readSavedPerfData(target?: string): {[testHash: string]: number} | undefined { const perfDataContents = IO.readFile(perfdataFileName(target)); if (perfDataContents) { return JSON.parse(perfDataContents); @@ -73,7 +75,7 @@ namespace Harness.Parallel.Host { setTimeout(() => startDelayed(perfData, totalCost), 0); // Do real startup on next tick, so all unit tests have been collected } - function startDelayed(perfData: {[testHash: string]: number}, totalCost: number) { + function startDelayed(perfData: {[testHash: string]: number} | undefined, totalCost: number) { initializeProgressBarsDependencies(); console.log(`Discovered ${tasks.length} unittest suites` + (newTasks.length ? ` and ${newTasks.length} new suites.` : ".")); console.log("Discovering runner-based tests..."); @@ -227,16 +229,16 @@ namespace Harness.Parallel.Host { return; } // Send tasks in blocks if the tasks are small - const taskList = [tasks.pop()]; + const taskList = [tasks.pop()!]; while (tasks.length && taskList.reduce((p, c) => p + c.size, 0) < chunkSize) { - taskList.push(tasks.pop()); + taskList.push(tasks.pop()!); } child.currentTasks = taskList; if (taskList.length === 1) { - child.send({ type: "test", payload: taskList[0] }); + child.send({ type: "test", payload: taskList[0] } as ParallelHostMessage); // TODO: GH#18217 } else { - child.send({ type: "batch", payload: taskList }); + child.send({ type: "batch", payload: taskList } as ParallelHostMessage); // TODO: GH#18217 } } } @@ -268,7 +270,7 @@ namespace Harness.Parallel.Host { doneBatching[i] = true; continue; } - const task = tasks.pop(); + const task = tasks.pop()!; batches[i].push(task); scheduledTotal += task.size; } @@ -293,7 +295,7 @@ namespace Harness.Parallel.Host { worker.send({ type: "batch", payload }); } else { // Out of batches, send off just one test - const payload = tasks.pop(); + const payload = tasks.pop()!; ts.Debug.assert(!!payload); // The reserve kept above should ensure there is always an initial task available, even in suboptimal scenarios worker.currentTasks = [payload]; worker.send({ type: "test", payload }); @@ -302,7 +304,7 @@ namespace Harness.Parallel.Host { } else { for (let i = 0; i < workerCount; i++) { - const task = tasks.pop(); + const task = tasks.pop()!; workers[i].currentTasks = [task]; workers[i].send({ type: "test", payload: task }); } @@ -519,7 +521,7 @@ namespace Harness.Parallel.Host { this._enabled = false; } } - update(index: number, percentComplete: number, color: string, title: string, titleColor?: string) { + update(index: number, percentComplete: number, color: string, title: string | undefined, titleColor?: string) { percentComplete = minMax(percentComplete, 0, 1); const progressBar = this._progressBars[index] || (this._progressBars[index] = { }); @@ -555,7 +557,7 @@ namespace Harness.Parallel.Host { } cursor.hide(); - readline.moveCursor(process.stdout, -process.stdout.columns, -this._lineCount); + readline.moveCursor(process.stdout, -process.stdout.columns!, -this._lineCount); let lineCount = 0; const numProgressBars = this._progressBars.length; for (let i = 0; i < numProgressBars; i++) { @@ -564,7 +566,7 @@ namespace Harness.Parallel.Host { process.stdout.write(this._progressBars[i].text + os.EOL); } else { - readline.moveCursor(process.stdout, -process.stdout.columns, +1); + readline.moveCursor(process.stdout, -process.stdout.columns!, +1); } lineCount++; diff --git a/src/harness/parallel/worker.ts b/src/harness/parallel/worker.ts index d90533647451b..1606e30465730 100644 --- a/src/harness/parallel/worker.ts +++ b/src/harness/parallel/worker.ts @@ -1,3 +1,5 @@ +// tslint:disable no-unnecessary-type-assertion (TODO: tslint can't find node types) + namespace Harness.Parallel.Worker { let errors: ErrorInfo[] = []; let passes: TestInfo[] = []; @@ -35,7 +37,7 @@ namespace Harness.Parallel.Worker { if (!testList) { throw new Error("Tests must occur within a describe block"); } - testList.push({ name, callback, kind: "test" }); + testList.push({ name, callback: callback!, kind: "test" }); }) as Mocha.ITestDefinition; (global as any).it.skip = ts.noop; } @@ -43,18 +45,18 @@ namespace Harness.Parallel.Worker { function setTimeoutAndExecute(timeout: number | undefined, f: () => void) { if (timeout !== undefined) { const timeoutMsg: ParallelTimeoutChangeMessage = { type: "timeout", payload: { duration: timeout } }; - process.send(timeoutMsg); + process.send!(timeoutMsg); } f(); if (timeout !== undefined) { // Reset timeout const timeoutMsg: ParallelTimeoutChangeMessage = { type: "timeout", payload: { duration: "reset" } }; - process.send(timeoutMsg); + process.send!(timeoutMsg); } } function executeSuiteCallback(name: string, callback: MochaCallback) { - let timeout: number; + let timeout: number | undefined; const fakeContext: Mocha.ISuiteCallbackContext = { retries() { return this; }, slow() { return this; }, @@ -64,9 +66,9 @@ namespace Harness.Parallel.Worker { }, }; namestack.push(name); - let beforeFunc: Callable; + let beforeFunc: Callable | undefined; (before as any) = (cb: Callable) => beforeFunc = cb; - let afterFunc: Callable; + let afterFunc: Callable | undefined; (after as any) = (cb: Callable) => afterFunc = cb; const savedBeforeEach = beforeEachFunc; (beforeEach as any) = (cb: Callable) => beforeEachFunc = cb; @@ -127,13 +129,13 @@ namespace Harness.Parallel.Worker { } function executeTestCallback(name: string, callback: MochaCallback) { - let timeout: number; + let timeout: number | undefined; const fakeContext: Mocha.ITestCallbackContext = { skip() { return this; }, timeout(n: number) { timeout = n; const timeoutMsg: ParallelTimeoutChangeMessage = { type: "timeout", payload: { duration: timeout } }; - process.send(timeoutMsg); + process.send!(timeoutMsg); return this; }, retries() { return this; }, @@ -164,7 +166,7 @@ namespace Harness.Parallel.Worker { namestack.pop(); if (timeout !== undefined) { const timeoutMsg: ParallelTimeoutChangeMessage = { type: "timeout", payload: { duration: "reset" } }; - process.send(timeoutMsg); + process.send!(timeoutMsg); } } passing++; @@ -195,7 +197,7 @@ namespace Harness.Parallel.Worker { namestack.pop(); if (timeout !== undefined) { const timeoutMsg: ParallelTimeoutChangeMessage = { type: "timeout", payload: { duration: "reset" } }; - process.send(timeoutMsg); + process.send!(timeoutMsg); } } if (!completed) { @@ -219,7 +221,7 @@ namespace Harness.Parallel.Worker { console.error(data); } const message: ParallelResultMessage = { type: "result", payload: handleTest(runner, file) }; - process.send(message); + process.send!(message); break; case "close": process.exit(0); @@ -239,16 +241,16 @@ namespace Harness.Parallel.Worker { else { message = { type: "progress", payload }; } - process.send(message); + process.send!(message); } break; } } }); process.on("uncaughtException", error => { - const message: ParallelErrorMessage = { type: "error", payload: { error: error.message, stack: error.stack, name: [...namestack] } }; + const message: ParallelErrorMessage = { type: "error", payload: { error: error.message, stack: error.stack!, name: [...namestack] } }; try { - process.send(message); + process.send!(message); } catch (e) { console.error(error); @@ -273,7 +275,7 @@ namespace Harness.Parallel.Worker { if (!runners.has(runner)) { runners.set(runner, createRunner(runner)); } - const instance = runners.get(runner); + const instance = runners.get(runner)!; instance.tests = [file]; return { ...resetShimHarnessAndExecute(instance), runner, file }; } diff --git a/src/harness/projectsRunner.ts b/src/harness/projectsRunner.ts index 9ef536ad0c8be..a12da7a268fe5 100644 --- a/src/harness/projectsRunner.ts +++ b/src/harness/projectsRunner.ts @@ -134,7 +134,7 @@ namespace project { this.compilerOptions = createCompilerOptions(testCase, moduleKind); this.sys = new fakes.System(vfs); - let configFileName: string; + let configFileName: string | undefined; let inputFiles = testCase.inputFiles; if (this.compilerOptions.project) { // Parse project @@ -145,7 +145,7 @@ namespace project { configFileName = ts.findConfigFile("", path => this.sys.fileExists(path)); } - let errors: ts.Diagnostic[]; + let errors: ts.Diagnostic[] | undefined; const configFileSourceFiles: ts.SourceFile[] = []; if (configFileName) { const result = ts.readJsonConfigFile(configFileName, path => this.sys.readFile(path)); @@ -178,7 +178,7 @@ namespace project { public static getConfigurations(testCaseFileName: string): ProjectTestConfiguration[] { let testCase: ProjectRunnerTestCase & ts.CompilerOptions; - let testFileText: string; + let testFileText: string | undefined; try { testFileText = Harness.IO.readFile(testCaseFileName); } @@ -187,10 +187,10 @@ namespace project { } try { - testCase = JSON.parse(testFileText); + testCase = JSON.parse(testFileText!); } catch (e) { - assert(false, "Testcase: " + testCaseFileName + " does not contain valid json format: " + e.message); + throw assert(false, "Testcase: " + testCaseFileName + " does not contain valid json format: " + e.message); } const fs = vfs.createFromFileSystem(Harness.IO, /*ignoreCase*/ false); @@ -209,12 +209,12 @@ namespace project { const cwd = this.vfs.cwd(); const ignoreCase = this.vfs.ignoreCase; const resolutionInfo: ProjectRunnerTestCaseResolutionInfo & ts.CompilerOptions = JSON.parse(JSON.stringify(this.testCase)); - resolutionInfo.resolvedInputFiles = this.compilerResult.program.getSourceFiles() + resolutionInfo.resolvedInputFiles = this.compilerResult.program!.getSourceFiles() .map(({ fileName: input }) => vpath.beneath(vfs.builtFolder, input, this.vfs.ignoreCase) || vpath.beneath(vfs.testLibFolder, input, this.vfs.ignoreCase) ? utils.removeTestPathPrefixes(input) : vpath.isAbsolute(input) ? vpath.relative(cwd, input, ignoreCase) : input); - resolutionInfo.emittedFiles = this.compilerResult.outputFiles + resolutionInfo.emittedFiles = this.compilerResult.outputFiles! .map(output => output.meta.get("fileName") || output.file) .map(output => utils.removeTestPathPrefixes(vpath.isAbsolute(output) ? vpath.relative(cwd, output, ignoreCase) : output)); @@ -234,7 +234,7 @@ namespace project { if (this.testCase.baselineCheck) { const errs: Error[] = []; let nonSubfolderDiskFiles = 0; - for (const output of this.compilerResult.outputFiles) { + for (const output of this.compilerResult.outputFiles!) { try { // convert file name to rooted name // if filename is not rooted - concat it with project root and then expand project root relative to current directory @@ -252,7 +252,7 @@ namespace project { } const content = utils.removeTestPathPrefixes(output.text, /*retainTrailingDirectorySeparator*/ true); - Harness.Baseline.runBaseline(this.getBaselineFolder(this.compilerResult.moduleKind) + diskRelativeName, () => content); + Harness.Baseline.runBaseline(this.getBaselineFolder(this.compilerResult.moduleKind) + diskRelativeName, () => content as string | null); // TODO: GH#18217 } catch (e) { errs.push(e); @@ -292,7 +292,7 @@ namespace project { } private cleanProjectUrl(url: string) { - let diskProjectPath = ts.normalizeSlashes(Harness.IO.resolvePath(this.testCase.projectRoot)); + let diskProjectPath = ts.normalizeSlashes(Harness.IO.resolvePath(this.testCase.projectRoot)!); let projectRootUrl = "file:///" + diskProjectPath; const normalizedProjectRoot = ts.normalizeSlashes(this.testCase.projectRoot); diskProjectPath = diskProjectPath.substr(0, diskProjectPath.lastIndexOf(normalizedProjectRoot)); @@ -362,10 +362,10 @@ namespace project { rootFiles.unshift(sourceFile.fileName); } else if (!(compilerOptions.outFile || compilerOptions.out)) { - let emitOutputFilePathWithoutExtension: string; + let emitOutputFilePathWithoutExtension: string | undefined; if (compilerOptions.outDir) { - let sourceFilePath = ts.getNormalizedAbsolutePath(sourceFile.fileName, compilerResult.program.getCurrentDirectory()); - sourceFilePath = sourceFilePath.replace(compilerResult.program.getCommonSourceDirectory(), ""); + let sourceFilePath = ts.getNormalizedAbsolutePath(sourceFile.fileName, compilerResult.program!.getCurrentDirectory()); + sourceFilePath = sourceFilePath.replace(compilerResult.program!.getCommonSourceDirectory(), ""); emitOutputFilePathWithoutExtension = ts.removeFileExtension(ts.combinePaths(compilerOptions.outDir, sourceFilePath)); } else { @@ -380,8 +380,8 @@ namespace project { } } else { - const outputDtsFileName = ts.removeFileExtension(compilerOptions.outFile || compilerOptions.out) + ts.Extension.Dts; - const outputDtsFile = findOutputDtsFile(outputDtsFileName); + const outputDtsFileName = ts.removeFileExtension(compilerOptions.outFile || compilerOptions.out!) + ts.Extension.Dts; + const outputDtsFile = findOutputDtsFile(outputDtsFileName)!; if (!ts.contains(allInputFiles, outputDtsFile)) { allInputFiles.unshift(outputDtsFile); rootFiles.unshift(outputDtsFile.meta.get("fileName") || outputDtsFile.file); @@ -395,8 +395,8 @@ namespace project { }); // Dont allow config files since we are compiling existing source options - const compilerHost = new ProjectCompilerHost(_vfs, compilerResult.compilerOptions, this.testCaseJustName, this.testCase, compilerResult.moduleKind); - return this.compileProjectFiles(compilerResult.moduleKind, compilerResult.configFileSourceFiles, () => rootFiles, compilerHost, compilerResult.compilerOptions); + const compilerHost = new ProjectCompilerHost(_vfs, compilerResult.compilerOptions!, this.testCaseJustName, this.testCase, compilerResult.moduleKind); + return this.compileProjectFiles(compilerResult.moduleKind, compilerResult.configFileSourceFiles, () => rootFiles, compilerHost, compilerResult.compilerOptions!); function findOutputDtsFile(fileName: string) { return ts.forEach(compilerResult.outputFiles, outputFile => outputFile.meta.get("fileName") === fileName ? outputFile : undefined); diff --git a/src/harness/runner.ts b/src/harness/runner.ts index 8bcc7605048f9..9fe48b559f2d2 100644 --- a/src/harness/runner.ts +++ b/src/harness/runner.ts @@ -65,7 +65,7 @@ function createRunner(kind: TestRunnerKind): RunnerBase { case "dt": return new DefinitelyTypedRunner(); } - ts.Debug.fail(`Unknown runner kind ${kind}`); + return ts.Debug.fail(`Unknown runner kind ${kind}`); } // users can define tests to run in mytest.config that will override cmd line args, otherwise use cmd line args (test.config), otherwise no options @@ -76,10 +76,10 @@ const testconfigFileName = "test.config"; const customConfig = tryGetConfig(Harness.IO.args()); let testConfigContent = customConfig && Harness.IO.fileExists(customConfig) - ? Harness.IO.readFile(customConfig) + ? Harness.IO.readFile(customConfig)! : Harness.IO.fileExists(mytestconfigFileName) - ? Harness.IO.readFile(mytestconfigFileName) - : Harness.IO.fileExists(testconfigFileName) ? Harness.IO.readFile(testconfigFileName) : ""; + ? Harness.IO.readFile(mytestconfigFileName)! + : Harness.IO.fileExists(testconfigFileName) ? Harness.IO.readFile(testconfigFileName)! : ""; let taskConfigsFolder: string; let workerCount: number; @@ -131,9 +131,9 @@ function handleTestConfig() { (Error).stackTraceLimit = Infinity; stackTraceLimit = testConfig.stackTraceLimit; } - else if ((+testConfig.stackTraceLimit | 0) > 0) { - (Error).stackTraceLimit = +testConfig.stackTraceLimit | 0; - stackTraceLimit = +testConfig.stackTraceLimit | 0; + else if ((+testConfig.stackTraceLimit! | 0) > 0) { + (Error).stackTraceLimit = +testConfig.stackTraceLimit! | 0; + stackTraceLimit = +testConfig.stackTraceLimit! | 0; } if (testConfig.listenForWork) { return true; @@ -222,6 +222,7 @@ function handleTestConfig() { if (runUnitTests === undefined) { runUnitTests = runners.length !== 1; // Don't run unit tests when running only one runner if unit tests were not explicitly asked for } + return false; } function beginTests() { diff --git a/src/harness/rwcRunner.ts b/src/harness/rwcRunner.ts index d0fe3a04c1fb4..72a372036ccfa 100644 --- a/src/harness/rwcRunner.ts +++ b/src/harness/rwcRunner.ts @@ -41,22 +41,22 @@ namespace RWC { inputFiles = []; otherFiles = []; tsconfigFiles = []; - compilerResult = undefined; - compilerOptions = undefined; - currentDirectory = undefined; + compilerResult = undefined!; + compilerOptions = undefined!; + currentDirectory = undefined!; // useCustomLibraryFile is a flag specified in the json object to indicate whether to use built/local/lib.d.ts // or to use lib.d.ts inside the json object. If the flag is true, use the lib.d.ts inside json file // otherwise use the lib.d.ts from built/local - useCustomLibraryFile = undefined; + useCustomLibraryFile = undefined!; }); it("can compile", function(this: Mocha.ITestCallbackContext) { this.timeout(800_000); // Allow long timeouts for RWC compilations - let opts: ts.ParsedCommandLine; + let opts!: ts.ParsedCommandLine; - const ioLog: IoLog = Playback.newStyleLogIntoOldStyleLog(JSON.parse(Harness.IO.readFile(`internal/cases/rwc/${jsonPath}/test.json`)), Harness.IO, `internal/cases/rwc/${baseName}`); + const ioLog: IoLog = Playback.newStyleLogIntoOldStyleLog(JSON.parse(Harness.IO.readFile(`internal/cases/rwc/${jsonPath}/test.json`)!), Harness.IO, `internal/cases/rwc/${baseName}`); currentDirectory = ioLog.currentDirectory; - useCustomLibraryFile = ioLog.useCustomLibraryFile; + useCustomLibraryFile = !!ioLog.useCustomLibraryFile; runWithIOLog(ioLog, () => { opts = ts.parseCommandLine(ioLog.arguments, fileName => Harness.IO.readFile(fileName)); assert.equal(opts.errors.length, 0); @@ -89,7 +89,7 @@ namespace RWC { const uniqueNames = ts.createMap(); for (const fileName of fileNames) { // Must maintain order, build result list while checking map - const normalized = ts.normalizeSlashes(Harness.IO.resolvePath(fileName)); + const normalized = ts.normalizeSlashes(Harness.IO.resolvePath(fileName)!); if (!uniqueNames.has(normalized)) { uniqueNames.set(normalized, true); // Load the file @@ -99,7 +99,7 @@ namespace RWC { // Add files to compilation for (const fileRead of ioLog.filesRead) { - const unitName = ts.normalizeSlashes(Harness.IO.resolvePath(fileRead.path)); + const unitName = ts.normalizeSlashes(Harness.IO.resolvePath(fileRead.path)!); if (!uniqueNames.has(unitName) && !Harness.isDefaultLibraryFile(fileRead.path)) { uniqueNames.set(unitName, true); otherFiles.push(getHarnessCompilerInputUnit(unitName)); @@ -134,13 +134,13 @@ namespace RWC { compilerOptions = compilerResult.options; function getHarnessCompilerInputUnit(fileName: string): Harness.Compiler.TestFile { - const unitName = ts.normalizeSlashes(Harness.IO.resolvePath(fileName)); + const unitName = ts.normalizeSlashes(Harness.IO.resolvePath(fileName)!); let content: string; try { - content = Harness.IO.readFile(unitName); + content = Harness.IO.readFile(unitName)!; } catch (e) { - content = Harness.IO.readFile(fileName); + content = Harness.IO.readFile(fileName)!; } return { unitName, content }; } @@ -196,11 +196,11 @@ namespace RWC { } const declContext = Harness.Compiler.prepareDeclarationCompilationContext( - inputFiles, otherFiles, compilerResult, /*harnessSettings*/ undefined, compilerOptions, currentDirectory + inputFiles, otherFiles, compilerResult, /*harnessSettings*/ undefined!, compilerOptions, currentDirectory // TODO: GH#18217 ); // Reset compilerResult before calling into `compileDeclarationFiles` so the memory from the original compilation can be freed - compilerResult = undefined; - const declFileCompilationResult = Harness.Compiler.compileDeclarationFiles(declContext); + compilerResult = undefined!; + const declFileCompilationResult = Harness.Compiler.compileDeclarationFiles(declContext)!; return Harness.Compiler.iterateErrorBaseline(tsconfigFiles.concat(declFileCompilationResult.declInputFiles, declFileCompilationResult.declOtherFiles), declFileCompilationResult.declResult.diagnostics); }, baselineOpts); diff --git a/src/harness/sourceMapRecorder.ts b/src/harness/sourceMapRecorder.ts index 1e13e3833a4bb..0804c281200d5 100644 --- a/src/harness/sourceMapRecorder.ts +++ b/src/harness/sourceMapRecorder.ts @@ -19,16 +19,16 @@ namespace Harness.SourceMapRecorder { interface SourceMapSpanWithDecodeErrors { sourceMapSpan: ts.SourceMapSpan; - decodeErrors: string[]; + decodeErrors: string[] | undefined; } namespace SourceMapDecoder { let sourceMapMappings: string; - let sourceMapNames: string[]; + let sourceMapNames: string[] | undefined; let decodingIndex: number; let prevNameIndex: number; let decodeOfEncodedMapping: ts.SourceMapSpan; - let errorDecodeOfEncodedMapping: string; + let errorDecodeOfEncodedMapping: string | undefined; export function initializeSourceMapDecoding(sourceMapData: ts.SourceMapData) { sourceMapMappings = sourceMapData.sourceMapMappings; @@ -88,7 +88,7 @@ namespace Harness.SourceMapRecorder { for (; moreDigits; decodingIndex++) { if (createErrorIfCondition(decodingIndex >= sourceMapMappings.length, "Error in decoding base64VLQFormatDecode, past the mapping string")) { - return; + return undefined!; // TODO: GH#18217 } // 6 digit number @@ -176,7 +176,7 @@ namespace Harness.SourceMapRecorder { prevNameIndex += base64VLQFormatDecode(); decodeOfEncodedMapping.nameIndex = prevNameIndex; // Incorrect nameIndex dont support this map - if (createErrorIfCondition(decodeOfEncodedMapping.nameIndex < 0 || decodeOfEncodedMapping.nameIndex >= sourceMapNames.length, "Invalid name index for the source map entry")) { + if (createErrorIfCondition(decodeOfEncodedMapping.nameIndex < 0 || decodeOfEncodedMapping.nameIndex >= sourceMapNames!.length, "Invalid name index for the source map entry")) { return { error: errorDecodeOfEncodedMapping, sourceMapSpan: decodeOfEncodedMapping }; } } @@ -190,6 +190,7 @@ namespace Harness.SourceMapRecorder { } createErrorIfCondition(/*condition*/ true, "No encoded entry found"); + return undefined!; // TODO: GH#18217 } export function hasCompletedDecoding() { @@ -204,7 +205,7 @@ namespace Harness.SourceMapRecorder { namespace SourceMapSpanWriter { let sourceMapRecorder: Compiler.WriterAggregator; let sourceMapSources: string[]; - let sourceMapNames: string[]; + let sourceMapNames: string[] | undefined; let jsFile: documents.TextDocument; let jsLineMap: ReadonlyArray; @@ -244,8 +245,8 @@ namespace Harness.SourceMapRecorder { function getSourceMapSpanString(mapEntry: ts.SourceMapSpan, getAbsentNameIndex?: boolean) { let mapString = "Emitted(" + mapEntry.emittedLine + ", " + mapEntry.emittedColumn + ") Source(" + mapEntry.sourceLine + ", " + mapEntry.sourceColumn + ") + SourceIndex(" + mapEntry.sourceIndex + ")"; - if (mapEntry.nameIndex >= 0 && mapEntry.nameIndex < sourceMapNames.length) { - mapString += " name (" + sourceMapNames[mapEntry.nameIndex] + ")"; + if (mapEntry.nameIndex! >= 0 && mapEntry.nameIndex! < sourceMapNames!.length) { + mapString += " name (" + sourceMapNames![mapEntry.nameIndex!] + ")"; } else { if ((mapEntry.nameIndex && mapEntry.nameIndex !== -1) || getAbsentNameIndex) { @@ -259,7 +260,7 @@ namespace Harness.SourceMapRecorder { export function recordSourceMapSpan(sourceMapSpan: ts.SourceMapSpan) { // verify the decoded span is same as the new span const decodeResult = SourceMapDecoder.decodeNextEncodedSourceMapSpan(); - let decodeErrors: string[]; + let decodeErrors: string[] | undefined; if (decodeResult.error || decodeResult.sourceMapSpan.emittedLine !== sourceMapSpan.emittedLine || decodeResult.sourceMapSpan.emittedColumn !== sourceMapSpan.emittedColumn @@ -345,7 +346,7 @@ namespace Harness.SourceMapRecorder { return markerId; } - let prevEmittedCol: number; + let prevEmittedCol!: number; function iterateSpans(fn: (currentSpan: SourceMapSpanWithDecodeErrors, index: number) => void) { prevEmittedCol = 1; for (let i = 0; i < spansOnSingleLine.length; i++) { @@ -361,7 +362,7 @@ namespace Harness.SourceMapRecorder { } } - function writeSourceMapMarker(currentSpan: SourceMapSpanWithDecodeErrors, index: number, endColumn = currentSpan.sourceMapSpan.emittedColumn, endContinues?: boolean) { + function writeSourceMapMarker(currentSpan: SourceMapSpanWithDecodeErrors, index: number, endColumn = currentSpan.sourceMapSpan.emittedColumn, endContinues = false) { const markerId = getMarkerId(index); markerIds.push(markerId); @@ -421,7 +422,7 @@ namespace Harness.SourceMapRecorder { const jsFileText = getTextOfLine(currentJsLine, jsLineMap, jsFile.text); if (prevEmittedCol < jsFileText.length) { // There is remaining text on this line that will be part of next source span so write marker that continues - writeSourceMapMarker(/*currentSpan*/ undefined, spansOnSingleLine.length, /*endColumn*/ jsFileText.length, /*endContinues*/ true); + writeSourceMapMarker(/*currentSpan*/ undefined!, spansOnSingleLine.length, /*endColumn*/ jsFileText.length, /*endContinues*/ true); // TODO: GH#18217 } // Emit Source text @@ -440,7 +441,7 @@ namespace Harness.SourceMapRecorder { for (let i = 0; i < sourceMapDataList.length; i++) { const sourceMapData = sourceMapDataList[i]; - let prevSourceFile: ts.SourceFile; + let prevSourceFile: ts.SourceFile | undefined; let currentFile: documents.TextDocument; if (ts.endsWith(sourceMapData.sourceMapFile, ts.Extension.Dts)) { if (sourceMapDataList.length > jsFiles.length) { @@ -461,7 +462,7 @@ namespace Harness.SourceMapRecorder { SourceMapSpanWriter.initializeSourceMapSpanWriter(sourceMapRecorder, sourceMapData, currentFile); for (const decodedSourceMapping of sourceMapData.sourceMapDecodedMappings) { - const currentSourceFile = program.getSourceFile(sourceMapData.inputSourceFileNames[decodedSourceMapping.sourceIndex]); + const currentSourceFile = program.getSourceFile(sourceMapData.inputSourceFileNames[decodedSourceMapping.sourceIndex])!; if (currentSourceFile !== prevSourceFile) { SourceMapSpanWriter.recordNewSourceFileSpan(decodedSourceMapping, currentSourceFile.text); prevSourceFile = currentSourceFile; diff --git a/src/harness/test262Runner.ts b/src/harness/test262Runner.ts index 7f83d9101bdd3..1c421d07a3ee4 100644 --- a/src/harness/test262Runner.ts +++ b/src/harness/test262Runner.ts @@ -8,7 +8,7 @@ class Test262BaselineRunner extends RunnerBase { private static readonly helpersFilePath = "tests/cases/test262-harness/helpers.d.ts"; private static readonly helperFile: Harness.Compiler.TestFile = { unitName: Test262BaselineRunner.helpersFilePath, - content: Harness.IO.readFile(Test262BaselineRunner.helpersFilePath), + content: Harness.IO.readFile(Test262BaselineRunner.helpersFilePath)!, }; private static readonly testFileExtensionRegex = /\.js$/; private static readonly options: ts.CompilerOptions = { @@ -36,7 +36,7 @@ class Test262BaselineRunner extends RunnerBase { }; before(() => { - const content = Harness.IO.readFile(filePath); + const content = Harness.IO.readFile(filePath)!; const testFilename = ts.removeFileExtension(filePath).replace(/\//g, "_") + ".test"; const testCaseContent = Harness.TestCaseParser.makeUnitsFromTest(content, testFilename); @@ -49,7 +49,7 @@ class Test262BaselineRunner extends RunnerBase { testState = { filename: testFilename, inputFiles, - compilerResult: undefined, + compilerResult: undefined!, // TODO: GH#18217 }; testState.compilerResult = Harness.Compiler.compileFiles( @@ -61,7 +61,7 @@ class Test262BaselineRunner extends RunnerBase { }); after(() => { - testState = undefined; + testState = undefined!; }); it("has the expected emitted code", () => { @@ -83,13 +83,13 @@ class Test262BaselineRunner extends RunnerBase { }); it("satisfies invariants", () => { - const sourceFile = testState.compilerResult.program.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename)); + const sourceFile = testState.compilerResult.program!.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename)); Utils.assertInvariants(sourceFile, /*parent:*/ undefined); }); it("has the expected AST", () => { Harness.Baseline.runBaseline(testState.filename + ".AST.txt", () => { - const sourceFile = testState.compilerResult.program.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename)); + const sourceFile = testState.compilerResult.program!.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename))!; return Utils.sourceFileToJSON(sourceFile); }, Test262BaselineRunner.baselineOptions); }); diff --git a/src/harness/typeWriter.ts b/src/harness/typeWriter.ts index 0a2d2d7e6571a..602ed458c93bc 100644 --- a/src/harness/typeWriter.ts +++ b/src/harness/typeWriter.ts @@ -34,7 +34,7 @@ class TypeWriterWalker { } public *getSymbols(fileName: string): IterableIterator { - const sourceFile = this.program.getSourceFile(fileName); + const sourceFile = this.program.getSourceFile(fileName)!; this.currentSourceFile = sourceFile; const gen = this.visitNode(sourceFile, /*isSymbolWalk*/ true); for (let {done, value} = gen.next(); !done; { done, value } = gen.next()) { @@ -43,7 +43,7 @@ class TypeWriterWalker { } public *getTypes(fileName: string): IterableIterator { - const sourceFile = this.program.getSourceFile(fileName); + const sourceFile = this.program.getSourceFile(fileName)!; this.currentSourceFile = sourceFile; const gen = this.visitNode(sourceFile, /*isSymbolWalk*/ false); for (let {done, value} = gen.next(); !done; { done, value } = gen.next()) { @@ -69,7 +69,7 @@ class TypeWriterWalker { } } - private writeTypeOrSymbol(node: ts.Node, isSymbolWalk: boolean): TypeWriterResult { + private writeTypeOrSymbol(node: ts.Node, isSymbolWalk: boolean): TypeWriterResult | undefined { const actualPos = ts.skipTrivia(this.currentSourceFile.text, node.pos); const lineAndCharacter = this.currentSourceFile.getLineAndCharacterOfPosition(actualPos); const sourceText = ts.getSourceTextOfNodeFromSourceFile(this.currentSourceFile, node); diff --git a/src/harness/unittests/builder.ts b/src/harness/unittests/builder.ts index 3a275d39e868b..3dcf3174f6f3d 100644 --- a/src/harness/unittests/builder.ts +++ b/src/harness/unittests/builder.ts @@ -120,7 +120,7 @@ namespace ts { operationWasCancelled = true; } assert.equal(cancel, operationWasCancelled); - assert.equal(operationWasCancelled, fileNames.length > cancelAfterEmitLength); + assert.equal(operationWasCancelled, fileNames.length > cancelAfterEmitLength!); assert.deepEqual(outputFileNames, fileNames.slice(0, cancelAfterEmitLength)); }; } diff --git a/src/harness/unittests/cancellableLanguageServiceOperations.ts b/src/harness/unittests/cancellableLanguageServiceOperations.ts index 7ae85ce2cba46..161b45841f31a 100644 --- a/src/harness/unittests/cancellableLanguageServiceOperations.ts +++ b/src/harness/unittests/cancellableLanguageServiceOperations.ts @@ -10,21 +10,21 @@ namespace ts { `; it("can cancel signature help mid-request", () => { verifyOperationCancelledAfter(file, 4, service => // Two calls are top-level in services, one is the root type, and the second should be for the parameter type - service.getSignatureHelpItems("file.ts", file.lastIndexOf("f")), + service.getSignatureHelpItems("file.ts", file.lastIndexOf("f"))!, r => assert.exists(r.items[0]) ); }); it("can cancel find all references mid-request", () => { verifyOperationCancelledAfter(file, 3, service => // Two calls are top-level in services, one is the root type - service.findReferences("file.ts", file.lastIndexOf("o")), + service.findReferences("file.ts", file.lastIndexOf("o"))!, r => assert.exists(r[0].definition) ); }); it("can cancel quick info mid-request", () => { verifyOperationCancelledAfter(file, 1, service => // The LS doesn't do any top-level checks on the token for quickinfo, so the first check is within the checker - service.getQuickInfoAtPosition("file.ts", file.lastIndexOf("o")), + service.getQuickInfoAtPosition("file.ts", file.lastIndexOf("o"))!, r => assert.exists(r.displayParts) ); }); @@ -52,7 +52,7 @@ namespace ts { placeOpenBraceOnNewLineForControlBlocks: false, }; verifyOperationCancelledAfter(file, 1, service => // The LS doesn't do any top-level checks on the token for completion entry details, so the first check is within the checker - service.getCompletionEntryDetails("file.ts", file.lastIndexOf("f"), "foo", options, /*content*/ undefined, {}), + service.getCompletionEntryDetails("file.ts", file.lastIndexOf("f"), "foo", options, /*content*/ undefined, {})!, r => assert.exists(r.displayParts) ); }); diff --git a/src/harness/unittests/compileOnSave.ts b/src/harness/unittests/compileOnSave.ts index df73c575b154f..587ac3dbb5e3a 100644 --- a/src/harness/unittests/compileOnSave.ts +++ b/src/harness/unittests/compileOnSave.ts @@ -601,7 +601,7 @@ namespace ts.projectSystem { const expectedOutFileName = "/a/b/dist.js"; assert.isTrue(host.fileExists(expectedOutFileName)); - const outFileContent = host.readFile(expectedOutFileName); + const outFileContent = host.readFile(expectedOutFileName)!; assert.isTrue(outFileContent.indexOf(file1.content) !== -1); assert.isTrue(outFileContent.indexOf(file2.content) === -1); assert.isTrue(outFileContent.indexOf(file3.content) === -1); @@ -635,14 +635,14 @@ namespace ts.projectSystem { // Verify js file const expectedOutFileName = "/root/TypeScriptProject3/TypeScriptProject3/" + outFileName; assert.isTrue(host.fileExists(expectedOutFileName)); - const outFileContent = host.readFile(expectedOutFileName); + const outFileContent = host.readFile(expectedOutFileName)!; verifyContentHasString(outFileContent, file1.content); verifyContentHasString(outFileContent, `//# ${"sourceMappingURL"}=${outFileName}.map`); // Sometimes tools can sometimes see this line as a source mapping url comment, so we obfuscate it a little // Verify map file const expectedMapFileName = expectedOutFileName + ".map"; assert.isTrue(host.fileExists(expectedMapFileName)); - const mapFileContent = host.readFile(expectedMapFileName); + const mapFileContent = host.readFile(expectedMapFileName)!; verifyContentHasString(mapFileContent, `"sources":["${inputFileName}"]`); function verifyContentHasString(content: string, str: string) { diff --git a/src/harness/unittests/convertTypeAcquisitionFromJson.ts b/src/harness/unittests/convertTypeAcquisitionFromJson.ts index 4b43d10275665..7faf0b8fdf9cb 100644 --- a/src/harness/unittests/convertTypeAcquisitionFromJson.ts +++ b/src/harness/unittests/convertTypeAcquisitionFromJson.ts @@ -11,7 +11,7 @@ namespace ts { assertTypeAcquisitionWithJsonNode(json, configFileName, expectedResult); } - function verifyAcquisition(actualTypeAcquisition: TypeAcquisition, expectedResult: ExpectedResult) { + function verifyAcquisition(actualTypeAcquisition: TypeAcquisition | undefined, expectedResult: ExpectedResult) { const parsedTypeAcquisition = JSON.stringify(actualTypeAcquisition); const expectedTypeAcquisition = JSON.stringify(expectedResult.typeAcquisition); assert.equal(parsedTypeAcquisition, expectedTypeAcquisition); @@ -120,7 +120,7 @@ namespace ts { file: undefined, start: 0, length: 0, - messageText: undefined + messageText: undefined!, // TODO: GH#18217 } ] }); @@ -215,7 +215,7 @@ namespace ts { file: undefined, start: 0, length: 0, - messageText: undefined + messageText: undefined!, // TODO: GH#18217 } ] }); diff --git a/src/harness/unittests/customTransforms.ts b/src/harness/unittests/customTransforms.ts index f47bdad5d588d..47aaf16acec57 100644 --- a/src/harness/unittests/customTransforms.ts +++ b/src/harness/unittests/customTransforms.ts @@ -17,7 +17,7 @@ namespace ts { useCaseSensitiveFileNames: () => true, getNewLine: () => "\n", fileExists: (fileName) => fileMap.has(fileName), - readFile: (fileName) => fileMap.has(fileName) ? fileMap.get(fileName).text : undefined, + readFile: (fileName) => fileMap.has(fileName) ? fileMap.get(fileName)!.text : undefined, writeFile: (fileName, text) => outputs.set(fileName, text), }; diff --git a/src/harness/unittests/extractRanges.ts b/src/harness/unittests/extractRanges.ts index 68d8289d20615..7393775676988 100644 --- a/src/harness/unittests/extractRanges.ts +++ b/src/harness/unittests/extractRanges.ts @@ -11,7 +11,7 @@ namespace ts { } const result = refactor.extractSymbol.getRangeToExtract(file, createTextSpanFromRange(selectionRange)); assert(result.targetRange === undefined, "failure expected"); - const sortedErrors = result.errors.map(e => e.messageText).sort(); + const sortedErrors = result.errors!.map(e => e.messageText).sort(); assert.deepEqual(sortedErrors, expectedErrors.sort(), "unexpected errors"); }); } @@ -27,13 +27,14 @@ namespace ts { const expectedRange = t.ranges.get("extracted"); if (expectedRange) { let pos: number, end: number; - if (isArray(result.targetRange.range)) { - pos = result.targetRange.range[0].getStart(f); - end = lastOrUndefined(result.targetRange.range).getEnd(); + const targetRange = result.targetRange!; + if (isArray(targetRange.range)) { + pos = targetRange.range[0].getStart(f); + end = last(targetRange.range).getEnd(); } else { - pos = result.targetRange.range.getStart(f); - end = result.targetRange.range.getEnd(); + pos = targetRange.range.getStart(f); + end = targetRange.range.getEnd(); } assert.equal(pos, expectedRange.pos, "incorrect pos of range"); assert.equal(end, expectedRange.end, "incorrect end of range"); diff --git a/src/harness/unittests/extractTestHelpers.ts b/src/harness/unittests/extractTestHelpers.ts index eaf90a211ccdc..252112cddac88 100644 --- a/src/harness/unittests/extractTestHelpers.ts +++ b/src/harness/unittests/extractTestHelpers.ts @@ -34,7 +34,7 @@ namespace ts { const name = s === e ? source.charCodeAt(saved + 1) === CharacterCodes.hash ? "selection" : "extracted" : source.substring(s, e); - activeRanges.push({ name, pos: text.length, end: undefined }); + activeRanges.push({ name, pos: text.length, end: undefined! }); // TODO: GH#18217 lastPos = pos; continue; } @@ -45,7 +45,7 @@ namespace ts { else if (source.charCodeAt(pos) === CharacterCodes.bar && source.charCodeAt(pos + 1) === CharacterCodes.closeBracket) { text += source.substring(lastPos, pos); activeRanges[activeRanges.length - 1].end = text.length; - const range = activeRanges.pop(); + const range = activeRanges.pop()!; if (range.name in ranges) { throw new Error(`Duplicate name of range ${range.name}`); } @@ -100,7 +100,7 @@ namespace ts { export function testExtractSymbol(caption: string, text: string, baselineFolder: string, description: DiagnosticMessage, includeLib?: boolean) { const t = extractTest(text); - const selectionRange = t.ranges.get("selection"); + const selectionRange = t.ranges.get("selection")!; if (!selectionRange) { throw new Error(`Test ${caption} does not specify selection range`); } @@ -118,7 +118,7 @@ namespace ts { return; } - const sourceFile = program.getSourceFile(path); + const sourceFile = program.getSourceFile(path)!; const context: RefactorContext = { cancellationToken: { throwIfCancellationRequested: noop, isCancellationRequested: returnFalse }, program, @@ -131,15 +131,15 @@ namespace ts { }; const rangeToExtract = refactor.extractSymbol.getRangeToExtract(sourceFile, createTextSpanFromRange(selectionRange)); assert.equal(rangeToExtract.errors, undefined, rangeToExtract.errors && "Range error: " + rangeToExtract.errors[0].messageText); - const infos = refactor.extractSymbol.getAvailableActions(context); - const actions = find(infos, info => info.description === description.message).actions; + const infos = refactor.extractSymbol.getAvailableActions(context)!; + const actions = find(infos, info => info.description === description.message)!.actions; Harness.Baseline.runBaseline(`${baselineFolder}/${caption}${extension}`, () => { const data: string[] = []; data.push(`// ==ORIGINAL==`); data.push(text.replace("[#|", "/*[#|*/").replace("|]", "/*|]*/")); for (const action of actions) { - const { renameLocation, edits } = refactor.extractSymbol.getEditsForAction(context, action.name); + const { renameLocation, edits } = refactor.extractSymbol.getEditsForAction(context, action.name)!; assert.lengthOf(edits, 1); data.push(`// ==SCOPE::${action.description}==`); const newText = textChanges.applyChanges(sourceFile.text, edits[0].textChanges); @@ -157,7 +157,7 @@ namespace ts { const host = projectSystem.createServerHost(includeLib ? [f, projectSystem.libFile] : [f]); // libFile is expensive to parse repeatedly - only test when required const projectService = projectSystem.createProjectService(host); projectService.openClientFile(f.path); - const program = projectService.inferredProjects[0].getLanguageService().getProgram(); + const program = projectService.inferredProjects[0].getLanguageService().getProgram()!; return program; } @@ -181,8 +181,8 @@ namespace ts { const host = projectSystem.createServerHost([f, projectSystem.libFile]); const projectService = projectSystem.createProjectService(host); projectService.openClientFile(f.path); - const program = projectService.inferredProjects[0].getLanguageService().getProgram(); - const sourceFile = program.getSourceFile(f.path); + const program = projectService.inferredProjects[0].getLanguageService().getProgram()!; + const sourceFile = program.getSourceFile(f.path)!; const context: RefactorContext = { cancellationToken: { throwIfCancellationRequested: noop, isCancellationRequested: returnFalse }, program, @@ -195,7 +195,7 @@ namespace ts { }; const rangeToExtract = refactor.extractSymbol.getRangeToExtract(sourceFile, createTextSpanFromRange(selectionRange)); assert.isUndefined(rangeToExtract.errors, rangeToExtract.errors && "Range error: " + rangeToExtract.errors[0].messageText); - const infos = refactor.extractSymbol.getAvailableActions(context); + const infos = refactor.extractSymbol.getAvailableActions(context)!; assert.isUndefined(find(infos, info => info.description === description.message)); }); } diff --git a/src/harness/unittests/hostNewLineSupport.ts b/src/harness/unittests/hostNewLineSupport.ts index 34543f2ec6f2f..fee58d92e4f90 100644 --- a/src/harness/unittests/hostNewLineSupport.ts +++ b/src/harness/unittests/hostNewLineSupport.ts @@ -2,7 +2,7 @@ namespace ts { describe("hostNewLineSupport", () => { function testLSWithFiles(settings: CompilerOptions, files: Harness.Compiler.TestFile[]) { - function snapFor(path: string): IScriptSnapshot { + function snapFor(path: string): IScriptSnapshot | undefined { if (path === "lib.d.ts") { return ScriptSnapshot.fromString(""); } diff --git a/src/harness/unittests/jsDocParsing.ts b/src/harness/unittests/jsDocParsing.ts index fbd9e761625cc..cad5ed94b32ea 100644 --- a/src/harness/unittests/jsDocParsing.ts +++ b/src/harness/unittests/jsDocParsing.ts @@ -10,7 +10,7 @@ namespace ts { assert.isTrue(typeAndDiagnostics && typeAndDiagnostics.diagnostics.length === 0, "no errors issued"); Harness.Baseline.runBaseline("JSDocParsing/TypeExpressions.parsesCorrectly." + name + ".json", - () => Utils.sourceFileToJSON(typeAndDiagnostics.jsDocTypeExpression.type)); + () => Utils.sourceFileToJSON(typeAndDiagnostics!.jsDocTypeExpression.type)); }); } @@ -89,7 +89,7 @@ namespace ts { describe("DocComments", () => { function parsesCorrectly(name: string, content: string) { it(name, () => { - const comment = parseIsolatedJSDocComment(content); + const comment = parseIsolatedJSDocComment(content)!; if (!comment) { Debug.fail("Comment failed to parse entirely"); } @@ -320,7 +320,7 @@ namespace ts { assert.equal(root.kind, SyntaxKind.SourceFile); const first = root.getFirstToken(); assert.isDefined(first); - assert.equal(first.kind, SyntaxKind.VarKeyword); + assert.equal(first!.kind, SyntaxKind.VarKeyword); }); }); describe("getLastToken", () => { @@ -329,7 +329,7 @@ namespace ts { assert.isDefined(root); const last = root.getLastToken(); assert.isDefined(last); - assert.equal(last.kind, SyntaxKind.EndOfFileToken); + assert.equal(last!.kind, SyntaxKind.EndOfFileToken); }); }); }); diff --git a/src/harness/unittests/moduleResolution.ts b/src/harness/unittests/moduleResolution.ts index b5c527aa246df..bc221dc8b0766 100644 --- a/src/harness/unittests/moduleResolution.ts +++ b/src/harness/unittests/moduleResolution.ts @@ -1,7 +1,7 @@ /// namespace ts { - export function checkResolvedModule(expected: ResolvedModuleFull, actual: ResolvedModuleFull): boolean { + export function checkResolvedModule(expected: ResolvedModuleFull | undefined, actual: ResolvedModuleFull): boolean { if (!expected === !actual) { if (expected) { assert.isTrue(expected.resolvedFileName === actual.resolvedFileName, `'resolvedFileName': expected '${expected.resolvedFileName}' to be equal to '${actual.resolvedFileName}'`); @@ -71,7 +71,7 @@ namespace ts { return file && file.content; } function realpath(path: string): string { - return map.get(path).name; + return map.get(path)!.name; } } @@ -332,7 +332,7 @@ namespace ts { getSourceFile: (fileName: string, languageVersion: ScriptTarget) => { const path = normalizePath(combinePaths(currentDirectory, fileName)); const file = files.get(path); - return file && createSourceFile(fileName, file, languageVersion); + return file ? createSourceFile(fileName, file, languageVersion) : undefined; }, getDefaultLibFileName: () => "lib.d.ts", writeFile: notImplemented, @@ -420,7 +420,7 @@ export = C; } const path = getCanonicalFileName(normalizePath(combinePaths(currentDirectory, fileName))); const file = files.get(path); - return file && createSourceFile(fileName, file, languageVersion); + return file ? createSourceFile(fileName, file, languageVersion) : undefined; }, getDefaultLibFileName: () => "lib.d.ts", writeFile: notImplemented, @@ -975,9 +975,9 @@ import b = require("./moduleB"); function test(typesRoot: string, typeDirective: string, primary: boolean, initialFile: File, targetFile: File, ...otherFiles: File[]) { const host = createModuleResolutionHost(/*hasDirectoryExists*/ false, ...[initialFile, targetFile].concat(...otherFiles)); const result = resolveTypeReferenceDirective(typeDirective, initialFile.name, { typeRoots: [typesRoot] }, host); - assert(result.resolvedTypeReferenceDirective.resolvedFileName !== undefined, "expected type directive to be resolved"); - assert.equal(result.resolvedTypeReferenceDirective.resolvedFileName, targetFile.name, "unexpected result of type reference resolution"); - assert.equal(result.resolvedTypeReferenceDirective.primary, primary, "unexpected 'primary' value"); + assert(result.resolvedTypeReferenceDirective!.resolvedFileName !== undefined, "expected type directive to be resolved"); + assert.equal(result.resolvedTypeReferenceDirective!.resolvedFileName, targetFile.name, "unexpected result of type reference resolution"); + assert.equal(result.resolvedTypeReferenceDirective!.primary, primary, "unexpected 'primary' value"); } it("Can be resolved from primary location", () => { @@ -1111,10 +1111,7 @@ import b = require("./moduleB"); getNewLine: () => "\r\n", useCaseSensitiveFileNames: () => false, readFile: fileName => fileName === file.fileName ? file.text : undefined, - resolveModuleNames() { - assert(false, "resolveModuleNames should not be called"); - return undefined; - } + resolveModuleNames: notImplemented, }; createProgram([f.name], {}, compilerHost); }); @@ -1145,7 +1142,7 @@ import b = require("./moduleB"); readFile: fileName => fileName === file.fileName ? file.text : undefined, resolveModuleNames(moduleNames: string[], _containingFile: string) { assert.deepEqual(moduleNames, ["fs"]); - return [undefined]; + return [undefined!]; // TODO: GH#18217 } }; createProgram([f.name], {}, compilerHost); diff --git a/src/harness/unittests/projectErrors.ts b/src/harness/unittests/projectErrors.ts index dae465a3ef333..ae272fd58c649 100644 --- a/src/harness/unittests/projectErrors.ts +++ b/src/harness/unittests/projectErrors.ts @@ -136,7 +136,7 @@ namespace ts.projectSystem { projectService.openClientFile(file1.path); { projectService.checkNumberOfProjects({ configuredProjects: 1 }); - const configuredProject = forEach(projectService.synchronizeProjectList([]), f => f.info.projectName === corruptedConfig.path && f); + const configuredProject = find(projectService.synchronizeProjectList([]), f => f.info!.projectName === corruptedConfig.path)!; assert.isTrue(configuredProject !== undefined, "should find configured project"); checkProjectErrors(configuredProject, []); const projectErrors = configuredProjectAt(projectService, 0).getAllProjectErrors(); @@ -144,13 +144,13 @@ namespace ts.projectSystem { "'{' expected." ]); assert.isNotNull(projectErrors[0].file); - assert.equal(projectErrors[0].file.fileName, corruptedConfig.path); + assert.equal(projectErrors[0].file!.fileName, corruptedConfig.path); } // fix config and trigger watcher host.reloadFS([file1, file2, correctConfig]); { projectService.checkNumberOfProjects({ configuredProjects: 1 }); - const configuredProject = forEach(projectService.synchronizeProjectList([]), f => f.info.projectName === corruptedConfig.path && f); + const configuredProject = find(projectService.synchronizeProjectList([]), f => f.info!.projectName === corruptedConfig.path)!; assert.isTrue(configuredProject !== undefined, "should find configured project"); checkProjectErrors(configuredProject, []); const projectErrors = configuredProjectAt(projectService, 0).getAllProjectErrors(); @@ -181,7 +181,7 @@ namespace ts.projectSystem { projectService.openClientFile(file1.path); { projectService.checkNumberOfProjects({ configuredProjects: 1 }); - const configuredProject = forEach(projectService.synchronizeProjectList([]), f => f.info.projectName === corruptedConfig.path && f); + const configuredProject = find(projectService.synchronizeProjectList([]), f => f.info!.projectName === corruptedConfig.path)!; assert.isTrue(configuredProject !== undefined, "should find configured project"); checkProjectErrors(configuredProject, []); const projectErrors = configuredProjectAt(projectService, 0).getAllProjectErrors(); @@ -191,7 +191,7 @@ namespace ts.projectSystem { host.reloadFS([file1, file2, corruptedConfig]); { projectService.checkNumberOfProjects({ configuredProjects: 1 }); - const configuredProject = forEach(projectService.synchronizeProjectList([]), f => f.info.projectName === corruptedConfig.path && f); + const configuredProject = find(projectService.synchronizeProjectList([]), f => f.info!.projectName === corruptedConfig.path)!; assert.isTrue(configuredProject !== undefined, "should find configured project"); checkProjectErrors(configuredProject, []); const projectErrors = configuredProjectAt(projectService, 0).getAllProjectErrors(); @@ -199,7 +199,7 @@ namespace ts.projectSystem { "'{' expected." ]); assert.isNotNull(projectErrors[0].file); - assert.equal(projectErrors[0].file.fileName, corruptedConfig.path); + assert.equal(projectErrors[0].file!.fileName, corruptedConfig.path); } }); }); diff --git a/src/harness/unittests/projectReferences.ts b/src/harness/unittests/projectReferences.ts index 76ddd5fc29ea4..97628d17141cd 100644 --- a/src/harness/unittests/projectReferences.ts +++ b/src/harness/unittests/projectReferences.ts @@ -77,7 +77,7 @@ namespace ts { } } - const vfsys = new vfs.FileSystem(false, { files: { "/lib.d.ts": TestFSWithWatch.libFile.content! } }); + const vfsys = new vfs.FileSystem(false, { files: { "/lib.d.ts": TestFSWithWatch.libFile.content } }); files.forEach((v, k) => { vfsys.mkdirpSync(getDirectoryPath(k)); vfsys.writeFileSync(k, v); diff --git a/src/harness/unittests/publicApi.ts b/src/harness/unittests/publicApi.ts index b99557b67bdcd..0a5280f527329 100644 --- a/src/harness/unittests/publicApi.ts +++ b/src/harness/unittests/publicApi.ts @@ -6,7 +6,7 @@ describe("Public APIs", () => { const api = `api/${fileName}`; let fileContent: string; before(() => { - fileContent = Harness.IO.readFile(builtFile); + fileContent = Harness.IO.readFile(builtFile)!; }); it("should be acknowledged when they change", () => { diff --git a/src/harness/unittests/reuseProgramStructure.ts b/src/harness/unittests/reuseProgramStructure.ts index 74037d794187d..27873925302ae 100644 --- a/src/harness/unittests/reuseProgramStructure.ts +++ b/src/harness/unittests/reuseProgramStructure.ts @@ -93,7 +93,7 @@ namespace ts { newLength = this.program.length; break; default: - Debug.assert(false, "Unexpected change"); + return Debug.fail("Unexpected change"); } return createTextChangeRange(oldSpan, newLength); @@ -114,7 +114,7 @@ namespace ts { if (oldFile && oldFile.redirectInfo) { oldFile = oldFile.redirectInfo.unredirected; } - if (oldFile && oldFile.sourceText.getVersion() === t.text.getVersion()) { + if (oldFile && oldFile.sourceText!.getVersion() === t.text.getVersion()) { return oldFile; } } @@ -126,7 +126,7 @@ namespace ts { trace: s => trace.push(s), getTrace: () => trace, getSourceFile(fileName): SourceFile { - return files.get(fileName); + return files.get(fileName)!; }, getDefaultLibFileName(): string { return "lib.d.ts"; @@ -156,7 +156,7 @@ namespace ts { } export function newProgram(texts: NamedSourceText[], rootNames: string[], options: CompilerOptions): ProgramWithSourceTexts { - const host = createTestCompilerHost(texts, options.target); + const host = createTestCompilerHost(texts, options.target!); const program = createProgram(rootNames, options, host); program.sourceTexts = texts; program.host = host; @@ -165,10 +165,10 @@ namespace ts { export function updateProgram(oldProgram: ProgramWithSourceTexts, rootNames: ReadonlyArray, options: CompilerOptions, updater: (files: NamedSourceText[]) => void, newTexts?: NamedSourceText[]) { if (!newTexts) { - newTexts = oldProgram.sourceTexts.slice(0); + newTexts = oldProgram.sourceTexts!.slice(0); } updater(newTexts); - const host = createTestCompilerHost(newTexts, options.target, oldProgram); + const host = createTestCompilerHost(newTexts, options.target!, oldProgram); const program = createProgram(rootNames, options, host, oldProgram); program.sourceTexts = newTexts; program.host = host; @@ -191,16 +191,16 @@ namespace ts { return false; } - function checkCache(caption: string, program: Program, fileName: string, expectedContent: Map, getCache: (f: SourceFile) => Map, entryChecker: (expected: T, original: T) => boolean): void { + function checkCache(caption: string, program: Program, fileName: string, expectedContent: Map | undefined, getCache: (f: SourceFile) => Map | undefined, entryChecker: (expected: T, original: T) => boolean): void { const file = program.getSourceFile(fileName); assert.isTrue(file !== undefined, `cannot find file ${fileName}`); - const cache = getCache(file); + const cache = getCache(file!); if (expectedContent === undefined) { assert.isTrue(cache === undefined, `expected ${caption} to be undefined`); } else { assert.isTrue(cache !== undefined, `expected ${caption} to be set`); - assert.isTrue(mapsAreEqual(expectedContent, cache, entryChecker), `contents of ${caption} did not match the expected contents.`); + assert.isTrue(mapsAreEqual(expectedContent, cache!, entryChecker), `contents of ${caption} did not match the expected contents.`); } } @@ -210,7 +210,7 @@ namespace ts { if (!left || !right) return false; const someInLeftHasNoMatch = forEachEntry(left, (leftValue, leftKey) => { if (!right.has(leftKey)) return true; - const rightValue = right.get(leftKey); + const rightValue = right.get(leftKey)!; return !(valuesAreEqual ? valuesAreEqual(leftValue, rightValue) : leftValue === rightValue); }); if (someInLeftHasNoMatch) return false; @@ -218,11 +218,11 @@ namespace ts { return !someInRightHasNoMatch; } - function checkResolvedModulesCache(program: Program, fileName: string, expectedContent: Map): void { + function checkResolvedModulesCache(program: Program, fileName: string, expectedContent: Map | undefined): void { checkCache("resolved modules", program, fileName, expectedContent, f => f.resolvedModules, checkResolvedModule); } - function checkResolvedTypeDirectivesCache(program: Program, fileName: string, expectedContent: Map): void { + function checkResolvedTypeDirectivesCache(program: Program, fileName: string, expectedContent: Map | undefined): void { checkCache("resolved type directives", program, fileName, expectedContent, f => f.resolvedTypeReferenceDirectiveNames, checkResolvedTypeDirective); } @@ -399,7 +399,7 @@ namespace ts { const program2 = updateProgram(program1, ["/a.ts"], options, files => { files[0].text = files[0].text.updateProgram('import * as aa from "a";'); }); - assert.isDefined(program2.getSourceFile("/a.ts").resolvedModules.get("a"), "'a' is not an unresolved module after re-use"); + assert.isDefined(program2.getSourceFile("/a.ts")!.resolvedModules!.get("a"), "'a' is not an unresolved module after re-use"); }); it("resolved type directives cache follows type directives", () => { @@ -896,7 +896,7 @@ namespace ts { ) { const actual = isProgramUptoDate( program, newRootFileNames, newOptions, - path => program.getSourceFileByPath(path).version, /*fileExists*/ returnFalse, + path => program.getSourceFileByPath(path)!.version, /*fileExists*/ returnFalse, /*hasInvalidatedResolution*/ returnFalse, /*hasChangedAutomaticTypeDirectiveNames*/ false ); @@ -916,7 +916,7 @@ namespace ts { function verifyProgramWithConfigFile(system: System, configFileName: string) { const program = createWatchProgram(createWatchCompilerHostOfConfigFile(configFileName, {}, system)).getCurrentProgram().getProgram(); - const { fileNames, options } = parseConfigFileWithSystem(configFileName, {}, system, notImplemented); + const { fileNames, options } = parseConfigFileWithSystem(configFileName, {}, system, notImplemented)!; // TODO: GH#18217 verifyProgramIsUptoDate(program, fileNames, options); } diff --git a/src/harness/unittests/services/colorization.ts b/src/harness/unittests/services/colorization.ts index 17d4132e9e544..a05ca01641e83 100644 --- a/src/harness/unittests/services/colorization.ts +++ b/src/harness/unittests/services/colorization.ts @@ -32,7 +32,7 @@ describe("Colorization", () => { function identifier(text: string, position?: number) { return createClassification(text, ts.TokenClass.Identifier, position); } function numberLiteral(text: string, position?: number) { return createClassification(text, ts.TokenClass.NumberLiteral, position); } function stringLiteral(text: string, position?: number) { return createClassification(text, ts.TokenClass.StringLiteral, position); } - function finalEndOfLineState(value: number): ClassificationEntry { return { value, classification: undefined, position: 0 }; } + function finalEndOfLineState(value: number): ClassificationEntry { return { value, classification: undefined!, position: 0 }; } // TODO: GH#18217 function createClassification(value: string, classification: ts.TokenClass, position?: number): ClassificationEntry { return { value, classification, position }; } @@ -48,7 +48,7 @@ describe("Colorization", () => { const actualEntryPosition = expectedEntry.position !== undefined ? expectedEntry.position : text.indexOf(expectedEntry.value); assert(actualEntryPosition >= 0, "token: '" + expectedEntry.value + "' does not exit in text: '" + text + "'."); - const actualEntry = getEntryAtPosition(result, actualEntryPosition); + const actualEntry = getEntryAtPosition(result, actualEntryPosition)!; assert(actualEntry, "Could not find classification entry for '" + expectedEntry.value + "' at position: " + actualEntryPosition); assert.equal(actualEntry.classification, expectedEntry.classification, "Classification class does not match expected. Expected: " + ts.TokenClass[expectedEntry.classification] + ", Actual: " + ts.TokenClass[actualEntry.classification]); @@ -351,7 +351,7 @@ describe("Colorization", () => { pos += lastLength; lastLength = val.length; } - return ts.lastOrUndefined(vals); + return ts.last(vals); } }); diff --git a/src/harness/unittests/services/patternMatcher.ts b/src/harness/unittests/services/patternMatcher.ts index 64de3557da47c..d40354a5e6030 100644 --- a/src/harness/unittests/services/patternMatcher.ts +++ b/src/harness/unittests/services/patternMatcher.ts @@ -321,7 +321,7 @@ describe("PatternMatcher", () => { }); function assertSegmentMatch(candidate: string, pattern: string, expected: ts.PatternMatch | undefined): void { - assert.deepEqual(ts.createPatternMatcher(pattern).getMatchForLastSegmentOfPattern(candidate), expected); + assert.deepEqual(ts.createPatternMatcher(pattern)!.getMatchForLastSegmentOfPattern(candidate), expected); } function assertInvalidPattern(pattern: string) { @@ -329,7 +329,7 @@ describe("PatternMatcher", () => { } function assertFullMatch(dottedContainer: string, candidate: string, pattern: string, expected: ts.PatternMatch | undefined): void { - assert.deepEqual(ts.createPatternMatcher(pattern).getFullMatch(dottedContainer.split("."), candidate), expected); + assert.deepEqual(ts.createPatternMatcher(pattern)!.getFullMatch(dottedContainer.split("."), candidate), expected); } function spanListToSubstrings(identifier: string, spans: ts.TextSpan[]) { diff --git a/src/harness/unittests/session.ts b/src/harness/unittests/session.ts index 25df6f72ea623..5e0b44fb5f0c7 100644 --- a/src/harness/unittests/session.ts +++ b/src/harness/unittests/session.ts @@ -12,7 +12,7 @@ namespace ts.server { write(s): void { lastWrittenToHost = s; }, readFile: () => undefined, writeFile: noop, - resolvePath(): string { return void 0; }, + resolvePath(): string { return undefined!; }, // TODO: GH#18217 fileExists: () => false, directoryExists: () => false, getDirectories: () => [], @@ -47,7 +47,7 @@ namespace ts.server { cancellationToken: nullCancellationToken, useSingleInferredProject: false, useInferredProjectPerProjectRoot: false, - typingsInstaller: undefined, + typingsInstaller: undefined!, // TODO: GH#18217 byteLength: Utils.byteLength, hrtime: process.hrtime, logger: projectSystem.nullLogger, @@ -81,7 +81,7 @@ namespace ts.server { seq: 0, type: "request", arguments: { - file: undefined + file: undefined! // TODO: GH#18217 } }; @@ -441,7 +441,7 @@ namespace ts.server { lastSent: protocol.Message; private exceptionRaisingHandler(_request: protocol.Request): { response?: any, responseRequired: boolean } { f1(); - return; + return Debug.fail(); // unreachable, throw to make compiler happy function f1() { throw new Error("myMessage"); } @@ -453,7 +453,7 @@ namespace ts.server { cancellationToken: nullCancellationToken, useSingleInferredProject: false, useInferredProjectPerProjectRoot: false, - typingsInstaller: undefined, + typingsInstaller: undefined!, // TODO: GH#18217 byteLength: Utils.byteLength, hrtime: process.hrtime, logger: projectSystem.nullLogger, @@ -500,7 +500,7 @@ namespace ts.server { cancellationToken: nullCancellationToken, useSingleInferredProject: false, useInferredProjectPerProjectRoot: false, - typingsInstaller: undefined, + typingsInstaller: undefined!, // TODO: GH#18217 byteLength: Utils.byteLength, hrtime: process.hrtime, logger: projectSystem.nullLogger, @@ -568,7 +568,7 @@ namespace ts.server { cancellationToken: nullCancellationToken, useSingleInferredProject: false, useInferredProjectPerProjectRoot: false, - typingsInstaller: undefined, + typingsInstaller: undefined!, // TODO: GH#18217 byteLength: Utils.byteLength, hrtime: process.hrtime, logger: projectSystem.nullLogger, @@ -604,7 +604,7 @@ namespace ts.server { consumeQueue() { while (this.queue.length > 0) { - const elem = this.queue.pop(); + const elem = this.queue.pop()!; this.handleRequest(elem); } } diff --git a/src/harness/unittests/symbolWalker.ts b/src/harness/unittests/symbolWalker.ts index f793c237da302..a5939da68bf24 100644 --- a/src/harness/unittests/symbolWalker.ts +++ b/src/harness/unittests/symbolWalker.ts @@ -8,8 +8,8 @@ namespace ts { unitName: "main.ts", content: source }], [], {}, {}, "/"); - const file = result.program.getSourceFile("main.ts"); - const checker = result.program.getTypeChecker(); + const file = result.program!.getSourceFile("main.ts")!; + const checker = result.program!.getTypeChecker(); verifier(file, checker); }); } diff --git a/src/harness/unittests/textChanges.ts b/src/harness/unittests/textChanges.ts index df940fa8b7411..5303c9bcc28d9 100644 --- a/src/harness/unittests/textChanges.ts +++ b/src/harness/unittests/textChanges.ts @@ -8,9 +8,9 @@ namespace ts { describe("textChanges", () => { function findChild(name: string, n: Node) { - return find(n); + return find(n)!; - function find(node: Node): Node { + function find(node: Node): Node | undefined { if (isDeclaration(node) && node.name && isIdentifier(node.name) && node.name.escapedText === name) { return node; } @@ -88,7 +88,7 @@ namespace M } }`; runSingleFileTest("extractMethodLike", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { - const statements = (findChild("foo", sourceFile)).body.statements.slice(1); + const statements = (findChild("foo", sourceFile)).body!.statements.slice(1); const newFunction = createFunctionDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, @@ -105,11 +105,11 @@ namespace M // replace statements with return statement const newStatement = createReturn( createCall( - /*expression*/ newFunction.name, + /*expression*/ newFunction.name!, /*typeArguments*/ undefined, /*argumentsArray*/ emptyArray )); - changeTracker.replaceNodeRange(sourceFile, statements[0], lastOrUndefined(statements), newStatement, { suffix: newLineCharacter }); + changeTracker.replaceNodeRange(sourceFile, statements[0], last(statements), newStatement, { suffix: newLineCharacter }); }); } { diff --git a/src/harness/unittests/transform.ts b/src/harness/unittests/transform.ts index 61d8dc04e183b..c86a3185c7e59 100644 --- a/src/harness/unittests/transform.ts +++ b/src/harness/unittests/transform.ts @@ -139,7 +139,7 @@ namespace ts { return (sourceFile: SourceFile) => { const result = getMutableClone(sourceFile); result.statements = createNodeArray([ - createClassDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, "Foo", /*typeParameters*/ undefined, /*heritageClauses*/ undefined, /*members*/ undefined), + createClassDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, "Foo", /*typeParameters*/ undefined, /*heritageClauses*/ undefined, /*members*/ undefined!), // TODO: GH#18217 createModuleDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createIdentifier("Foo"), createModuleBlock([createEmptyStatement()])) ]); return result; @@ -266,7 +266,7 @@ namespace ts { function baselineDeclarationTransform(text: string, opts: TranspileOptions) { const fs = vfs.createFromFileSystem(Harness.IO, /*caseSensitive*/ true, { documents: [new documents.TextDocument("/.src/index.ts", text)] }); const host = new fakes.CompilerHost(fs, opts.compilerOptions); - const program = createProgram(["/.src/index.ts"], opts.compilerOptions, host); + const program = createProgram(["/.src/index.ts"], opts.compilerOptions!, host); program.emit(program.getSourceFiles()[1], (p, s, bom) => host.writeFile(p, s, bom), /*cancellationToken*/ undefined, /*onlyDts*/ true, opts.transformers); return fs.readFileSync("/.src/index.d.ts").toString(); } diff --git a/src/harness/unittests/transpile.ts b/src/harness/unittests/transpile.ts index 7cf663bf06eca..70f7ebdbc46e2 100644 --- a/src/harness/unittests/transpile.ts +++ b/src/harness/unittests/transpile.ts @@ -53,20 +53,20 @@ namespace ts { }); after(() => { - transpileResult = undefined; - oldTranspileResult = undefined; - oldTranspileDiagnostics = undefined; + transpileResult = undefined!; + oldTranspileResult = undefined!; + oldTranspileDiagnostics = undefined!; }); it("Correct errors for " + justName, () => { Harness.Baseline.runBaseline(justName.replace(/\.tsx?$/, ".errors.txt"), () => { - if (transpileResult.diagnostics.length === 0) { + if (transpileResult.diagnostics!.length === 0) { /* tslint:disable:no-null-keyword */ return null; /* tslint:enable:no-null-keyword */ } - return Harness.Compiler.getErrorBaseline(toBeCompiled, transpileResult.diagnostics); + return Harness.Compiler.getErrorBaseline(toBeCompiled, transpileResult.diagnostics!); }); }); diff --git a/src/harness/unittests/tscWatchMode.ts b/src/harness/unittests/tscWatchMode.ts index f3194d68dcdaf..f2ef80ce51582 100644 --- a/src/harness/unittests/tscWatchMode.ts +++ b/src/harness/unittests/tscWatchMode.ts @@ -171,7 +171,7 @@ namespace ts.tscWatch { assert.equal(host.exitCode, expectedExitCode); } - function getDiagnosticOfFileFrom(file: SourceFile, text: string, start: number, length: number, message: DiagnosticMessage): Diagnostic { + function getDiagnosticOfFileFrom(file: SourceFile | undefined, text: string, start: number | undefined, length: number | undefined, message: DiagnosticMessage): Diagnostic { return { file, start, @@ -205,7 +205,7 @@ namespace ts.tscWatch { function getUnknownCompilerOption(program: Program, configFile: File, option: string) { const quotedOption = `"${option}"`; - return getDiagnosticOfFile(program.getCompilerOptions().configFile, configFile.content.indexOf(quotedOption), quotedOption.length, Diagnostics.Unknown_compiler_option_0, option); + return getDiagnosticOfFile(program.getCompilerOptions().configFile!, configFile.content.indexOf(quotedOption), quotedOption.length, Diagnostics.Unknown_compiler_option_0, option); } function getDiagnosticOfFileFromProgram(program: Program, filePath: string, start: number, length: number, message: DiagnosticMessage, ..._args: (string | number)[]): Diagnostic { @@ -215,7 +215,7 @@ namespace ts.tscWatch { text = formatStringFromArgs(text, arguments, 5); } - return getDiagnosticOfFileFrom(program.getSourceFileByPath(toPath(filePath, program.getCurrentDirectory(), s => s.toLowerCase())), + return getDiagnosticOfFileFrom(program.getSourceFileByPath(toPath(filePath, program.getCurrentDirectory(), s => s.toLowerCase()))!, text, start, length, message); } @@ -1101,8 +1101,8 @@ namespace ts.tscWatch { const host = createWatchedSystem(files); const watch = createWatchOfConfigFile(configFile.path, host); const errors = () => [ - getDiagnosticOfFile(watch().getCompilerOptions().configFile, configFile.content.indexOf('"allowJs"'), '"allowJs"'.length, Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", "declaration"), - getDiagnosticOfFile(watch().getCompilerOptions().configFile, configFile.content.indexOf('"declaration"'), '"declaration"'.length, Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", "declaration") + getDiagnosticOfFile(watch().getCompilerOptions().configFile!, configFile.content.indexOf('"allowJs"'), '"allowJs"'.length, Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", "declaration"), + getDiagnosticOfFile(watch().getCompilerOptions().configFile!, configFile.content.indexOf('"declaration"'), '"declaration"'.length, Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", "declaration") ]; const intialErrors = errors(); checkOutputErrorsInitial(host, intialErrors); @@ -1112,8 +1112,8 @@ namespace ts.tscWatch { host.runQueuedTimeoutCallbacks(); const nowErrors = errors(); checkOutputErrorsIncremental(host, nowErrors); - assert.equal(nowErrors[0].start, intialErrors[0].start - configFileContentComment.length); - assert.equal(nowErrors[1].start, intialErrors[1].start - configFileContentComment.length); + assert.equal(nowErrors[0].start, intialErrors[0].start! - configFileContentComment.length); + assert.equal(nowErrors[1].start, intialErrors[1].start! - configFileContentComment.length); }); it("should not trigger recompilation because of program emit", () => { @@ -1409,7 +1409,7 @@ namespace ts.tscWatch { } function getFile(fileName: string) { - return find(files, file => file.path === fileName); + return find(files, file => file.path === fileName)!; } function verifyAffectedAllFiles() { @@ -2252,7 +2252,7 @@ declare module "fs" { const disableConsoleClear = options.diagnostics || options.extendedDiagnostics || options.preserveWatchOutput; const host = createWatchedSystem(files); createWatchOfFilesAndCompilerOptions([file.path], host, options); - checkOutputErrorsInitial(host, emptyArray, disableConsoleClear, options.extendedDiagnostics && [ + checkOutputErrorsInitial(host, emptyArray, disableConsoleClear, options.extendedDiagnostics ? [ "Current directory: / CaseSensitiveFileNames: false\n", "Synchronizing program\n", "CreatingProgramWith::\n", @@ -2260,21 +2260,21 @@ declare module "fs" { " options: {\"extendedDiagnostics\":true}\n", "FileWatcher:: Added:: WatchInfo: f.ts 250 Source file\n", "FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 250 Source file\n" - ]); + ] : undefined); file.content = "//"; host.reloadFS(files); host.runQueuedTimeoutCallbacks(); - checkOutputErrorsIncremental(host, emptyArray, disableConsoleClear, options.extendedDiagnostics && [ + checkOutputErrorsIncremental(host, emptyArray, disableConsoleClear, options.extendedDiagnostics ? [ "FileWatcher:: Triggered with /f.ts1:: WatchInfo: f.ts 250 Source file\n", "Scheduling update\n", "Elapsed:: 0ms FileWatcher:: Triggered with /f.ts1:: WatchInfo: f.ts 250 Source file\n" - ], options.extendedDiagnostics && [ + ] : undefined, options.extendedDiagnostics ? [ "Synchronizing program\n", "CreatingProgramWith::\n", " roots: [\"f.ts\"]\n", " options: {\"extendedDiagnostics\":true}\n" - ]); + ] : undefined); } it("without --diagnostics or --extendedDiagnostics", () => { diff --git a/src/harness/unittests/tsconfigParsing.ts b/src/harness/unittests/tsconfigParsing.ts index 7a47481b88d3f..f46cee3656b40 100644 --- a/src/harness/unittests/tsconfigParsing.ts +++ b/src/harness/unittests/tsconfigParsing.ts @@ -135,11 +135,12 @@ namespace ts { const parsed = parseConfigFileTextToJson("/apath/tsconfig.json", "invalid"); assert.deepEqual(parsed.config, { invalid: undefined }); const expected = createCompilerDiagnostic(Diagnostics._0_expected, "{"); - assert.equal(parsed.error.messageText, expected.messageText); - assert.equal(parsed.error.category, expected.category); - assert.equal(parsed.error.code, expected.code); - assert.equal(parsed.error.start, 0); - assert.equal(parsed.error.length, "invalid".length); + const error = parsed.error!; + assert.equal(error.messageText, expected.messageText); + assert.equal(error.category, expected.category); + assert.equal(error.code, expected.code); + assert.equal(error.start, 0); + assert.equal(error.length, "invalid".length); }); it("returns object when users correctly specify library", () => { diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 1e75957feefea..28a8bdb114a7d 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -58,7 +58,7 @@ namespace ts.projectSystem { msg: noop, startGroup: noop, endGroup: noop, - getLogFileName: (): string => undefined + getLogFileName: () => undefined, }; export class TestTypingsInstaller extends TI.TypingsInstaller implements server.ITypingsInstaller { @@ -189,7 +189,7 @@ namespace ts.projectSystem { } getEvent(eventName: T["eventName"]): T["data"] { - let eventData: T["data"]; + let eventData: T["data"] | undefined; filterMutate(this.events, e => { if (e.eventName === eventName) { if (eventData !== undefined) { @@ -200,8 +200,7 @@ namespace ts.projectSystem { } return true; }); - assert.isDefined(eventData); - return eventData; + return Debug.assertDefined(eventData); } hasZeroEvent(eventName: T["eventName"]) { @@ -216,7 +215,7 @@ namespace ts.projectSystem { assertProjectInfoTelemetryEvent(partial: Partial, configFile = "/tsconfig.json"): void { assert.deepEqual(this.getEvent(server.ProjectInfoTelemetryEvent), { - projectId: sys.createSHA256Hash(configFile), + projectId: sys.createSHA256Hash!(configFile), fileStats: fileStats({ ts: 1 }), compilerOptions: {}, extends: false, @@ -294,7 +293,7 @@ namespace ts.projectSystem { cancellationToken: server.nullCancellationToken, useSingleInferredProject: false, useInferredProjectPerProjectRoot: false, - typingsInstaller: undefined, + typingsInstaller: undefined!, // TODO: GH#18217 byteLength: Utils.byteLength, hrtime: process.hrtime, logger: opts.logger || nullLogger, @@ -336,7 +335,7 @@ namespace ts.projectSystem { const cancellationToken = parameters.cancellationToken || server.nullCancellationToken; const logger = parameters.logger || nullLogger; const useSingleInferredProject = parameters.useSingleInferredProject !== undefined ? parameters.useSingleInferredProject : false; - return new TestProjectService(host, logger, cancellationToken, useSingleInferredProject, parameters.typingsInstaller, parameters.eventHandler, options); + return new TestProjectService(host, logger, cancellationToken, useSingleInferredProject, parameters.typingsInstaller!, parameters.eventHandler!, options); // TODO: GH#18217 } export function checkNumberOfConfiguredProjects(projectService: server.ProjectService, expected: number) { @@ -404,7 +403,7 @@ namespace ts.projectSystem { } function checkOpenFiles(projectService: server.ProjectService, expectedFiles: File[]) { - checkArray("Open files", arrayFrom(projectService.openFiles.keys(), path => projectService.getScriptInfoForPath(path as Path).fileName), expectedFiles.map(file => file.path)); + checkArray("Open files", arrayFrom(projectService.openFiles.keys(), path => projectService.getScriptInfoForPath(path as Path)!.fileName), expectedFiles.map(file => file.path)); } function textSpanFromSubstring(str: string, substring: string): TextSpan { @@ -420,7 +419,7 @@ namespace ts.projectSystem { * setRequestToCancel(); */ export class TestServerCancellationToken implements server.ServerCancellationToken { - private currentId = -1; + private currentId: number | undefined = -1; private requestToCancel = -1; private isCancellationRequestedCount = 0; @@ -708,7 +707,7 @@ namespace ts.projectSystem { projectService.checkNumberOfProjects({ inferredProjects: 2, configuredProjects: 1 }); assert.isTrue(projectService.inferredProjects[0].isOrphan()); checkProjectActualFiles(projectService.inferredProjects[1], [commonFile2.path, libFile.path]); - checkProjectActualFiles(projectService.configuredProjects.get(configFile.path), [libFile.path, commonFile1.path, configFile.path]); + checkProjectActualFiles(projectService.configuredProjects.get(configFile.path)!, [libFile.path, commonFile1.path, configFile.path]); checkWatchedFiles(host, watchedFiles); @@ -1106,15 +1105,15 @@ namespace ts.projectSystem { const projectService = createProjectService(host); projectService.openExternalProject({ rootFiles: toExternalFiles([file1.path]), options: {}, projectFileName: proj1name }); - const proj1 = projectService.findProject(proj1name); + const proj1 = projectService.findProject(proj1name)!; assert.isTrue(proj1.languageServiceEnabled); projectService.openExternalProject({ rootFiles: toExternalFiles([file2.path]), options: {}, projectFileName: proj2name }); - const proj2 = projectService.findProject(proj2name); + const proj2 = projectService.findProject(proj2name)!; assert.isTrue(proj2.languageServiceEnabled); projectService.openExternalProject({ rootFiles: toExternalFiles([file3.path]), options: {}, projectFileName: proj3name }); - const proj3 = projectService.findProject(proj3name); + const proj3 = projectService.findProject(proj3name)!; assert.isFalse(proj3.languageServiceEnabled); }); @@ -1182,7 +1181,7 @@ namespace ts.projectSystem { const projectService = createProjectService(host, { useSingleInferredProject: true }); projectService.openClientFile(file1.path); checkNumberOfConfiguredProjects(projectService, 1); - const project = projectService.configuredProjects.get(configFile.path); + const project = projectService.configuredProjects.get(configFile.path)!; assert.isTrue(project.hasOpenRef()); // file1 projectService.closeClientFile(file1.path); @@ -1216,7 +1215,7 @@ namespace ts.projectSystem { const projectService = createProjectService(host, { useSingleInferredProject: true }); projectService.openClientFile(file1.path); checkNumberOfConfiguredProjects(projectService, 1); - const project = projectService.configuredProjects.get(configFile.path); + const project = projectService.configuredProjects.get(configFile.path)!; assert.isTrue(project.hasOpenRef()); // file1 projectService.closeClientFile(file1.path); @@ -1489,13 +1488,13 @@ namespace ts.projectSystem { service.checkNumberOfProjects({ externalProjects: 1 }); checkProjectActualFiles(service.externalProjects[0], [f1.path, f2.path, libFile.path]); - const completions1 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 2, defaultPreferences); + const completions1 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 2, defaultPreferences)!; // should contain completions for string assert.isTrue(completions1.entries.some(e => e.name === "charAt"), "should contain 'charAt'"); assert.isFalse(completions1.entries.some(e => e.name === "toExponential"), "should not contain 'toExponential'"); service.closeClientFile(f2.path); - const completions2 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 2, defaultPreferences); + const completions2 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 2, defaultPreferences)!; // should contain completions for string assert.isFalse(completions2.entries.some(e => e.name === "charAt"), "should not contain 'charAt'"); assert.isTrue(completions2.entries.some(e => e.name === "toExponential"), "should contain 'toExponential'"); @@ -1521,13 +1520,13 @@ namespace ts.projectSystem { service.checkNumberOfProjects({ externalProjects: 1 }); checkProjectActualFiles(service.externalProjects[0], [f1.path, f2.path, libFile.path]); - const completions1 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 0, defaultPreferences); + const completions1 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 0, defaultPreferences)!; assert.isTrue(completions1.entries.some(e => e.name === "somelongname"), "should contain 'somelongname'"); service.closeClientFile(f2.path); - const completions2 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 0, defaultPreferences); + const completions2 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 0, defaultPreferences)!; assert.isFalse(completions2.entries.some(e => e.name === "somelongname"), "should not contain 'somelongname'"); - const sf2 = service.externalProjects[0].getLanguageService().getProgram().getSourceFile(f2.path); + const sf2 = service.externalProjects[0].getLanguageService().getProgram()!.getSourceFile(f2.path)!; assert.equal(sf2.text, ""); }); @@ -2048,8 +2047,8 @@ namespace ts.projectSystem { const projectService = createProjectService(host); projectService.applyChangesInOpenFiles([tsFile], [], []); const projs = projectService.synchronizeProjectList([]); - projectService.findProject(projs[0].info.projectName).getLanguageService().getNavigationBarItems(tsFile.fileName); - projectService.synchronizeProjectList([projs[0].info]); + projectService.findProject(projs[0].info!.projectName)!.getLanguageService().getNavigationBarItems(tsFile.fileName); + projectService.synchronizeProjectList([projs[0].info!]); projectService.applyChangesInOpenFiles([jsFile], [], []); }); @@ -2333,7 +2332,7 @@ namespace ts.projectSystem { const project = projectService.externalProjects[0]; - const scriptInfo = project.getScriptInfo(file1.path); + const scriptInfo = project.getScriptInfo(file1.path)!; const snap = scriptInfo.getSnapshot(); const actualText = getSnapshotText(snap); assert.equal(actualText, "", `expected content to be empty string, got "${actualText}"`); @@ -2341,12 +2340,12 @@ namespace ts.projectSystem { projectService.openClientFile(file1.path, `var x = 1;`); project.updateGraph(); - const quickInfo = project.getLanguageService().getQuickInfoAtPosition(file1.path, 4); + const quickInfo = project.getLanguageService().getQuickInfoAtPosition(file1.path, 4)!; assert.equal(quickInfo.kind, ScriptElementKind.variableElement); projectService.closeClientFile(file1.path); - const scriptInfo2 = project.getScriptInfo(file1.path); + const scriptInfo2 = project.getScriptInfo(file1.path)!; const actualText2 = getSnapshotText(scriptInfo2.getSnapshot()); assert.equal(actualText2, "", `expected content to be empty string, got "${actualText2}"`); }); @@ -2391,7 +2390,7 @@ namespace ts.projectSystem { projectService.openClientFile(file1.path); projectService.inferredProjects[0].getLanguageService(/*ensureSynchronized*/ false).getOutliningSpans(file1.path); projectService.setCompilerOptionsForInferredProjects({ target: ScriptTarget.ES5, allowJs: true }); - projectService.getScriptInfo(file1.path).editContent(0, 0, " "); + projectService.getScriptInfo(file1.path)!.editContent(0, 0, " "); projectService.inferredProjects[0].getLanguageService(/*ensureSynchronized*/ false).getOutliningSpans(file1.path); projectService.closeClientFile(file1.path); }); @@ -2418,9 +2417,9 @@ namespace ts.projectSystem { projectService.openClientFile(file2.path); checkNumberOfProjects(projectService, { configuredProjects: 1 }); - const project1 = projectService.configuredProjects.get(tsconfig1.path); + const project1 = projectService.configuredProjects.get(tsconfig1.path)!; assert.isTrue(project1.hasOpenRef(), "Has open ref count in project1 - 1"); // file2 - assert.equal(project1.getScriptInfo(file2.path).containingProjects.length, 1, "containing projects count"); + assert.equal(project1.getScriptInfo(file2.path)!.containingProjects.length, 1, "containing projects count"); assert.isFalse(project1.isClosed()); projectService.openClientFile(file1.path); @@ -2429,12 +2428,12 @@ namespace ts.projectSystem { assert.strictEqual(projectService.configuredProjects.get(tsconfig1.path), project1); assert.isFalse(project1.isClosed()); - const project2 = projectService.configuredProjects.get(tsconfig2.path); + const project2 = projectService.configuredProjects.get(tsconfig2.path)!; assert.isTrue(project2.hasOpenRef(), "Has open ref count in project2 - 2"); // file1 assert.isFalse(project2.isClosed()); - assert.equal(project1.getScriptInfo(file1.path).containingProjects.length, 2, `${file1.path} containing projects count`); - assert.equal(project1.getScriptInfo(file2.path).containingProjects.length, 1, `${file2.path} containing projects count`); + assert.equal(project1.getScriptInfo(file1.path)!.containingProjects.length, 2, `${file1.path} containing projects count`); + assert.equal(project1.getScriptInfo(file2.path)!.containingProjects.length, 1, `${file2.path} containing projects count`); projectService.closeClientFile(file2.path); checkNumberOfProjects(projectService, { configuredProjects: 2 }); @@ -2494,10 +2493,10 @@ namespace ts.projectSystem { projectService.openClientFile(file3.path); projectService.openClientFile(file4.path); - const infos = files.map(file => projectService.getScriptInfoForPath(file.path as Path)); + const infos = files.map(file => projectService.getScriptInfoForPath(file.path as Path)!); checkOpenFiles(projectService, files); checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 2 }); - const configProject1 = projectService.configuredProjects.get(configFile.path); + const configProject1 = projectService.configuredProjects.get(configFile.path)!; assert.isTrue(configProject1.hasOpenRef()); // file1 and file3 checkProjectActualFiles(configProject1, [file1.path, file3.path, configFile.path]); const inferredProject1 = projectService.inferredProjects[0]; @@ -2568,7 +2567,7 @@ namespace ts.projectSystem { function verifyConfiguredProjectStateAfterUpdate(hasOpenRef: boolean, inferredProjects: number) { checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects }); - const configProject2 = projectService.configuredProjects.get(configFile.path); + const configProject2 = projectService.configuredProjects.get(configFile.path)!; assert.strictEqual(configProject2, configProject1); checkProjectActualFiles(configProject2, [file1.path, file2.path, file3.path, configFile.path]); assert.equal(configProject2.hasOpenRef(), hasOpenRef); @@ -2607,7 +2606,7 @@ namespace ts.projectSystem { projectService.openClientFile(file3.path); checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 1 }); - const configuredProject = projectService.configuredProjects.get(configFile.path); + const configuredProject = projectService.configuredProjects.get(configFile.path)!; assert.isTrue(configuredProject.hasOpenRef()); // file1 and file3 checkProjectActualFiles(configuredProject, [file1.path, file3.path, configFile.path]); const inferredProject1 = projectService.inferredProjects[0]; @@ -2709,7 +2708,7 @@ namespace ts.projectSystem { const projectService = createProjectService(host); projectService.openClientFile(f1.path); projectService.checkNumberOfProjects({ configuredProjects: 1 }); - const project = projectService.configuredProjects.get(config.path); + const project = projectService.configuredProjects.get(config.path)!; assert.isTrue(project.hasOpenRef()); // f1 assert.isFalse(project.isClosed()); @@ -2721,7 +2720,7 @@ namespace ts.projectSystem { for (const f of [f1, f2, f3]) { // All the script infos should be present and contain the project since it is still alive. - const scriptInfo = projectService.getScriptInfoForNormalizedPath(server.toNormalizedPath(f.path)); + const scriptInfo = projectService.getScriptInfoForNormalizedPath(server.toNormalizedPath(f.path))!; assert.equal(scriptInfo.containingProjects.length, 1, `expect 1 containing projects for '${f.path}'`); assert.equal(scriptInfo.containingProjects[0], project, `expect configured project to be the only containing project for '${f.path}'`); } @@ -2764,7 +2763,7 @@ namespace ts.projectSystem { host.getFileSize = (filePath: string) => filePath === f2.path ? server.maxProgramSizeForNonTsFiles + 1 : originalGetFileSize.call(host, filePath); - let lastEvent: server.ProjectLanguageServiceStateEvent; + let lastEvent!: server.ProjectLanguageServiceStateEvent; const session = createSession(host, { canUseEvents: true, eventHandler: e => { @@ -2816,7 +2815,7 @@ namespace ts.projectSystem { const originalGetFileSize = host.getFileSize; host.getFileSize = (filePath: string) => filePath === f2.path ? server.maxProgramSizeForNonTsFiles + 1 : originalGetFileSize.call(host, filePath); - let lastEvent: server.ProjectLanguageServiceStateEvent; + let lastEvent!: server.ProjectLanguageServiceStateEvent; const session = createSession(host, { canUseEvents: true, eventHandler: e => { @@ -2906,7 +2905,7 @@ namespace ts.projectSystem { host.reloadFS([libFile, site]); host.checkTimeoutQueueLengthAndRun(1); - knownProjects = projectService.synchronizeProjectList(map(knownProjects, proj => proj.info)); + knownProjects = projectService.synchronizeProjectList(map(knownProjects, proj => proj.info!)); // TODO: GH#18217 GH#20039 checkNumberOfProjects(projectService, { configuredProjects: 0, externalProjects: 0, inferredProjects: 0 }); externalProject.rootFiles.length = 1; @@ -2979,7 +2978,7 @@ namespace ts.projectSystem { const projectService = createProjectService(host); projectService.openClientFile(file1.path); checkNumberOfProjects(projectService, { configuredProjects: 1 }); - const project = projectService.configuredProjects.get(configFile.path); + const project = projectService.configuredProjects.get(configFile.path)!; assert.isDefined(project); checkProjectActualFiles(project, map(files, file => file.path)); checkWatchedFiles(host, mapDefined(files, file => file === file1 ? undefined : file.path)); @@ -3040,7 +3039,7 @@ namespace ts.projectSystem { const projectService = createProjectService(host); projectService.openClientFile(file1.path); checkNumberOfProjects(projectService, { configuredProjects: 1 }); - const project = projectService.configuredProjects.get(configFile.path); + const project = projectService.configuredProjects.get(configFile.path)!; assert.isDefined(project); checkProjectActualFiles(project, [file1.path, libFile.path, module1.path, module2.path, configFile.path]); checkWatchedFiles(host, [libFile.path, module1.path, module2.path, configFile.path]); @@ -3145,7 +3144,7 @@ namespace ts.projectSystem { }); const projectService = session.getProjectService(); - const configuredProject = projectService.configuredProjects.get(config.path); + const configuredProject = projectService.configuredProjects.get(config.path)!; verifyConfiguredProject(); // open files/file1 = should not create another project @@ -3296,7 +3295,7 @@ namespace ts.projectSystem { const host = createServerHost(files); const service = createProjectService(host); service.openClientFile(file1.path); - checkProjectActualFiles(service.configuredProjects.get(config.path), [file1.path, file2.path, libFile.path, config.path]); + checkProjectActualFiles(service.configuredProjects.get(config.path)!, [file1.path, file2.path, libFile.path, config.path]); const configContent2 = JSON.stringify({ files: ["src/file1.ts"] @@ -3305,19 +3304,18 @@ namespace ts.projectSystem { host.reloadFS(files); host.runQueuedTimeoutCallbacks(); - checkProjectActualFiles(service.configuredProjects.get(config.path), [file1.path, libFile.path, config.path]); + checkProjectActualFiles(service.configuredProjects.get(config.path)!, [file1.path, libFile.path, config.path]); verifyFile2InfoIsOrphan(); file2.content += "export let z = 10;"; host.reloadFS(files); host.runQueuedTimeoutCallbacks(); - checkProjectActualFiles(service.configuredProjects.get(config.path), [file1.path, libFile.path, config.path]); + checkProjectActualFiles(service.configuredProjects.get(config.path)!, [file1.path, libFile.path, config.path]); verifyFile2InfoIsOrphan(); function verifyFile2InfoIsOrphan() { - const info = service.getScriptInfoForPath(file2.path as Path); - assert.isDefined(info); + const info = Debug.assertDefined(service.getScriptInfoForPath(file2.path as Path)); assert.equal(info.containingProjects.length, 0); } }); @@ -3339,7 +3337,7 @@ namespace ts.projectSystem { }, startGroup: noop, endGroup: noop, - getLogFileName: (): string => undefined + getLogFileName: () => undefined }; return { errorLogger, @@ -3362,7 +3360,7 @@ namespace ts.projectSystem { projectService.openClientFile(file1.path); projectService.checkNumberOfProjects({ configuredProjects: 1 }); - const project = projectService.findProject(corruptedConfig.path); + const project = projectService.findProject(corruptedConfig.path)!; checkProjectRootFiles(project, [file1.path]); }); @@ -3904,7 +3902,7 @@ namespace ts.projectSystem { const projectService = createProjectService(host); projectService.openClientFile(f.path); projectService.checkNumberOfProjects({ configuredProjects: 1 }); - const project = projectService.configuredProjects.get(config.path); + const project = projectService.configuredProjects.get(config.path)!; assert.isTrue(project.hasOpenRef()); // f projectService.closeClientFile(f.path); @@ -4053,7 +4051,7 @@ namespace ts.projectSystem { // force to load the content of the file p.updateGraph(); - const scriptInfo = p.getScriptInfo(f.path); + const scriptInfo = p.getScriptInfo(f.path)!; checkSnapLength(scriptInfo.getSnapshot(), f.content.length); // open project and replace its content with empty string @@ -4137,7 +4135,7 @@ namespace ts.projectSystem { function verifyProject() { assert.isDefined(service.configuredProjects.get(configFile.path)); - const project = service.configuredProjects.get(configFile.path); + const project = service.configuredProjects.get(configFile.path)!; checkProjectActualFiles(project, files.map(f => f.path)); } }); @@ -5037,7 +5035,7 @@ namespace ts.projectSystem { // verify content const projectServiice = session.getProjectService(); - const snap1 = projectServiice.getScriptInfo(f1.path).getSnapshot(); + const snap1 = projectServiice.getScriptInfo(f1.path)!.getSnapshot(); assert.equal(getSnapshotText(snap1), tmp.content, "content should be equal to the content of temp file"); // reload from original file file @@ -5049,7 +5047,7 @@ namespace ts.projectSystem { }); // verify content - const snap2 = projectServiice.getScriptInfo(f1.path).getSnapshot(); + const snap2 = projectServiice.getScriptInfo(f1.path)!.getSnapshot(); assert.equal(getSnapshotText(snap2), f1.content, "content should be equal to the content of original file"); }); @@ -5074,7 +5072,7 @@ namespace ts.projectSystem { const projectService = session.getProjectService(); checkNumberOfProjects(projectService, { inferredProjects: 1 }); - const info = projectService.getScriptInfo(f1.path); + const info = projectService.getScriptInfo(f1.path)!; assert.isDefined(info); checkScriptInfoContents(openContent, "contents set during open request"); @@ -5647,8 +5645,7 @@ namespace ts.projectSystem { function verifyConfiguredProject(host: TestServerHost, projectService: TestProjectService, orphanInferredProject?: boolean) { projectService.checkNumberOfProjects({ configuredProjects: 1, inferredProjects: orphanInferredProject ? 1 : 0 }); - const project = projectService.configuredProjects.get(tsconfig.path); - assert.isDefined(project); + const project = Debug.assertDefined(projectService.configuredProjects.get(tsconfig.path)); if (orphanInferredProject) { const inferredProject = projectService.inferredProjects[0]; @@ -6240,7 +6237,7 @@ namespace ts.projectSystem { const calledMap = createMultiMap<[U, V, W, X]>(); const cb = (host)[prop].bind(host); (host)[prop] = (f: string, arg1?: U, arg2?: V, arg3?: W, arg4?: X) => { - calledMap.add(f, [arg1, arg2, arg3, arg4]); + calledMap.add(f, [arg1!, arg2!, arg3!, arg4!]); // TODO: GH#18217 return cb(f, arg1, arg2, arg3, arg4); }; return calledMap; @@ -6495,7 +6492,7 @@ namespace ts.projectSystem { assert.isDefined(configFileName, `should find config`); checkNumberOfConfiguredProjects(projectService, 1); - const project = projectService.configuredProjects.get(tsconfigFile.path); + const project = projectService.configuredProjects.get(tsconfigFile.path)!; checkProjectActualFiles(project, map(projectFiles, f => f.path)); const callsTrackingHost = createCallsTrackingHost(host); @@ -6504,8 +6501,8 @@ namespace ts.projectSystem { const getDefinitionRequest = makeSessionRequest(protocol.CommandTypes.Definition, { file: clientFile.path, position: clientFile.content.indexOf("/vessel") + 1, - line: undefined, - offset: undefined + line: undefined!, // TODO: GH#18217 + offset: undefined! // TODO: GH#18217 }); const response = session.executeCommand(getDefinitionRequest).response as server.protocol.FileSpan[]; assert.equal(response[0].file, moduleFile.path, "Should go to definition of vessel: response: " + JSON.stringify(response)); @@ -6581,11 +6578,11 @@ namespace ts.projectSystem { const projectService = createProjectService(host); const canonicalConfigPath = toCanonical(tsconfigFile.path); const { configFileName } = projectService.openClientFile(file1.path); - assert.equal(configFileName, tsconfigFile.path, `should find config`); + assert.equal(configFileName, tsconfigFile.path as server.NormalizedPath, `should find config`); // tslint:disable-line no-unnecessary-type-assertion (TODO: GH#18217) checkNumberOfConfiguredProjects(projectService, 1); const watchingRecursiveDirectories = [`${canonicalFrontendDir}/src`, canonicalFrontendDir].concat(getNodeModuleDirectories(getDirectoryPath(canonicalFrontendDir))); - const project = projectService.configuredProjects.get(canonicalConfigPath); + const project = projectService.configuredProjects.get(canonicalConfigPath)!; verifyProjectAndWatchedDirectories(); const callsTrackingHost = createCallsTrackingHost(host); @@ -6664,7 +6661,7 @@ namespace ts.projectSystem { const service = createProjectService(host); service.openClientFile(file1.path); - const project = service.configuredProjects.get(tsconfig.path); + const project = service.configuredProjects.get(tsconfig.path)!; checkProjectActualFiles(project, files.map(f => f.path)); assert.deepEqual(project.getLanguageService().getSemanticDiagnostics(file1.path).map(diag => diag.messageText), ["Cannot find module 'debug'."]); assert.deepEqual(project.getLanguageService().getSemanticDiagnostics(file2.path).map(diag => diag.messageText), ["Cannot find module 'debug'."]); @@ -6736,7 +6733,7 @@ namespace ts.projectSystem { const host = createServerHost(projectFiles.concat(otherFiles)); const projectService = createProjectService(host); const { configFileName } = projectService.openClientFile(app.path); - assert.equal(configFileName, tsconfigJson.path, `should find config`); + assert.equal(configFileName, tsconfigJson.path as server.NormalizedPath, `should find config`); // TODO: GH#18217 const recursiveWatchedDirectories: string[] = [appFolder].concat(getNodeModuleDirectories(getDirectoryPath(appFolder))); verifyProject(); @@ -6815,7 +6812,7 @@ namespace ts.projectSystem { }); const lodashIndexPath = root + "/a/b/node_modules/@types/lodash/index.d.ts"; - projectFiles.push(find(filesAndFoldersToAdd, f => f.path === lodashIndexPath)); + projectFiles.push(find(filesAndFoldersToAdd, f => f.path === lodashIndexPath)!); // we would now not have failed lookup in the parent of appFolder since lodash is available recursiveWatchedDirectories.length = 1; // npm installation complete, timeout after reload fs @@ -6836,7 +6833,7 @@ namespace ts.projectSystem { function verifyProject() { checkNumberOfConfiguredProjects(projectService, 1); - const project = projectService.configuredProjects.get(tsconfigJson.path); + const project = projectService.configuredProjects.get(tsconfigJson.path)!; const projectFilePaths = map(projectFiles, f => f.path); checkProjectActualFiles(project, projectFilePaths); @@ -6872,7 +6869,7 @@ namespace ts.projectSystem { const service = createProjectService(host); service.openClientFile(app.path); - const project = service.configuredProjects.get(tsconfig.path); + const project = service.configuredProjects.get(tsconfig.path)!; checkProjectActualFiles(project, files.map(f => f.path)); assert.deepEqual(project.getLanguageService().getSemanticDiagnostics(app.path).map(diag => diag.messageText), ["Cannot find module 'debug'."]); @@ -7071,7 +7068,7 @@ namespace ts.projectSystem { content: JSON.stringify(configObj || { compilerOptions: {} }) }; - const files = [file1Consumer1, moduleFile1, file1Consumer2, moduleFile2, ...additionalFiles, globalFile3, libFile, configFile]; + const files: File[] = [file1Consumer1, moduleFile1, file1Consumer2, moduleFile2, ...additionalFiles, globalFile3, libFile, configFile]; const filesToReload = firstReloadFileList && getFiles(firstReloadFileList) || files; const host = createServerHost([filesToReload[0], configFile]); @@ -7097,7 +7094,7 @@ namespace ts.projectSystem { } function getFile(fileName: string) { - return find(files, file => file.path === fileName); + return find(files, file => file.path === fileName)!; } function verifyNoProjectsUpdatedInBackgroundEvent(filesToReload?: File[]) { @@ -7345,7 +7342,7 @@ namespace ts.projectSystem { const projectService = session.getProjectService(); verifyInitialOpen(file1); checkNumberOfProjects(projectService, { configuredProjects: 1 }); - const project = projectService.configuredProjects.get(configFile.path); + const project = projectService.configuredProjects.get(configFile.path)!; verifyProject(); if (limitHit) { (project as ResolutionCacheHost).maxNumberOfFilesToIterateForInvalidation = 1; @@ -7521,7 +7518,7 @@ namespace ts.projectSystem { const host = createServerHost(files, { useWindowsStylePaths: true }); const projectService = createProjectService(host); projectService.openClientFile(file1.path); - const project = projectService.configuredProjects.get(configFile.path); + const project = projectService.configuredProjects.get(configFile.path)!; assert.isDefined(project); const winsowsStyleLibFilePath = "c:/" + libFile.path.substring(1); checkProjectActualFiles(project, files.map(f => f === libFile ? winsowsStyleLibFilePath : f.path)); @@ -7849,7 +7846,7 @@ new C();` function verifyProjectWithResolvedModule(session: TestSession) { const projectService = session.getProjectService(); - const project = projectService.configuredProjects.get(recognizerDateTimeTsconfigPath); + const project = projectService.configuredProjects.get(recognizerDateTimeTsconfigPath)!; checkProjectActualFiles(project, filesInProjectWithResolvedModule); verifyWatchedFilesAndDirectories(session.host, filesInProjectWithResolvedModule, watchedDirectoriesWithResolvedModule); verifyErrors(session, []); @@ -7857,7 +7854,7 @@ new C();` function verifyProjectWithUnresolvedModule(session: TestSession) { const projectService = session.getProjectService(); - const project = projectService.configuredProjects.get(recognizerDateTimeTsconfigPath); + const project = projectService.configuredProjects.get(recognizerDateTimeTsconfigPath)!; checkProjectActualFiles(project, filesInProjectWithUnresolvedModule); verifyWatchedFilesAndDirectories(session.host, filesInProjectWithUnresolvedModule, watchedDirectoriesWithUnresolvedModule); const startOffset = recognizersDateTimeSrcFile.content.indexOf('"') + 1; @@ -8358,8 +8355,7 @@ new C();` const projectService = createProjectService(host); projectService.openClientFile(index.path); - const project = projectService.configuredProjects.get(configFile.path); - assert.isDefined(project); + const project = Debug.assertDefined(projectService.configuredProjects.get(configFile.path)); verifyProjectAndCompletions(); // Add file2 @@ -8377,7 +8373,7 @@ new C();` verifyProjectAndCompletions(); function verifyProjectAndCompletions() { - const completions = project.getLanguageService().getCompletionsAtPosition(index.path, completionPosition, { includeExternalModuleExports: false, includeInsertTextCompletions: false }); + const completions = project.getLanguageService().getCompletionsAtPosition(index.path, completionPosition, { includeExternalModuleExports: false, includeInsertTextCompletions: false })!; checkArray("Completion Entries", completions.entries.map(e => e.name), expectedCompletions); checkWatchedDirectories(host, emptyArray, /*recursive*/ true); @@ -8443,7 +8439,7 @@ new C();` }; function getProject(service: TestProjectService) { - return service.configuredProjects.get(configFile.path); + return service.configuredProjects.get(configFile.path)!; } function checkProject(service: TestProjectService, moduleIsOrphan: boolean) { @@ -8451,7 +8447,7 @@ new C();` const project = getProject(service); project.getLanguageService(); checkProjectActualFiles(project, [file.path, libFile.path, configFile.path, ...(moduleIsOrphan ? [] : [moduleFile.path])]); - const moduleInfo = service.getScriptInfo(moduleFile.path); + const moduleInfo = service.getScriptInfo(moduleFile.path)!; assert.isDefined(moduleInfo); assert.equal(moduleInfo.isOrphan(), moduleIsOrphan); const key = service.documentRegistry.getKeyForCompilationSettings(project.getCompilationSettings()); @@ -8467,13 +8463,13 @@ new C();` } function changeFileToNotImportModule(service: TestProjectService) { - const info = service.getScriptInfo(file.path); + const info = service.getScriptInfo(file.path)!; service.applyChangesToFile(info, [{ span: { start: 0, length: importModuleContent.length }, newText: "" }]); checkProject(service, /*moduleIsOrphan*/ true); } function changeFileToImportModule(service: TestProjectService) { - const info = service.getScriptInfo(file.path); + const info = service.getScriptInfo(file.path)!; service.applyChangesToFile(info, [{ span: { start: 0, length: 0 }, newText: importModuleContent }]); checkProject(service, /*moduleIsOrphan*/ false); } @@ -8482,7 +8478,7 @@ new C();` const { service } = createServiceAndHost(); const project = getProject(service); - const moduleInfo = service.getScriptInfo(moduleFile.path); + const moduleInfo = service.getScriptInfo(moduleFile.path)!; const sourceFile = moduleInfo.cacheSourceFile.sourceFile; assert.equal(project.getSourceFile(moduleInfo.path), sourceFile); @@ -8500,7 +8496,7 @@ new C();` const { host, service } = createServiceAndHost(); const project = getProject(service); - const moduleInfo = service.getScriptInfo(moduleFile.path); + const moduleInfo = service.getScriptInfo(moduleFile.path)!; const sourceFile = moduleInfo.cacheSourceFile.sourceFile; assert.equal(project.getSourceFile(moduleInfo.path), sourceFile); diff --git a/src/harness/unittests/typingsInstaller.ts b/src/harness/unittests/typingsInstaller.ts index 2f83fe90c8a17..34176e8563cae 100644 --- a/src/harness/unittests/typingsInstaller.ts +++ b/src/harness/unittests/typingsInstaller.ts @@ -1447,7 +1447,7 @@ namespace ts.projectSystem { commander: { typingLocation: commander.path, version: Semver.parse("1.3.0-next.0") } }); const registry = createTypesRegistry("node", "commander"); - registry.get("node")[`ts${versionMajorMinor}`] = "1.3.0-next.1"; + registry.get("node")![`ts${versionMajorMinor}`] = "1.3.0-next.1"; const logger = trackingLogger(); const result = JsTyping.discoverTypings(host, logger.log, [app.path], getDirectoryPath(app.path), emptySafeList, cache, { enable: true }, ["http", "commander"], registry); assert.deepEqual(logger.finish(), [ @@ -1535,8 +1535,8 @@ namespace ts.projectSystem { content: "export let x: number" }; const host = createServerHost([f1, packageFile, packageLockFile]); - let beginEvent: server.BeginInstallTypes; - let endEvent: server.EndInstallTypes; + let beginEvent!: server.BeginInstallTypes; + let endEvent!: server.EndInstallTypes; const installer = new (class extends Installer { constructor() { super(host, { globalTypingsCacheLocation: cachePath, typesRegistry: createTypesRegistry("commander") }); @@ -1583,8 +1583,8 @@ namespace ts.projectSystem { }; const cachePath = "/a/cache/"; const host = createServerHost([f1, packageFile]); - let beginEvent: server.BeginInstallTypes; - let endEvent: server.EndInstallTypes; + let beginEvent: server.BeginInstallTypes | undefined; + let endEvent: server.EndInstallTypes | undefined; const installer: Installer = new (class extends Installer { constructor() { super(host, { globalTypingsCacheLocation: cachePath, typesRegistry: createTypesRegistry("commander") }); @@ -1611,8 +1611,8 @@ namespace ts.projectSystem { assert.isTrue(!!beginEvent); assert.isTrue(!!endEvent); - assert.isTrue(beginEvent.eventId === endEvent.eventId); - assert.isFalse(endEvent.installSuccess); + assert.isTrue(beginEvent!.eventId === endEvent!.eventId); + assert.isFalse(endEvent!.installSuccess); checkNumberOfProjects(projectService, { inferredProjects: 1 }); checkProjectActualFiles(projectService.inferredProjects[0], [f1.path]); }); @@ -1651,7 +1651,7 @@ namespace ts.projectSystem { const appPath = "/a/b/app.js" as Path; const foooPath = "/a/b/node_modules/fooo/index.d.ts"; function verifyResolvedModuleOfFooo(project: server.Project) { - const foooResolution = project.getLanguageService().getProgram().getSourceFileByPath(appPath).resolvedModules.get("fooo"); + const foooResolution = project.getLanguageService().getProgram()!.getSourceFileByPath(appPath)!.resolvedModules!.get("fooo")!; assert.equal(foooResolution.resolvedFileName, foooPath); return foooResolution; } diff --git a/src/harness/unittests/versionCache.ts b/src/harness/unittests/versionCache.ts index f688a9e56bbe4..40f5f43b6dccb 100644 --- a/src/harness/unittests/versionCache.ts +++ b/src/harness/unittests/versionCache.ts @@ -46,7 +46,7 @@ var q:Point=p;`; }); after(() => { - validateEditAtLineCharIndex = undefined; + validateEditAtLineCharIndex = undefined!; }); it("handles empty lines array", () => { @@ -105,10 +105,10 @@ and grew 1cm per day`; }); after(() => { - validateEditAtPosition = undefined; - testContent = undefined; - lines = undefined; - lineMap = undefined; + validateEditAtPosition = undefined!; + testContent = undefined!; + lines = undefined!; + lineMap = undefined!; }); it(`Insert at end of file`, () => { @@ -201,7 +201,7 @@ and grew 1cm per day`; before(() => { // Use scanner.ts, decent size, does not change frequently const testFileName = "src/compiler/scanner.ts"; - testContent = Harness.IO.readFile(testFileName); + testContent = Harness.IO.readFile(testFileName)!; const totalChars = testContent.length; assert.isTrue(totalChars > 0, "Failed to read test file."); @@ -237,16 +237,16 @@ and grew 1cm per day`; }); after(() => { - rsa = undefined; - la = undefined; - las = undefined; - elas = undefined; - ersa = undefined; - ela = undefined; - lines = undefined; - lineMap = undefined; - lineIndex = undefined; - testContent = undefined; + rsa = undefined!; + la = undefined!; + las = undefined!; + elas = undefined!; + ersa = undefined!; + ela = undefined!; + lines = undefined!; + lineMap = undefined!; + lineIndex = undefined!; + testContent = undefined!; }); it("Range (average length 1/4 file size)", () => { diff --git a/src/harness/utils.ts b/src/harness/utils.ts index 83e51a065a055..d7e113c45fbd9 100644 --- a/src/harness/utils.ts +++ b/src/harness/utils.ts @@ -3,8 +3,8 @@ */ namespace utils { const testPathPrefixRegExp = /(?:(file:\/{3})|\/)\.(ts|lib|src)\//g; - export function removeTestPathPrefixes(text: string, retainTrailingDirectorySeparator?: boolean) { - return text !== undefined ? text.replace(testPathPrefixRegExp, (_, scheme) => scheme || (retainTrailingDirectorySeparator ? "/" : "")) : undefined; + export function removeTestPathPrefixes(text: string, retainTrailingDirectorySeparator?: boolean): string { + return text !== undefined ? text.replace(testPathPrefixRegExp, (_, scheme) => scheme || (retainTrailingDirectorySeparator ? "/" : "")) : undefined!; // TODO: GH#18217 } /** @@ -49,7 +49,7 @@ namespace utils { } function guessIndentation(lines: string[]) { - let indentation: number; + let indentation: number | undefined; for (const line of lines) { for (let i = 0; i < line.length && (indentation === undefined || i < indentation); i++) { if (!ts.isWhiteSpaceLike(line.charCodeAt(i))) { diff --git a/src/harness/vfs.ts b/src/harness/vfs.ts index 34a48f5909104..2bae5303996a4 100644 --- a/src/harness/vfs.ts +++ b/src/harness/vfs.ts @@ -935,7 +935,7 @@ namespace vfs { this._applyFilesWorker(value.files, path, deferred); } else { - deferred.push([value as Symlink | Link | Mount, path]); + deferred.push([value, path]); } } } @@ -998,7 +998,7 @@ namespace vfs { directoryExists(path: string): boolean; fileExists(path: string): boolean; getFileSize(path: string): number; - readFile(path: string): string; + readFile(path: string): string | undefined; getWorkspaceRoot(): string; } @@ -1020,7 +1020,7 @@ namespace vfs { } }, readFileSync(path: string): Buffer { - return Buffer.from(host.readFile(path), "utf8"); + return Buffer.from(host.readFile(path)!, "utf8"); // TODO: GH#18217 } }; } @@ -1241,7 +1241,7 @@ namespace vfs { ctimeMs: number; // status change time birthtimeMs: number; // creation time nlink: number; // number of hard links - symlink?: string; + symlink: string; shadowRoot?: SymlinkInode; meta?: collections.Metadata; } @@ -1262,7 +1262,7 @@ namespace vfs { realpath: string; basename: string; parent: DirectoryInode | undefined; - links: collections.SortedMap | undefined; + links: collections.SortedMap; node: Inode | undefined; } diff --git a/src/harness/virtualFileSystemWithWatch.ts b/src/harness/virtualFileSystemWithWatch.ts index 96873f1c08325..0afa67880a4d8 100644 --- a/src/harness/virtualFileSystemWithWatch.ts +++ b/src/harness/virtualFileSystemWithWatch.ts @@ -179,7 +179,7 @@ interface Array {}` verifyMapSize(caption, actual, arrayFrom(expectedKeys.keys())); expectedKeys.forEach((count, name) => { assert.isTrue(actual.has(name), `${caption}: expected to contain ${name}, actual keys: ${arrayFrom(actual.keys())}`); - assert.equal(actual.get(name).length, count, `${caption}: Expected to be have ${count} entries for ${name}. Actual entry: ${JSON.stringify(actual.get(name))}`); + assert.equal(actual.get(name)!.length, count, `${caption}: Expected to be have ${count} entries for ${name}. Actual entry: ${JSON.stringify(actual.get(name))}`); }); } @@ -322,7 +322,7 @@ interface Array {}` readonly watchedFiles = createMultiMap(); private readonly executingFilePath: string; private readonly currentDirectory: string; - private readonly dynamicPriorityWatchFile: HostWatchFile; + private readonly dynamicPriorityWatchFile: HostWatchFile | undefined; private readonly customRecursiveWatchDirectory: HostWatchDirectory | undefined; constructor(public withSafeList: boolean, public useCaseSensitiveFileNames: boolean, executingFilePath: string, currentDirectory: string, fileOrFolderorSymLinkList: ReadonlyArray, public readonly newLine = "\n", public readonly useWindowsStylePath?: boolean, private readonly environmentVariables?: Map) { @@ -465,7 +465,7 @@ interface Array {}` else { currentEntry.content = content; currentEntry.modifiedTime = this.now(); - this.fs.get(getDirectoryPath(currentEntry.path)).modifiedTime = this.now(); + this.fs.get(getDirectoryPath(currentEntry.path))!.modifiedTime = this.now(); if (options && options.invokeDirectoryWatcherInsteadOfFileChanged) { this.invokeDirectoryWatcher(getDirectoryPath(currentEntry.fullPath), currentEntry.fullPath); } @@ -570,7 +570,7 @@ interface Array {}` this.invokeDirectoryWatcher(folder.fullPath, fileOrDirectory.fullPath); } - private removeFileOrFolder(fileOrDirectory: FsFile | FsFolder | FsSymLink, isRemovableLeafFolder: (folder: FsFolder) => boolean, isRenaming?: boolean) { + private removeFileOrFolder(fileOrDirectory: FsFile | FsFolder | FsSymLink, isRemovableLeafFolder: (folder: FsFolder) => boolean, isRenaming = false) { const basePath = getDirectoryPath(fileOrDirectory.path); const baseFolder = this.fs.get(basePath) as FsFolder; if (basePath !== fileOrDirectory.path) { @@ -621,15 +621,15 @@ interface Array {}` // For overriding the methods invokeWatchedDirectoriesCallback(folderFullPath: string, relativePath: string) { - invokeWatcherCallbacks(this.watchedDirectories.get(this.toPath(folderFullPath)), cb => this.directoryCallback(cb, relativePath)); + invokeWatcherCallbacks(this.watchedDirectories.get(this.toPath(folderFullPath))!, cb => this.directoryCallback(cb, relativePath)); } invokeWatchedDirectoriesRecursiveCallback(folderFullPath: string, relativePath: string) { - invokeWatcherCallbacks(this.watchedDirectoriesRecursive.get(this.toPath(folderFullPath)), cb => this.directoryCallback(cb, relativePath)); + invokeWatcherCallbacks(this.watchedDirectoriesRecursive.get(this.toPath(folderFullPath))!, cb => this.directoryCallback(cb, relativePath)); } invokeFileWatcher(fileFullPath: string, eventKind: FileWatcherEventKind, useFileNameInCallback?: boolean) { - invokeWatcherCallbacks(this.watchedFiles.get(this.toPath(fileFullPath)), ({ cb, fileName }) => cb(useFileNameInCallback ? fileName : fileFullPath, eventKind)); + invokeWatcherCallbacks(this.watchedFiles.get(this.toPath(fileFullPath))!, ({ cb, fileName }) => cb(useFileNameInCallback ? fileName : fileFullPath, eventKind)); } private getRelativePathToDirectory(directoryFullPath: string, fileFullPath: string) { @@ -687,11 +687,11 @@ interface Array {}` private toFsFolder(path: string): FsFolder { const fsFolder = this.toFsEntry(path) as FsFolder; - fsFolder.entries = [] as SortedArray; + fsFolder.entries = [] as FSEntry[] as SortedArray; // https://github.com/Microsoft/TypeScript/issues/19873 return fsFolder; } - private getRealFsEntry(isFsEntry: (fsEntry: FSEntry) => fsEntry is T, path: Path, fsEntry = this.fs.get(path)): T | undefined { + private getRealFsEntry(isFsEntry: (fsEntry: FSEntry) => fsEntry is T, path: Path, fsEntry = this.fs.get(path)!): T | undefined { if (isFsEntry(fsEntry)) { return fsEntry; } @@ -737,21 +737,21 @@ interface Array {}` getModifiedTime(s: string) { const path = this.toFullPath(s); const fsEntry = this.fs.get(path); - return fsEntry && fsEntry.modifiedTime; + return (fsEntry && fsEntry.modifiedTime)!; // TODO: GH#18217 } - readFile(s: string): string { + readFile(s: string): string | undefined { const fsEntry = this.getRealFile(this.toFullPath(s)); return fsEntry ? fsEntry.content : undefined; } getFileSize(s: string) { const path = this.toFullPath(s); - const entry = this.fs.get(path); + const entry = this.fs.get(path)!; if (isFsFile(entry)) { return entry.fileSize ? entry.fileSize : entry.content.length; } - return undefined; + return undefined!; // TODO: GH#18217 } directoryExists(s: string) { @@ -812,7 +812,7 @@ interface Array {}` } createSHA256Hash(s: string): string { - return sys.createSHA256Hash(s); + return sys.createSHA256Hash!(s); } watchFile(fileName: string, cb: FileWatcherCallback, pollingInterval: number) { @@ -925,7 +925,7 @@ interface Array {}` } const dirFullPath = this.realpath(getDirectoryPath(fullPath)); const realFullPath = combinePaths(dirFullPath, getBaseFileName(fullPath)); - const fsEntry = this.fs.get(this.toPath(realFullPath)); + const fsEntry = this.fs.get(this.toPath(realFullPath))!; if (isFsSymLink(fsEntry)) { return this.realpath(fsEntry.symLink); } @@ -934,7 +934,7 @@ interface Array {}` } readonly exitMessage = "System Exit"; - exitCode: number; + exitCode: number | undefined; readonly resolvePath = (s: string) => s; readonly getExecutingFilePath = () => this.executingFilePath; readonly getCurrentDirectory = () => this.currentDirectory; @@ -943,7 +943,7 @@ interface Array {}` throw new Error(this.exitMessage); } getEnvironmentVariable(name: string) { - return this.environmentVariables && this.environmentVariables.get(name); + return this.environmentVariables && this.environmentVariables.get(name) || ""; } } } diff --git a/src/server/cancellationToken/cancellationToken.ts b/src/server/cancellationToken/cancellationToken.ts index b7243ccd87111..9b74ebb713a7a 100644 --- a/src/server/cancellationToken/cancellationToken.ts +++ b/src/server/cancellationToken/cancellationToken.ts @@ -19,7 +19,7 @@ function pipeExists(name: string): boolean { } function createCancellationToken(args: string[]): ServerCancellationToken { - let cancellationPipeName: string; + let cancellationPipeName: string | undefined; for (let i = 0; i < args.length - 1; i++) { if (args[i] === "--cancellationPipeName") { cancellationPipeName = args[i + 1]; @@ -43,7 +43,7 @@ function createCancellationToken(args: string[]): ServerCancellationToken { if (namePrefix.length === 0 || namePrefix.indexOf("*") >= 0) { throw new Error("Invalid name for template cancellation pipe: it should have length greater than 2 characters and contain only one '*'."); } - let perRequestPipeName: string; + let perRequestPipeName: string | undefined; let currentRequestId: number; return { isCancellationRequested: () => perRequestPipeName !== undefined && pipeExists(perRequestPipeName), @@ -61,7 +61,7 @@ function createCancellationToken(args: string[]): ServerCancellationToken { } else { return { - isCancellationRequested: () => pipeExists(cancellationPipeName), + isCancellationRequested: () => pipeExists(cancellationPipeName!), // TODO: GH#18217 setRequest: (_requestId: number): void => void 0, resetRequest: (_requestId: number): void => void 0 }; diff --git a/src/server/client.ts b/src/server/client.ts index 2a97a54a18dcc..a7e76fb06a897 100644 --- a/src/server/client.ts +++ b/src/server/client.ts @@ -50,7 +50,7 @@ namespace ts.server { private getLineMap(fileName: string): number[] { let lineMap = this.lineMaps.get(fileName); if (!lineMap) { - lineMap = computeLineStarts(getSnapshotText(this.host.getScriptSnapshot(fileName))); + lineMap = computeLineStarts(getSnapshotText(this.host.getScriptSnapshot(fileName)!)); this.lineMaps.set(fileName, lineMap); } return lineMap; @@ -89,10 +89,9 @@ namespace ts.server { private processResponse(request: protocol.Request): T { let foundResponseMessage = false; - let lastMessage: string; - let response: T; + let response!: T; while (!foundResponseMessage) { - lastMessage = this.messages.shift(); + const lastMessage = this.messages.shift()!; Debug.assert(!!lastMessage, "Did not receive any responses."); const responseBody = extractMessage(lastMessage); try { @@ -133,7 +132,7 @@ namespace ts.server { changeFile(fileName: string, start: number, end: number, insertString: string): void { // clear the line map after an edit - this.lineMaps.set(fileName, undefined); + this.lineMaps.set(fileName, undefined!); // TODO: GH#18217 const args: protocol.ChangeRequestArgs = { ...this.createFileLocationRequestArgsWithEndLineAndOffset(fileName, start, end), insertString }; this.processRequest(CommandNames.Change, args); @@ -149,14 +148,15 @@ namespace ts.server { const request = this.processRequest(CommandNames.Quickinfo, args); const response = this.processResponse(request); + const body = response.body!; // TODO: GH#18217 return { - kind: response.body.kind, - kindModifiers: response.body.kindModifiers, - textSpan: this.decodeSpan(response.body, fileName), - displayParts: [{ kind: "text", text: response.body.displayString }], - documentation: [{ kind: "text", text: response.body.documentation }], - tags: response.body.tags + kind: body.kind, + kindModifiers: body.kindModifiers, + textSpan: this.decodeSpan(body, fileName), + displayParts: [{ kind: "text", text: body.displayString }], + documentation: [{ kind: "text", text: body.documentation }], + tags: body.tags }; } @@ -167,8 +167,8 @@ namespace ts.server { const response = this.processResponse(request); return { - configFileName: response.body.configFileName, - fileNames: response.body.fileNames + configFileName: response.body!.configFileName, // TODO: GH#18217 + fileNames: response.body!.fileNames }; } @@ -183,7 +183,7 @@ namespace ts.server { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, - entries: response.body.map(entry => { + entries: response.body!.map(entry => { // TODO: GH#18217 if (entry.replacementSpan !== undefined) { const { name, kind, kindModifiers, sortText, replacementSpan, hasAction, source, isRecommended } = entry; // TODO: GH#241 @@ -201,10 +201,9 @@ namespace ts.server { const request = this.processRequest(CommandNames.CompletionDetails, args); const response = this.processResponse(request); - Debug.assert(response.body.length === 1, "Unexpected length of completion details response body."); - - const convertedCodeActions = map(response.body[0].codeActions, ({ description, changes }) => ({ description, changes: this.convertChanges(changes, fileName) })); - return { ...response.body[0], codeActions: convertedCodeActions }; + Debug.assert(response.body!.length === 1, "Unexpected length of completion details response body."); + const convertedCodeActions = map(response.body![0].codeActions, ({ description, changes }) => ({ description, changes: this.convertChanges(changes, fileName) })); + return { ...response.body![0], codeActions: convertedCodeActions }; } getCompletionEntrySymbol(_fileName: string, _position: number, _entryName: string): Symbol { @@ -220,14 +219,14 @@ namespace ts.server { const request = this.processRequest(CommandNames.Navto, args); const response = this.processResponse(request); - return response.body.map(entry => ({ + return response.body!.map(entry => ({ // TODO: GH#18217 name: entry.name, containerName: entry.containerName || "", containerKind: entry.containerKind || ScriptElementKind.unknown, kind: entry.kind, - kindModifiers: entry.kindModifiers, - matchKind: entry.matchKind, - isCaseSensitive: entry.isCaseSensitive, + kindModifiers: entry.kindModifiers!, // TODO: GH#18217 + matchKind: entry.matchKind!, // TODO: GH#18217 + isCaseSensitive: entry.isCaseSensitive!, // TODO: GH#18217 fileName: entry.file, textSpan: this.decodeSpan(entry), })); @@ -241,11 +240,11 @@ namespace ts.server { const request = this.processRequest(CommandNames.Format, args); const response = this.processResponse(request); - return response.body.map(entry => this.convertCodeEditsToTextChange(file, entry)); + return response.body!.map(entry => this.convertCodeEditsToTextChange(file, entry)); // TODO: GH#18217 } getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions): TextChange[] { - return this.getFormattingEditsForRange(fileName, 0, this.host.getScriptSnapshot(fileName).getLength(), options); + return this.getFormattingEditsForRange(fileName, 0, this.host.getScriptSnapshot(fileName)!.getLength(), options); } getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, _options: FormatCodeOptions): TextChange[] { @@ -255,7 +254,7 @@ namespace ts.server { const request = this.processRequest(CommandNames.Formatonkey, args); const response = this.processResponse(request); - return response.body.map(entry => this.convertCodeEditsToTextChange(fileName, entry)); + return response.body!.map(entry => this.convertCodeEditsToTextChange(fileName, entry)); // TODO: GH#18217 } getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] { @@ -264,7 +263,7 @@ namespace ts.server { const request = this.processRequest(CommandNames.Definition, args); const response = this.processResponse(request); - return response.body.map(entry => ({ + return response.body!.map(entry => ({ // TODO: GH#18217 containerKind: ScriptElementKind.unknown, containerName: "", fileName: entry.file, @@ -281,7 +280,7 @@ namespace ts.server { const response = this.processResponse(request); return { - definitions: response.body.definitions.map(entry => ({ + definitions: response.body!.definitions.map(entry => ({ // TODO: GH#18217 containerKind: ScriptElementKind.unknown, containerName: "", fileName: entry.file, @@ -289,7 +288,7 @@ namespace ts.server { kind: ScriptElementKind.unknown, name: "" })), - textSpan: this.decodeSpan(response.body.textSpan, request.arguments.file) + textSpan: this.decodeSpan(response.body!.textSpan, request.arguments.file) }; } @@ -299,7 +298,7 @@ namespace ts.server { const request = this.processRequest(CommandNames.TypeDefinition, args); const response = this.processResponse(request); - return response.body.map(entry => ({ + return response.body!.map(entry => ({ // TODO: GH#18217 containerKind: ScriptElementKind.unknown, containerName: "", fileName: entry.file, @@ -315,7 +314,7 @@ namespace ts.server { const request = this.processRequest(CommandNames.Implementation, args); const response = this.processResponse(request); - return response.body.map(entry => ({ + return response.body!.map(entry => ({ // TODO: GH#18217 fileName: entry.file, textSpan: this.decodeSpan(entry), kind: ScriptElementKind.unknown, @@ -334,7 +333,7 @@ namespace ts.server { const request = this.processRequest(CommandNames.References, args); const response = this.processResponse(request); - return response.body.refs.map(entry => ({ + return response.body!.refs.map(entry => ({ // TODO: GH#18217 fileName: entry.file, textSpan: this.decodeSpan(entry), isWriteAccess: entry.isWriteAccess, @@ -349,7 +348,7 @@ namespace ts.server { getSyntacticDiagnostics(file: string): DiagnosticWithLocation[] { return this.getDiagnostics(file, CommandNames.SyntacticDiagnosticsSync); } - getSemanticDiagnostics(file: string): DiagnosticWithLocation[] { + getSemanticDiagnostics(file: string): Diagnostic[] { return this.getDiagnostics(file, CommandNames.SemanticDiagnosticsSync); } getSuggestionDiagnostics(file: string): DiagnosticWithLocation[] { @@ -364,7 +363,7 @@ namespace ts.server { const category = firstDefined(Object.keys(DiagnosticCategory), id => isString(id) && entry.category === id.toLowerCase() ? (DiagnosticCategory)[id] : undefined); return { - file: undefined, + file: undefined!, // TODO: GH#18217 start: entry.start, length: entry.length, messageText: entry.message, @@ -384,8 +383,9 @@ namespace ts.server { const request = this.processRequest(CommandNames.Rename, args); const response = this.processResponse(request); + const body = response.body!; // TODO: GH#18217 const locations: RenameLocation[] = []; - for (const entry of response.body.locs) { + for (const entry of body.locs) { const fileName = entry.file; for (const loc of entry.locs) { locations.push({ textSpan: this.decodeSpan(loc, fileName), fileName }); @@ -393,17 +393,17 @@ namespace ts.server { } return this.lastRenameEntry = { - canRename: response.body.info.canRename, - displayName: response.body.info.displayName, - fullDisplayName: response.body.info.fullDisplayName, - kind: response.body.info.kind, - kindModifiers: response.body.info.kindModifiers, - localizedErrorMessage: response.body.info.localizedErrorMessage, + canRename: body.info.canRename, + displayName: body.info.displayName, + fullDisplayName: body.info.fullDisplayName, + kind: body.info.kind, + kindModifiers: body.info.kindModifiers, + localizedErrorMessage: body.info.localizedErrorMessage, triggerSpan: createTextSpanFromBounds(position, position), fileName, position, - findInStrings, - findInComments, + findInStrings: !!findInStrings, + findInComments: !!findInComments, locations, }; } @@ -420,7 +420,7 @@ namespace ts.server { return this.lastRenameEntry.locations; } - private decodeNavigationBarItems(items: protocol.NavigationBarItem[], fileName: string, lineMap: number[]): NavigationBarItem[] { + private decodeNavigationBarItems(items: protocol.NavigationBarItem[] | undefined, fileName: string, lineMap: number[]): NavigationBarItem[] { if (!items) { return []; } @@ -460,7 +460,7 @@ namespace ts.server { const response = this.processResponse(request); const lineMap = this.getLineMap(file); - return this.decodeNavigationTree(response.body, file, lineMap); + return this.decodeNavigationTree(response.body!, file, lineMap); // TODO: GH#18217 } private decodeSpan(span: protocol.TextSpan & { file: string }): TextSpan; @@ -488,7 +488,7 @@ namespace ts.server { const response = this.processResponse(request); if (!response.body) { - return undefined; + return undefined!; // TODO: GH#18217 } const { items, applicableSpan: encodedApplicableSpan, selectedItemIndex, argumentIndex, argumentCount } = response.body; @@ -504,7 +504,7 @@ namespace ts.server { const request = this.processRequest(CommandNames.Occurrences, args); const response = this.processResponse(request); - return response.body.map(entry => ({ + return response.body!.map(entry => ({ // TODO: GH#18217 fileName: entry.file, textSpan: this.decodeSpan(entry), isWriteAccess: entry.isWriteAccess, @@ -518,7 +518,7 @@ namespace ts.server { const request = this.processRequest(CommandNames.DocumentHighlights, args); const response = this.processResponse(request); - return response.body.map(item => ({ + return response.body!.map(item => ({ // TODO: GH#18217 fileName: item.file, highlightSpans: item.highlightSpans.map(span => ({ textSpan: this.decodeSpan(span, item.file), @@ -531,7 +531,7 @@ namespace ts.server { const request = this.processRequest(CommandNames.GetOutliningSpans, { file }); const response = this.processResponse(request); - return response.body.map(item => ({ + return response.body!.map(item => ({ textSpan: this.decodeSpan(item.textSpan, file), hintSpan: this.decodeSpan(item.hintSpan, file), bannerText: item.bannerText, @@ -562,7 +562,7 @@ namespace ts.server { const request = this.processRequest(CommandNames.GetCodeFixes, args); const response = this.processResponse(request); - return response.body.map(({ fixName, description, changes, commands, fixId, fixAllDescription }) => + return response.body!.map(({ fixName, description, changes, commands, fixId, fixAllDescription }) => // TODO: GH#18217 ({ fixName, description, changes: this.convertChanges(changes, file), commands: commands as CodeActionCommand[], fixId, fixAllDescription })); } @@ -598,7 +598,7 @@ namespace ts.server { const request = this.processRequest(CommandNames.GetApplicableRefactors, args); const response = this.processResponse(request); - return response.body; + return response.body!; // TODO: GH#18217 } getEditsForRefactor( @@ -624,7 +624,7 @@ namespace ts.server { const renameFilename: string | undefined = response.body.renameFilename; let renameLocation: number | undefined; if (renameFilename !== undefined) { - renameLocation = this.lineOffsetToPosition(renameFilename, response.body.renameLocation); + renameLocation = this.lineOffsetToPosition(renameFilename, response.body.renameLocation!); // TODO: GH#18217 } return { @@ -672,7 +672,7 @@ namespace ts.server { const request = this.processRequest(CommandNames.Brace, args); const response = this.processResponse(request); - return response.body.map(entry => this.decodeSpan(entry, fileName)); + return response.body!.map(entry => this.decodeSpan(entry, fileName)); // TODO: GH#18217 } getIndentationAtPosition(_fileName: string, _position: number, _options: EditorOptions): number { diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 71c5791187721..77e5b2ed8294d 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -71,7 +71,7 @@ namespace ts.server { } export interface ProjectInfoTypeAcquisitionData { - readonly enable: boolean; + readonly enable: boolean | undefined; // Actual values of include/exclude entries are scrubbed. readonly include: boolean; readonly exclude: boolean; @@ -225,13 +225,13 @@ namespace ts.server { interface FilePropertyReader { getFileName(f: T): string; getScriptKind(f: T, extraFileExtensions?: FileExtensionInfo[]): ScriptKind; - hasMixedContent(f: T, extraFileExtensions: FileExtensionInfo[]): boolean; + hasMixedContent(f: T, extraFileExtensions: FileExtensionInfo[] | undefined): boolean; } const fileNamePropertyReader: FilePropertyReader = { getFileName: x => x, getScriptKind: (fileName, extraFileExtensions) => { - let result: ScriptKind; + let result: ScriptKind | undefined; if (extraFileExtensions) { const fileExtension = getAnyExtensionFromPath(fileName); if (fileExtension) { @@ -244,18 +244,18 @@ namespace ts.server { }); } } - return result; + return result!; // TODO: GH#18217 }, hasMixedContent: (fileName, extraFileExtensions) => some(extraFileExtensions, ext => ext.isMixedContent && fileExtensionIs(fileName, ext.extension)), }; const externalFilePropertyReader: FilePropertyReader = { getFileName: x => x.fileName, - getScriptKind: x => tryConvertScriptKindName(x.scriptKind), - hasMixedContent: x => x.hasMixedContent, + getScriptKind: x => tryConvertScriptKindName(x.scriptKind!), // TODO: GH#18217 + hasMixedContent: x => !!x.hasMixedContent, }; - function findProjectByName(projectName: string, projects: T[]): T { + function findProjectByName(projectName: string, projects: T[]): T | undefined { for (const proj of projects) { if (proj.getProjectName() === projectName) { return proj; @@ -374,7 +374,7 @@ namespace ts.server { /** * Open files: with value being project root path, and key being Path of the file that is open */ - readonly openFiles = createMap(); + readonly openFiles = createMap(); /** * Map of open files that are opened without complete path but have projectRoot as current directory */ @@ -413,7 +413,7 @@ namespace ts.server { public readonly useSingleInferredProject: boolean; public readonly useInferredProjectPerProjectRoot: boolean; public readonly typingsInstaller: ITypingsInstaller; - private readonly globalCacheLocationDirectoryPath: Path; + private readonly globalCacheLocationDirectoryPath: Path | undefined; public readonly throttleWaitMilliseconds?: number; private readonly eventHandler?: ProjectServiceEventHandler; private readonly suppressDiagnosticEvents?: boolean; @@ -453,8 +453,9 @@ namespace ts.server { } this.currentDirectory = toNormalizedPath(this.host.getCurrentDirectory()); this.toCanonicalFileName = createGetCanonicalFileName(this.host.useCaseSensitiveFileNames); - this.globalCacheLocationDirectoryPath = this.typingsInstaller.globalTypingsCacheLocation && - ensureTrailingDirectorySeparator(this.toPath(this.typingsInstaller.globalTypingsCacheLocation)); + this.globalCacheLocationDirectoryPath = this.typingsInstaller.globalTypingsCacheLocation + ? ensureTrailingDirectorySeparator(this.toPath(this.typingsInstaller.globalTypingsCacheLocation)) + : undefined; this.throttledOperations = new ThrottledOperations(this.host, this.logger); if (this.typesMapLocation) { @@ -498,15 +499,14 @@ namespace ts.server { /*@internal*/ setDocument(key: DocumentRegistryBucketKey, path: Path, sourceFile: SourceFile) { - const info = this.getScriptInfoForPath(path); - Debug.assert(!!info); + const info = Debug.assertDefined(this.getScriptInfoForPath(path)); info.cacheSourceFile = { key, sourceFile }; } /*@internal*/ - getDocument(key: DocumentRegistryBucketKey, path: Path) { + getDocument(key: DocumentRegistryBucketKey, path: Path): SourceFile | undefined { const info = this.getScriptInfoForPath(path); - return info && info.cacheSourceFile && info.cacheSourceFile.key === key && info.cacheSourceFile.sourceFile; + return info && info.cacheSourceFile && info.cacheSourceFile.key === key ? info.cacheSourceFile.sourceFile : undefined; } /* @internal */ @@ -533,7 +533,7 @@ namespace ts.server { private loadTypesMap() { try { - const fileContent = this.host.readFile(this.typesMapLocation); + const fileContent = this.host.readFile(this.typesMapLocation!); // TODO: GH#18217 if (fileContent === undefined) { this.logger.info(`Provided types map file "${this.typesMapLocation}" doesn't exist`); return; @@ -623,7 +623,7 @@ namespace ts.server { const event: ProjectsUpdatedInBackgroundEvent = { eventName: ProjectsUpdatedInBackgroundEvent, data: { - openFiles: arrayFrom(this.openFiles.keys(), path => this.getScriptInfoForPath(path as Path).fileName) + openFiles: arrayFrom(this.openFiles.keys(), path => this.getScriptInfoForPath(path as Path)!.fileName) } }; this.eventHandler(event); @@ -673,7 +673,7 @@ namespace ts.server { project.projectRootPath === canonicalProjectRootPath : !project.projectRootPath || !this.compilerOptionsForInferredProjectsPerProjectRoot.has(project.projectRootPath)) { project.setCompilerOptions(compilerOptions); - project.compileOnSaveEnabled = compilerOptions.compileOnSave; + project.compileOnSaveEnabled = compilerOptions.compileOnSave!; project.markAsDirty(); this.delayUpdateProjectGraph(project); } @@ -692,7 +692,7 @@ namespace ts.server { return this.findExternalProjectByProjectName(projectName) || this.findConfiguredProjectByProjectName(toNormalizedPath(projectName)); } - getDefaultProjectForFile(fileName: NormalizedPath, ensureProject: boolean) { + getDefaultProjectForFile(fileName: NormalizedPath, ensureProject: boolean): Project | undefined { let scriptInfo = this.getScriptInfoForNormalizedPath(fileName); if (ensureProject && (!scriptInfo || scriptInfo.isOrphan())) { this.ensureProjectStructuresUptoDate(); @@ -702,7 +702,7 @@ namespace ts.server { } return scriptInfo.getDefaultProject(); } - return scriptInfo && !scriptInfo.isOrphan() && scriptInfo.getDefaultProject(); + return scriptInfo && !scriptInfo.isOrphan() ? scriptInfo.getDefaultProject() : undefined; } getScriptInfoEnsuringProjectsUptoDate(uncheckedFileName: string) { @@ -810,7 +810,7 @@ namespace ts.server { /** Gets the config file existence info for the configured project */ /*@internal*/ getConfigFileExistenceInfo(project: ConfiguredProject) { - return this.configFileExistenceInfoCache.get(project.canonicalConfigFilePath); + return this.configFileExistenceInfoCache.get(project.canonicalConfigFilePath)!; } private onConfigChangedForConfiguredProject(project: ConfiguredProject, eventKind: FileWatcherEventKind) { @@ -846,7 +846,7 @@ namespace ts.server { private onConfigFileChangeForOpenScriptInfo(configFileName: NormalizedPath, eventKind: FileWatcherEventKind) { // This callback is called only if we dont have config file project for this config file const canonicalConfigPath = normalizedPathToPath(configFileName, this.currentDirectory, this.toCanonicalFileName); - const configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigPath); + const configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigPath)!; configFileExistenceInfo.exists = (eventKind !== FileWatcherEventKind.Deleted); this.logConfigFileWatchUpdate(configFileName, canonicalConfigPath, configFileExistenceInfo, ConfigFileWatcherStatus.ReloadingFiles); @@ -975,7 +975,7 @@ namespace ts.server { if (ensureProjectsForOpenFiles) { // collect orphaned files and assign them to inferred project just like we treat open of a file this.openFiles.forEach((projectRootPath, path) => { - const info = this.getScriptInfoForPath(path as Path); + const info = this.getScriptInfoForPath(path as Path)!; // collect all orphaned script infos from open files if (info.isOrphan()) { this.assignOrphanScriptInfoToInferredProject(info, projectRootPath); @@ -1001,7 +1001,7 @@ namespace ts.server { this.filenameToScriptInfo.delete(info.path); const realpath = info.getRealpathIfDifferent(); if (realpath) { - this.realpathToScriptInfos.remove(realpath, info); + this.realpathToScriptInfos!.remove(realpath, info); // TODO: GH#18217 } } @@ -1091,7 +1091,7 @@ namespace ts.server { const inferredRoots: string[] = []; const otherFiles: string[] = []; configFileExistenceInfo.openFilesImpactedByConfigFile.forEach((isRootOfInferredProject, key) => { - const info = this.getScriptInfoForPath(key as Path); + const info = this.getScriptInfoForPath(key as Path)!; (isRootOfInferredProject ? inferredRoots : otherFiles).push(info.fileName); }); @@ -1235,7 +1235,7 @@ namespace ts.server { const projectRootPath = this.openFiles.get(info.path); let searchPath = asNormalizedPath(getDirectoryPath(info.fileName)); - const isSearchPathInProjectRoot = () => containsPath(projectRootPath, searchPath, this.currentDirectory, !this.host.useCaseSensitiveFileNames); + const isSearchPathInProjectRoot = () => containsPath(projectRootPath!, searchPath, this.currentDirectory, !this.host.useCaseSensitiveFileNames); // If projectRootPath doesnt contain info.path, then do normal search for config file const anySearchPathOk = !projectRootPath || !isSearchPathInProjectRoot(); @@ -1310,7 +1310,7 @@ namespace ts.server { this.logger.info("Open files: "); this.openFiles.forEach((projectRootPath, path) => { - const info = this.getScriptInfoForPath(path as Path); + const info = this.getScriptInfoForPath(path as Path)!; this.logger.info(`\tFileName: ${info.fileName} ProjectRootPath: ${projectRootPath}`); if (writeProjectFileNames) { this.logger.info(`\t\tProjects: ${info.containingProjects.map(p => p.getProjectName())}`); @@ -1337,7 +1337,7 @@ namespace ts.server { private convertConfigFileContentToProjectOptions(configFilename: string, cachedDirectoryStructureHost: CachedDirectoryStructureHost) { configFilename = normalizePath(configFilename); - const configFileContent = this.host.readFile(configFilename); + const configFileContent = this.host.readFile(configFilename)!; // TODO: GH#18217 const result = parseJsonText(configFilename, configFileContent); if (!result.endOfFileToken) { @@ -1366,7 +1366,7 @@ namespace ts.server { configHasFilesProperty: parsedCommandLine.raw.files !== undefined, configHasIncludeProperty: parsedCommandLine.raw.include !== undefined, configHasExcludeProperty: parsedCommandLine.raw.exclude !== undefined, - wildcardDirectories: createMapFromTemplate(parsedCommandLine.wildcardDirectories), + wildcardDirectories: createMapFromTemplate(parsedCommandLine.wildcardDirectories!), // TODO: GH#18217 typeAcquisition: parsedCommandLine.typeAcquisition, compileOnSave: parsedCommandLine.compileOnSave, projectReferences: parsedCommandLine.projectReferences @@ -1376,7 +1376,7 @@ namespace ts.server { } /** Get a filename if the language service exceeds the maximum allowed program size; otherwise returns undefined. */ - private getFilenameForExceededTotalSizeLimitForNonTsFiles(name: string, options: CompilerOptions, fileNames: T[], propertyReader: FilePropertyReader): string | undefined { + private getFilenameForExceededTotalSizeLimitForNonTsFiles(name: string, options: CompilerOptions | undefined, fileNames: T[], propertyReader: FilePropertyReader): string | undefined { if (options && options.disableSizeLimit || !this.host.getFileSize) { return; } @@ -1414,7 +1414,7 @@ namespace ts.server { function getTop5LargestFiles({ propertyReader, hasTypeScriptFileExtension, host }: { propertyReader: FilePropertyReader, hasTypeScriptFileExtension: (filename: string) => boolean, host: ServerHost }) { return fileNames.map(f => propertyReader.getFileName(f)) .filter(name => hasTypeScriptFileExtension(name)) - .map(name => ({ name, size: host.getFileSize(name) })) + .map(name => ({ name, size: host.getFileSize!(name) })) // TODO: GH#18217 .sort((a, b) => b.size - a.size) .slice(0, 5); } @@ -1469,7 +1469,7 @@ namespace ts.server { return "other"; } - const configFilePath = project instanceof ConfiguredProject && project.getConfigFilePath(); + const configFilePath = project instanceof ConfiguredProject ? project.getConfigFilePath() : undefined!; // TODO: GH#18217 return getBaseConfigFileName(configFilePath) || "other"; } @@ -1490,16 +1490,16 @@ namespace ts.server { } private createConfiguredProject(configFileName: NormalizedPath) { - const cachedDirectoryStructureHost = createCachedDirectoryStructureHost(this.host, this.host.getCurrentDirectory(), this.host.useCaseSensitiveFileNames); + const cachedDirectoryStructureHost = createCachedDirectoryStructureHost(this.host, this.host.getCurrentDirectory(), this.host.useCaseSensitiveFileNames)!; // TODO: GH#18217 const { projectOptions, configFileErrors, configFileSpecs } = this.convertConfigFileContentToProjectOptions(configFileName, cachedDirectoryStructureHost); this.logger.info(`Opened configuration file ${configFileName}`); - const lastFileExceededProgramSize = this.getFilenameForExceededTotalSizeLimitForNonTsFiles(configFileName, projectOptions.compilerOptions, projectOptions.files, fileNamePropertyReader); + const lastFileExceededProgramSize = this.getFilenameForExceededTotalSizeLimitForNonTsFiles(configFileName, projectOptions.compilerOptions, projectOptions.files!, fileNamePropertyReader); // TODO: GH#18217 const project = new ConfiguredProject( configFileName, this, this.documentRegistry, projectOptions.configHasFilesProperty, - projectOptions.compilerOptions, + projectOptions.compilerOptions!, // TODO: GH#18217 lastFileExceededProgramSize, projectOptions.compileOnSave === undefined ? false : projectOptions.compileOnSave, cachedDirectoryStructureHost, @@ -1516,12 +1516,12 @@ namespace ts.server { project ); if (!lastFileExceededProgramSize) { - project.watchWildcards(projectOptions.wildcardDirectories); + project.watchWildcards(projectOptions.wildcardDirectories!); // TODO: GH#18217 } project.setProjectErrors(configFileErrors); - const filesToAdd = projectOptions.files.concat(project.getExternalFiles()); - this.addFilesToNonInferredProjectAndUpdateGraph(project, filesToAdd, fileNamePropertyReader, projectOptions.typeAcquisition); + const filesToAdd = projectOptions.files!.concat(project.getExternalFiles()); + this.addFilesToNonInferredProjectAndUpdateGraph(project, filesToAdd, fileNamePropertyReader, projectOptions.typeAcquisition!); // TODO: GH#18217 this.configuredProjects.set(project.canonicalConfigFilePath, project); this.setConfigFileExistenceByNewConfiguredProject(project); this.sendProjectTelemetry(configFileName, project, projectOptions); @@ -1541,7 +1541,7 @@ namespace ts.server { // Use the project's fileExists so that it can use caching instead of reaching to disk for the query if (!isDynamic && !project.fileExists(newRootFile)) { path = normalizedPathToPath(normalizedPath, this.currentDirectory, this.toCanonicalFileName); - const existingValue = projectRootFilesMap.get(path); + const existingValue = projectRootFilesMap.get(path)!; if (isScriptInfo(existingValue)) { project.removeFile(existingValue, /*fileExists*/ false, /*detachFromProject*/ true); } @@ -1551,7 +1551,7 @@ namespace ts.server { else { const scriptKind = propertyReader.getScriptKind(f, this.hostConfiguration.extraFileExtensions); const hasMixedContent = propertyReader.hasMixedContent(f, this.hostConfiguration.extraFileExtensions); - scriptInfo = this.getOrCreateScriptInfoNotOpenedByClientForNormalizedPath(normalizedPath, project.currentDirectory, scriptKind, hasMixedContent, project.directoryStructureHost); + scriptInfo = this.getOrCreateScriptInfoNotOpenedByClientForNormalizedPath(normalizedPath, project.currentDirectory, scriptKind, hasMixedContent, project.directoryStructureHost)!; // TODO: GH#18217 path = scriptInfo.path; // If this script info is not already a root add it if (!project.isRoot(scriptInfo)) { @@ -1586,7 +1586,7 @@ namespace ts.server { project.markAsDirty(); } - private updateNonInferredProject(project: ExternalProject | ConfiguredProject, newUncheckedFiles: T[], propertyReader: FilePropertyReader, newOptions: CompilerOptions, newTypeAcquisition: TypeAcquisition, compileOnSave: boolean) { + private updateNonInferredProject(project: ExternalProject | ConfiguredProject, newUncheckedFiles: T[], propertyReader: FilePropertyReader, newOptions: CompilerOptions, newTypeAcquisition: TypeAcquisition, compileOnSave: boolean | undefined) { project.setCompilerOptions(newOptions); // VS only set the CompileOnSaveEnabled option in the request if the option was changed recently // therefore if it is undefined, it should not be updated. @@ -1601,7 +1601,7 @@ namespace ts.server { */ /*@internal*/ reloadFileNamesOfConfiguredProject(project: ConfiguredProject): boolean { - const configFileSpecs = project.configFileSpecs; + const configFileSpecs = project.configFileSpecs!; // TODO: GH#18217 const configFileName = project.getConfigFilePath(); const fileNamesResult = getFileNamesFromConfigSpecs(configFileSpecs, getDirectoryPath(configFileName), project.getCompilationSettings(), project.getCachedDirectoryStructureHost(), this.hostConfiguration.extraFileExtensions); project.updateErrorOnNoInputFiles(fileNamesResult.fileNames.length !== 0); @@ -1629,16 +1629,16 @@ namespace ts.server { project.configFileSpecs = configFileSpecs; project.setProjectErrors(configFileErrors); project.updateReferences(projectOptions.projectReferences); - const lastFileExceededProgramSize = this.getFilenameForExceededTotalSizeLimitForNonTsFiles(project.canonicalConfigFilePath, projectOptions.compilerOptions, projectOptions.files, fileNamePropertyReader); + const lastFileExceededProgramSize = this.getFilenameForExceededTotalSizeLimitForNonTsFiles(project.canonicalConfigFilePath, projectOptions.compilerOptions, projectOptions.files!, fileNamePropertyReader); // TODO: GH#18217 if (lastFileExceededProgramSize) { project.disableLanguageService(lastFileExceededProgramSize); project.stopWatchingWildCards(); } else { project.enableLanguageService(); - project.watchWildcards(projectOptions.wildcardDirectories); + project.watchWildcards(projectOptions.wildcardDirectories!); // TODO: GH#18217 } - this.updateNonInferredProject(project, projectOptions.files, fileNamePropertyReader, projectOptions.compilerOptions, projectOptions.typeAcquisition, projectOptions.compileOnSave); + this.updateNonInferredProject(project, projectOptions.files!, fileNamePropertyReader, projectOptions.compilerOptions!, projectOptions.typeAcquisition!, projectOptions.compileOnSave!); // TODO: GH#18217 this.sendConfigFileDiagEvent(project, configFileName); } @@ -1671,7 +1671,7 @@ namespace ts.server { // we don't have an explicit root path, so we should try to find an inferred project // that more closely contains the file. - let bestMatch: InferredProject; + let bestMatch: InferredProject | undefined; for (const project of this.inferredProjects) { // ignore single inferred projects (handled elsewhere) if (!project.projectRootPath) continue; @@ -1679,7 +1679,7 @@ namespace ts.server { if (!containsPath(project.projectRootPath, info.path, this.host.getCurrentDirectory(), !this.host.useCaseSensitiveFileNames)) continue; // ignore inferred projects that are higher up in the project root. // TODO(rbuckton): Should we add the file as a root to these as well? - if (bestMatch && bestMatch.projectRootPath.length > project.projectRootPath.length) continue; + if (bestMatch && bestMatch.projectRootPath!.length > project.projectRootPath.length) continue; bestMatch = project; } @@ -1837,7 +1837,7 @@ namespace ts.server { if (!openedByClient && !isDynamic && !(hostToQueryFileExistsOn || this.host).fileExists(fileName)) { return; } - info = new ScriptInfo(this.host, fileName, scriptKind, hasMixedContent, path); + info = new ScriptInfo(this.host, fileName, scriptKind!, !!hasMixedContent, path); // TODO: GH#18217 this.filenameToScriptInfo.set(info.path, info); if (!openedByClient) { this.watchClosedScriptInfo(info); @@ -1851,7 +1851,7 @@ namespace ts.server { // Opening closed script info // either it was created just now, or was part of projects but was closed this.stopWatchingScriptInfo(info); - info.open(fileContent); + info.open(fileContent!); if (hasMixedContent) { info.registerFileUpdate(); } @@ -1878,7 +1878,7 @@ namespace ts.server { if (args.file) { const info = this.getScriptInfoForNormalizedPath(toNormalizedPath(args.file)); if (info) { - info.setOptions(convertFormatOptions(args.formatOptions), args.preferences); + info.setOptions(convertFormatOptions(args.formatOptions!), args.preferences); this.logger.info(`Host configuration update for file ${args.file}`); } } @@ -1952,7 +1952,7 @@ namespace ts.server { return; } - const info = this.getScriptInfoForPath(path as Path); + const info = this.getScriptInfoForPath(path as Path)!; // TODO: GH#18217 Debug.assert(info.isScriptOpen()); // This tries to search for a tsconfig.json for the given file. If we found it, // we first detect if there is already a configured project created for it: if so, @@ -2020,7 +2020,7 @@ namespace ts.server { this.printProjects(); this.openFiles.forEach((projectRootPath, path) => { - const info = this.getScriptInfoForPath(path as Path); + const info = this.getScriptInfoForPath(path as Path)!; // collect all orphaned script infos from open files if (info.isOrphan()) { this.assignOrphanScriptInfoToInferredProject(info, projectRootPath); @@ -2055,10 +2055,10 @@ namespace ts.server { } openClientFileWithNormalizedPath(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, projectRootPath?: NormalizedPath): OpenConfiguredProjectResult { - let configFileName: NormalizedPath; - let configFileErrors: ReadonlyArray; + let configFileName: NormalizedPath | undefined; + let configFileErrors: ReadonlyArray | undefined; - const info = this.getOrCreateScriptInfoOpenedByClientForNormalizedPath(fileName, projectRootPath ? this.getNormalizedAbsolutePath(projectRootPath) : this.currentDirectory, fileContent, scriptKind, hasMixedContent); + const info = this.getOrCreateScriptInfoOpenedByClientForNormalizedPath(fileName, projectRootPath ? this.getNormalizedAbsolutePath(projectRootPath) : this.currentDirectory, fileContent, scriptKind, hasMixedContent)!; // TODO: GH#18217 this.openFiles.set(info.path, projectRootPath); let project: ConfiguredProject | ExternalProject | undefined = this.findExternalProjectContainingOpenScriptInfo(info); if (!project && !this.syntaxOnly) { // Checking syntaxOnly is an optimization @@ -2100,7 +2100,6 @@ namespace ts.server { } Debug.assert(!info.isOrphan()); - // Remove the configured projects that have zero references from open files. // This was postponed from closeOpenFile to after opening next file, // so that we can reuse the project if we need to right away @@ -2141,7 +2140,7 @@ namespace ts.server { return; } - const info: OpenFileInfo = { checkJs: !!scriptInfo.getDefaultProject().getSourceFile(scriptInfo.path).checkJsDirective }; + const info: OpenFileInfo = { checkJs: !!scriptInfo.getDefaultProject().getSourceFile(scriptInfo.path)!.checkJsDirective }; this.eventHandler({ eventName: OpenFileInfoTelemetryEvent, data: { info } }); } @@ -2159,7 +2158,7 @@ namespace ts.server { private collectChanges(lastKnownProjectVersions: protocol.ProjectVersionInfo[], currentProjects: Project[], result: ProjectFilesWithTSDiagnostics[]): void { for (const proj of currentProjects) { - const knownProject = forEach(lastKnownProjectVersions, p => p.projectName === proj.getProjectName() && p); + const knownProject = find(lastKnownProjectVersions, p => p.projectName === proj.getProjectName()); result.push(proj.getChangesSinceVersion(knownProject && knownProject.version)); } } @@ -2174,19 +2173,19 @@ namespace ts.server { } /* @internal */ - applyChangesInOpenFiles(openFiles: protocol.ExternalFile[], changedFiles: protocol.ChangedOpenFile[], closedFiles: string[]): void { + applyChangesInOpenFiles(openFiles: protocol.ExternalFile[] | undefined, changedFiles: protocol.ChangedOpenFile[] | undefined, closedFiles: string[] | undefined): void { if (openFiles) { for (const file of openFiles) { const scriptInfo = this.getScriptInfo(file.fileName); Debug.assert(!scriptInfo || !scriptInfo.isScriptOpen(), "Script should not exist and not be open already"); const normalizedPath = scriptInfo ? scriptInfo.fileName : toNormalizedPath(file.fileName); - this.openClientFileWithNormalizedPath(normalizedPath, file.content, tryConvertScriptKindName(file.scriptKind), file.hasMixedContent); + this.openClientFileWithNormalizedPath(normalizedPath, file.content, tryConvertScriptKindName(file.scriptKind!), file.hasMixedContent); // TODO: GH#18217 } } if (changedFiles) { for (const file of changedFiles) { - const scriptInfo = this.getScriptInfo(file.fileName); + const scriptInfo = this.getScriptInfo(file.fileName)!; Debug.assert(!!scriptInfo); this.applyChangesToFile(scriptInfo, file.changes); } @@ -2267,7 +2266,8 @@ namespace ts.server { } applySafeList(proj: protocol.ExternalProject): NormalizedPath[] { - const { rootFiles, typeAcquisition } = proj; + const { rootFiles } = proj; + const typeAcquisition = proj.typeAcquisition!; Debug.assert(!!typeAcquisition, "proj.typeAcquisition should be set by now"); // If type acquisition has been explicitly disabled, do not exclude anything from the project if (typeAcquisition.enable === false) { @@ -2390,7 +2390,7 @@ namespace ts.server { const excludedFiles = this.applySafeList(proj); - let tsConfigFiles: NormalizedPath[]; + let tsConfigFiles: NormalizedPath[] | undefined; const rootFiles: protocol.ExternalFile[] = []; for (const file of proj.rootFiles) { const normalized = toNormalizedPath(file.fileName); @@ -2410,7 +2410,7 @@ namespace ts.server { } const externalProject = this.findExternalProjectByProjectName(proj.projectFileName); - let exisingConfigFiles: string[]; + let exisingConfigFiles: string[] | undefined; if (externalProject) { externalProject.excludedFiles = excludedFiles; if (!tsConfigFiles) { @@ -2438,7 +2438,7 @@ namespace ts.server { } else { // project previously had some config files - compare them with new set of files and close all configured projects that correspond to unused files - const oldConfigFiles = this.externalProjectToConfiguredProjectMap.get(proj.projectFileName); + const oldConfigFiles = this.externalProjectToConfiguredProjectMap.get(proj.projectFileName)!; let iNew = 0; let iOld = 0; while (iNew < tsConfigFiles.length && iOld < oldConfigFiles.length) { @@ -2487,7 +2487,7 @@ namespace ts.server { } hasDeferredExtension() { - for (const extension of this.hostConfiguration.extraFileExtensions) { + for (const extension of this.hostConfiguration.extraFileExtensions!) { // TODO: GH#18217 if (extension.scriptKind === ScriptKind.Deferred) { return true; } diff --git a/src/server/project.ts b/src/server/project.ts index 754d061235d7c..f6f68f663879b 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -103,7 +103,7 @@ namespace ts.server { cachedUnresolvedImportsPerFile = createMap>(); /*@internal*/ - lastCachedUnresolvedImportsList: SortedReadonlyArray; + lastCachedUnresolvedImportsList: SortedReadonlyArray | undefined; /*@internal*/ private hasAddedorRemovedFiles = false; @@ -127,7 +127,7 @@ namespace ts.server { /** * Set of files names that were updated since the last call to getChangesSinceVersion. */ - private updatedFileNames: Map; + private updatedFileNames: Map | undefined; /** * Set of files that was returned from the last call to getChangesSinceVersion. */ @@ -173,7 +173,7 @@ namespace ts.server { public static resolveModule(moduleName: string, initialDir: string, host: ServerHost, log: (message: string) => void): {} | undefined { const resolvedPath = normalizeSlashes(host.resolvePath(combinePaths(initialDir, "node_modules"))); log(`Loading ${moduleName} from ${initialDir} (resolved to ${resolvedPath})`); - const result = host.require(resolvedPath, moduleName); + const result = host.require!(resolvedPath, moduleName); // TODO: GH#18217 if (result.error) { const err = result.error.stack || result.error.message || JSON.stringify(result.error); log(`Failed to load module '${moduleName}': ${err}`); @@ -226,11 +226,11 @@ namespace ts.server { this.trace = s => this.writeLog(s); } else if (host.trace) { - this.trace = s => host.trace(s); + this.trace = s => host.trace!(s); } if (host.realpath) { - this.realpath = path => host.realpath(path); + this.realpath = path => host.realpath!(path); } // Use the current directory as resolution root only if the project created using current directory string @@ -307,15 +307,15 @@ namespace ts.server { getScriptKind(fileName: string) { const info = this.getOrCreateScriptInfoAndAttachToProject(fileName); - return info && info.scriptKind; + return (info && info.scriptKind)!; // TODO: GH#18217 } getScriptVersion(filename: string) { const info = this.getOrCreateScriptInfoAndAttachToProject(filename); - return info && info.getLatestVersion(); + return (info && info.getLatestVersion())!; // TODO: GH#18217 } - getScriptSnapshot(filename: string): IScriptSnapshot { + getScriptSnapshot(filename: string): IScriptSnapshot | undefined { const scriptInfo = this.getOrCreateScriptInfoAndAttachToProject(filename); if (scriptInfo) { return scriptInfo.getSnapshot(); @@ -340,7 +340,7 @@ namespace ts.server { } readDirectory(path: string, extensions?: ReadonlyArray, exclude?: ReadonlyArray, include?: ReadonlyArray, depth?: number): string[] { - return this.directoryStructureHost.readDirectory(path, extensions, exclude, include, depth); + return this.directoryStructureHost.readDirectory!(path, extensions, exclude, include, depth); } readFile(fileName: string): string | undefined { @@ -358,7 +358,7 @@ namespace ts.server { return this.resolutionCache.resolveModuleNames(moduleNames, containingFile, reusedNames); } - getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string): ResolvedModuleWithFailedLookupLocations { + getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string): ResolvedModuleWithFailedLookupLocations | undefined { return this.resolutionCache.getResolvedModuleWithFailedLookupLocationsFromCache(moduleName, containingFile); } @@ -367,16 +367,16 @@ namespace ts.server { } directoryExists(path: string): boolean { - return this.directoryStructureHost.directoryExists(path); + return this.directoryStructureHost.directoryExists!(path); // TODO: GH#18217 } getDirectories(path: string): string[] { - return this.directoryStructureHost.getDirectories(path); + return this.directoryStructureHost.getDirectories!(path); // TODO: GH#18217 } /*@internal*/ getCachedDirectoryStructureHost(): CachedDirectoryStructureHost { - return undefined; + return undefined!; // TODO: GH#18217 } /*@internal*/ @@ -471,8 +471,8 @@ namespace ts.server { } this.updateGraph(); this.builderState = BuilderState.create(this.program, this.projectService.toCanonicalFileName, this.builderState); - return mapDefined(BuilderState.getFilesAffectedBy(this.builderState, this.program, scriptInfo.path, this.cancellationToken, data => this.projectService.host.createHash(data)), - sourceFile => this.shouldEmitFile(this.projectService.getScriptInfoForPath(sourceFile.path)) ? sourceFile.fileName : undefined); + return mapDefined(BuilderState.getFilesAffectedBy(this.builderState, this.program, scriptInfo.path, this.cancellationToken, data => this.projectService.host.createHash!(data)), // TODO: GH#18217 + sourceFile => this.shouldEmitFile(this.projectService.getScriptInfoForPath(sourceFile.path)!) ? sourceFile.fileName : undefined); } /** @@ -567,25 +567,25 @@ namespace ts.server { } this.projectService.pendingEnsureProjectForOpenFiles = true; - this.rootFiles = undefined; - this.rootFilesMap = undefined; - this.externalFiles = undefined; - this.program = undefined; - this.builderState = undefined; + this.rootFiles = undefined!; + this.rootFilesMap = undefined!; + this.externalFiles = undefined!; + this.program = undefined!; + this.builderState = undefined!; this.resolutionCache.clear(); - this.resolutionCache = undefined; - this.cachedUnresolvedImportsPerFile = undefined; - this.directoryStructureHost = undefined; + this.resolutionCache = undefined!; + this.cachedUnresolvedImportsPerFile = undefined!; + this.directoryStructureHost = undefined!; // Clean up file watchers waiting for missing files if (this.missingFilesMap) { clearMap(this.missingFilesMap, closeFileWatcher); - this.missingFilesMap = undefined; + this.missingFilesMap = undefined!; } // signal language service to release source files acquired from document registry this.languageService.dispose(); - this.languageService = undefined; + this.languageService = undefined!; } private detachScriptInfoIfNotRoot(uncheckedFilename: string) { @@ -623,17 +623,15 @@ namespace ts.server { return this.rootFiles; } - getScriptInfos() { + getScriptInfos(): ScriptInfo[] { if (!this.languageServiceEnabled) { // if language service is not enabled - return just root files return this.rootFiles; } return map(this.program.getSourceFiles(), sourceFile => { const scriptInfo = this.projectService.getScriptInfoForPath(sourceFile.path); - if (!scriptInfo) { - Debug.fail(`scriptInfo for a file '${sourceFile.fileName}' Path: '${sourceFile.path}' is missing.`); - } - return scriptInfo; + Debug.assert(!!scriptInfo, "getScriptInfo", () => `scriptInfo for a file '${sourceFile.fileName}' Path: '${sourceFile.path}' is missing.`); + return scriptInfo!; }); } @@ -701,11 +699,12 @@ namespace ts.server { return this.isRoot(info) || (this.program && this.program.getSourceFileByPath(info.path) !== undefined); } - containsFile(filename: NormalizedPath, requireOpen?: boolean) { + containsFile(filename: NormalizedPath, requireOpen?: boolean): boolean { const info = this.projectService.getScriptInfoForPath(this.toPath(filename)); if (info && (info.isScriptOpen() || !requireOpen)) { return this.containsScriptInfo(info); } + return false; } isRoot(info: ScriptInfo) { @@ -879,7 +878,7 @@ namespace ts.server { const start = timestamp(); this.hasInvalidatedResolution = this.resolutionCache.createHasInvalidatedResolution(); this.resolutionCache.startCachingPerDirectoryResolution(); - this.program = this.languageService.getProgram(); + this.program = this.languageService.getProgram()!; // TODO: GH#18217 this.dirty = false; this.resolutionCache.finishCachingPerDirectoryResolution(); @@ -888,7 +887,7 @@ namespace ts.server { // bump up the version if // - oldProgram is not set - this is a first time updateGraph is called // - newProgram is different from the old program and structure of the old program was not reused. - const hasNewProgram = this.program && (!oldProgram || (this.program !== oldProgram && !(oldProgram.structureIsReused & StructureIsReused.Completely))); + const hasNewProgram = this.program && (!oldProgram || (this.program !== oldProgram && !(oldProgram.structureIsReused! & StructureIsReused.Completely))); this.hasChangedAutomaticTypeDirectiveNames = false; if (hasNewProgram) { if (oldProgram) { @@ -922,7 +921,7 @@ namespace ts.server { // by the LSHost for files in the program when the program is retrieved above but // the program doesn't contain external files so this must be done explicitly. inserted => { - const scriptInfo = this.projectService.getOrCreateScriptInfoNotOpenedByClient(inserted, this.currentDirectory, this.directoryStructureHost); + const scriptInfo = this.projectService.getOrCreateScriptInfoNotOpenedByClient(inserted, this.currentDirectory, this.directoryStructureHost)!; scriptInfo.attachToProject(this); }, removed => this.detachScriptInfoFromProject(removed) @@ -1212,7 +1211,8 @@ namespace ts.server { ProjectKind.Inferred, projectService, documentRegistry, - /*files*/ undefined, + // TODO: GH#18217 + /*files*/ undefined!, /*lastFileExceededProgramSize*/ undefined, compilerOptions, /*compileOnSaveEnabled*/ false, @@ -1279,7 +1279,7 @@ namespace ts.server { export class ConfiguredProject extends Project { private typeAcquisition: TypeAcquisition; /* @internal */ - configFileWatcher: FileWatcher; + configFileWatcher: FileWatcher | undefined; private directoriesWatchedForWildcards: Map | undefined; readonly canonicalConfigFilePath: NormalizedPath; @@ -1287,12 +1287,12 @@ namespace ts.server { pendingReload: ConfigFileProgramReloadLevel; /*@internal*/ - configFileSpecs: ConfigFileSpecs; + configFileSpecs: ConfigFileSpecs | undefined; /** Ref count to the project when opened from external project */ private externalProjectRefCount = 0; - private projectErrors: Diagnostic[]; + private projectErrors: Diagnostic[] | undefined; /*@internal*/ constructor(configFileName: NormalizedPath, @@ -1473,7 +1473,7 @@ namespace ts.server { // The project is referenced only if open files impacted by this project are present in this project return forEachEntry( configFileExistenceInfo.openFilesImpactedByConfigFile, - (_value, infoPath) => this.containsScriptInfo(this.projectService.getScriptInfoForPath(infoPath as Path)) + (_value, infoPath) => this.containsScriptInfo(this.projectService.getScriptInfoForPath(infoPath as Path)!) ) || false; } @@ -1484,10 +1484,10 @@ namespace ts.server { /*@internal*/ updateErrorOnNoInputFiles(hasFileNames: boolean) { if (hasFileNames) { - filterMutate(this.projectErrors, error => !isErrorNoInputFiles(error)); + filterMutate(this.projectErrors!, error => !isErrorNoInputFiles(error)); // TODO: GH#18217 } - else if (!this.configFileSpecs.filesSpecs && !some(this.projectErrors, isErrorNoInputFiles)) { - this.projectErrors.push(getErrorForNoInputFiles(this.configFileSpecs, this.getConfigFilePath())); + else if (!this.configFileSpecs!.filesSpecs && !some(this.projectErrors, isErrorNoInputFiles)) { // TODO: GH#18217 + this.projectErrors!.push(getErrorForNoInputFiles(this.configFileSpecs!, this.getConfigFilePath())); } } } diff --git a/src/server/protocol.ts b/src/server/protocol.ts index 20854c7597b2e..9c34130bdef86 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -1201,7 +1201,7 @@ namespace ts.server.protocol { /** * Filename of the last file analyzed before disabling the language service. undefined, if the language service is enabled. */ - lastFileExceededProgramSize: string | undefined; + lastFileExceededProgramSize?: string; } /** @@ -1809,7 +1809,7 @@ namespace ts.server.protocol { export interface CompletionEntryIdentifier { name: string; - source: string; + source?: string; } /** @@ -1853,7 +1853,7 @@ namespace ts.server.protocol { /** * Optional modifiers for the kind (such as 'public'). */ - kindModifiers: string; + kindModifiers?: string; /** * A string that is used for comparing completion items so that they can be ordered. This * is often the same as the name but may be different in certain circumstances. @@ -1912,12 +1912,12 @@ namespace ts.server.protocol { /** * Documentation strings for the symbol. */ - documentation: SymbolDisplayPart[]; + documentation?: SymbolDisplayPart[]; /** * JSDoc tags for the symbol. */ - tags: JSDocTagInfo[]; + tags?: JSDocTagInfo[]; /** * The associated code actions for this entry diff --git a/src/server/scriptInfo.ts b/src/server/scriptInfo.ts index c47f3daecb9a5..e8f1d931ac2af 100644 --- a/src/server/scriptInfo.ts +++ b/src/server/scriptInfo.ts @@ -14,11 +14,11 @@ namespace ts.server { * The script version cache is generated on demand and text is still retained. * Only on edits to the script version cache, the text will be set to undefined */ - private text: string; + private text: string | undefined; /** * Line map for the text when there is no script version cache present */ - private lineMap: number[]; + private lineMap: number[] | undefined; private textVersion = 0; /** @@ -115,7 +115,7 @@ namespace ts.server { public getSnapshot(): IScriptSnapshot { return this.useScriptVersionCacheIfValidOrOpen() - ? this.svc.getSnapshot() + ? this.svc!.getSnapshot() : ScriptSnapshot.fromString(this.getOrLoadText()); } @@ -129,10 +129,10 @@ namespace ts.server { if (!this.useScriptVersionCacheIfValidOrOpen()) { const lineMap = this.getLineMap(); const start = lineMap[line]; // -1 since line is 1-based - const end = line + 1 < lineMap.length ? lineMap[line + 1] : this.text.length; + const end = line + 1 < lineMap.length ? lineMap[line + 1] : this.text!.length; return createTextSpanFromBounds(start, end); } - return this.svc.lineToTextSpan(line); + return this.svc!.lineToTextSpan(line); } /** @@ -145,7 +145,7 @@ namespace ts.server { } // TODO: assert this offset is actually on the line - return this.svc.lineOffsetToPosition(line, offset); + return this.svc!.lineOffsetToPosition(line, offset); } positionToLineOffset(position: number): protocol.Location { @@ -153,7 +153,7 @@ namespace ts.server { const { line, character } = computeLineAndCharacterOfPosition(this.getLineMap(), position); return { line: line + 1, offset: character + 1 }; } - return this.svc.positionToLineOffset(position); + return this.svc!.positionToLineOffset(position); } private getFileText(tempFileName?: string) { @@ -188,7 +188,7 @@ namespace ts.server { Debug.assert(!this.svc || this.pendingReloadFromDisk, "ScriptVersionCache should not be set when reloading from disk"); this.reloadWithFileText(); } - return this.text; + return this.text!; } private getLineMap() { @@ -217,7 +217,7 @@ namespace ts.server { private preferences: UserPreferences | undefined; /* @internal */ - fileWatcher: FileWatcher; + fileWatcher: FileWatcher | undefined; private textStorage: TextStorage; /*@internal*/ @@ -294,7 +294,7 @@ namespace ts.server { this.realpath = project.toPath(realpath); // If it is different from this.path, add to the map if (this.realpath !== this.path) { - project.projectService.realpathToScriptInfos.add(this.realpath, this); + project.projectService.realpathToScriptInfos!.add(this.realpath, this); // TODO: GH#18217 } } } @@ -306,8 +306,8 @@ namespace ts.server { return this.realpath && this.realpath !== this.path ? this.realpath : undefined; } - getFormatCodeSettings(): FormatCodeSettings { return this.formatSettings; } - getPreferences(): UserPreferences { return this.preferences; } + getFormatCodeSettings(): FormatCodeSettings | undefined { return this.formatSettings; } + getPreferences(): UserPreferences | undefined { return this.preferences; } attachToProject(project: Project): boolean { const isNew = !this.isAttached(project); @@ -345,7 +345,7 @@ namespace ts.server { case 2: if (this.containingProjects[0] === project) { project.onFileAddedOrRemoved(); - this.containingProjects[0] = this.containingProjects.pop(); + this.containingProjects[0] = this.containingProjects.pop()!; } else if (this.containingProjects[1] === project) { project.onFileAddedOrRemoved(); @@ -406,7 +406,7 @@ namespace ts.server { } } - setOptions(formatSettings: FormatCodeSettings, preferences: UserPreferences): void { + setOptions(formatSettings: FormatCodeSettings, preferences: UserPreferences | undefined): void { if (formatSettings) { if (!this.formatSettings) { this.formatSettings = getDefaultFormatCodeSettings(this.host); diff --git a/src/server/scriptVersionCache.ts b/src/server/scriptVersionCache.ts index d57f296e7a7bc..d7ac25062d021 100644 --- a/src/server/scriptVersionCache.ts +++ b/src/server/scriptVersionCache.ts @@ -55,7 +55,7 @@ namespace ts.server { this.stack = [this.lineIndex.root]; } - insertLines(insertedText: string, suppressTrailingText: boolean) { + insertLines(insertedText: string | undefined, suppressTrailingText: boolean) { if (suppressTrailingText) { this.trailingText = ""; } @@ -72,8 +72,8 @@ namespace ts.server { lines.pop(); } } - let branchParent: LineNode; - let lastZeroCount: LineCollection; + let branchParent: LineNode | undefined; + let lastZeroCount: LineCollection | undefined; for (let k = this.endBranch.length - 1; k >= 0; k--) { (this.endBranch[k]).updateCounts(); @@ -88,7 +88,7 @@ namespace ts.server { } } if (lastZeroCount) { - branchParent.remove(lastZeroCount); + branchParent!.remove(lastZeroCount); } // path at least length two (root and leaf) @@ -159,7 +159,7 @@ namespace ts.server { this.lineCollectionAtBranch = lineCollection; } - let child: LineCollection; + let child: LineCollection | undefined; function fresh(node: LineCollection): LineCollection { if (node.isLeaf()) { return new LineLeaf(""); @@ -332,7 +332,7 @@ namespace ts.server { if (oldVersion >= this.minVersion) { const textChangeRanges: TextChangeRange[] = []; for (let i = oldVersion + 1; i <= newVersion; i++) { - const snap = this.versions[this.versionToIndex(i)]; + const snap = this.versions[this.versionToIndex(i)!]; // TODO: GH#18217 for (const textChange of snap.changesSincePreviousVersion) { textChangeRanges.push(textChange.getTextChangeRange()); } @@ -370,7 +370,7 @@ namespace ts.server { return this.index.getLength(); } - getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange { + getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange | undefined { if (oldSnapshot instanceof LineIndexSnapshot && this.cache === oldSnapshot.cache) { if (this.version <= oldSnapshot.version) { return unchangedTextChangeRange; @@ -397,7 +397,7 @@ namespace ts.server { return { line: oneBasedLine, offset: zeroBasedColumn + 1 }; } - private positionToColumnAndLineText(position: number): { zeroBasedColumn: number, lineText: string } { + private positionToColumnAndLineText(position: number): { zeroBasedColumn: number, lineText: string | undefined } { return this.root.charOffsetToLineInfo(1, position); } @@ -471,9 +471,10 @@ namespace ts.server { this.load(LineIndex.linesFromText(newText).lines); return this; } + return undefined!; // TODO: GH#18217 } else { - let checkText: string; + let checkText: string | undefined; if (this.checkEdits) { const source = this.getText(0, this.root.charCount()); checkText = source.slice(0, pos) + newText + source.slice(pos + deleteLength); @@ -499,7 +500,7 @@ namespace ts.server { const { zeroBasedColumn, lineText } = this.positionToColumnAndLineText(e); if (zeroBasedColumn === 0) { // move range end just past line that will merge with previous line - deleteLength += lineText.length; + deleteLength += lineText!.length; // TODO: GH#18217 // store text by appending to end of insertedText newText = newText ? newText + lineText : lineText; } @@ -700,7 +701,7 @@ namespace ts.server { } private splitAfter(childIndex: number) { - let splitNode: LineNode; + let splitNode: LineNode | undefined; const clen = this.children.length; childIndex++; const endLength = childIndex; diff --git a/src/server/server.ts b/src/server/server.ts index 706a47a0aa5c5..cbb91ae70a843 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -1,3 +1,5 @@ +// tslint:disable no-unnecessary-type-assertion (TODO: tslint can't find node types) + namespace ts.server { const childProcess: { fork(modulePath: string, args: string[], options?: { execArgv: string[], env?: MapLike }): NodeChildProcess; @@ -38,8 +40,7 @@ namespace ts.server { return combinePaths(combinePaths(cacheLocation, "typescript"), versionMajorMinor); } default: - Debug.fail(`unsupported platform '${process.platform}'`); - return; + return Debug.fail(`unsupported platform '${process.platform}'`); } } @@ -200,7 +201,7 @@ namespace ts.server { if (this.fd >= 0) { const buf = new Buffer(s); // tslint:disable-next-line no-null-keyword - fs.writeSync(this.fd, buf, 0, buf.length, /*position*/ null); + fs.writeSync(this.fd, buf, 0, buf.length, /*position*/ null!); // TODO: GH#18217 } if (this.traceToConsole) { console.warn(s); @@ -230,7 +231,7 @@ namespace ts.server { // buffer, but we have yet to find a way to retrieve that value. private static readonly maxActiveRequestCount = 10; private static readonly requestDelayMillis = 100; - private packageInstalledPromise: { resolve(value: ApplyCodeActionCommandResult): void, reject(reason: any): void }; + private packageInstalledPromise: { resolve(value: ApplyCodeActionCommandResult): void, reject(reason: any): void } | undefined; constructor( private readonly telemetryEnabled: boolean, @@ -364,10 +365,10 @@ namespace ts.server { case ActionPackageInstalled: { const { success, message } = response; if (success) { - this.packageInstalledPromise.resolve({ successMessage: message }); + this.packageInstalledPromise!.resolve({ successMessage: message }); } else { - this.packageInstalledPromise.reject(message); + this.packageInstalledPromise!.reject(message); } this.packageInstalledPromise = undefined; @@ -435,7 +436,7 @@ namespace ts.server { } while (this.requestQueue.length > 0) { - const queuedRequest = this.requestQueue.shift(); + const queuedRequest = this.requestQueue.shift()!; if (this.requestMap.get(queuedRequest.operationId) === queuedRequest) { this.requestMap.delete(queuedRequest.operationId); this.scheduleRequest(queuedRequest); @@ -468,7 +469,7 @@ namespace ts.server { } class IOSession extends Session { - private eventPort: number; + private eventPort: number | undefined; private eventSocket: NodeSocket | undefined; private socketEventQueue: { body: any, eventName: string }[] | undefined; private constructed: boolean | undefined; @@ -529,7 +530,7 @@ namespace ts.server { } event(body: T, eventName: string): void { - Debug.assert(this.constructed, "Should only call `IOSession.prototype.event` on an initialized IOSession"); + Debug.assert(!!this.constructed, "Should only call `IOSession.prototype.event` on an initialized IOSession"); if (this.canUseEvents && this.eventPort) { if (!this.eventSocket) { @@ -550,7 +551,7 @@ namespace ts.server { } private writeToEventSocket(body: object, eventName: string): void { - this.eventSocket.write(formatMessage(toEvent(eventName, body), this.logger, this.byteLength, this.host.newLine), "utf8"); + this.eventSocket!.write(formatMessage(toEvent(eventName, body), this.logger, this.byteLength, this.host.newLine), "utf8"); } exit() { @@ -578,7 +579,7 @@ namespace ts.server { logToFile?: boolean; } - function parseLoggingEnvironmentString(logEnvStr: string): LogOptions { + function parseLoggingEnvironmentString(logEnvStr: string | undefined): LogOptions { if (!logEnvStr) { return {}; } @@ -625,7 +626,7 @@ namespace ts.server { } } - function getLogLevel(level: string) { + function getLogLevel(level: string | undefined) { if (level) { const l = level.toLowerCase(); for (const name in LogLevel) { @@ -650,7 +651,7 @@ namespace ts.server { : undefined; const logVerbosity = cmdLineVerbosity || envLogOptions.detailLevel; - return new Logger(logFileName, envLogOptions.traceToConsole, logVerbosity); + return new Logger(logFileName!, envLogOptions.traceToConsole!, logVerbosity!); // TODO: GH#18217 } // This places log file in the directory containing editorServices.js // TODO: check that this location is writable @@ -765,11 +766,11 @@ namespace ts.server { function setCanWriteFlagAndWriteMessageIfNecessary() { canWrite = true; if (pending.length) { - writeMessage(pending.shift()); + writeMessage(pending.shift()!); } } - function extractWatchDirectoryCacheKey(path: string, currentDriveKey: string) { + function extractWatchDirectoryCacheKey(path: string, currentDriveKey: string | undefined) { path = normalizeSlashes(path); if (isUNCPath(path)) { // UNC path: extract server name @@ -804,7 +805,7 @@ namespace ts.server { const sys = ts.sys; const nodeVersion = getNodeMajorVersion(); // use watchGuard process on Windows when node version is 4 or later - const useWatchGuard = process.platform === "win32" && nodeVersion >= 4; + const useWatchGuard = process.platform === "win32" && nodeVersion! >= 4; const originalWatchDirectory: ServerHost["watchDirectory"] = sys.watchDirectory.bind(sys); const noopWatcher: FileWatcher = { close: noop }; // This is the function that catches the exceptions when watching directory, and yet lets project service continue to function @@ -905,8 +906,8 @@ namespace ts.server { let eventPort: number | undefined; { const str = findArgument("--eventPort"); - const v = str && parseInt(str); - if (!isNaN(v)) { + const v = str === undefined ? undefined : parseInt(str); + if (v !== undefined && !isNaN(v)) { eventPort = v; } } @@ -918,7 +919,7 @@ namespace ts.server { setStackTraceLimit(); - const typingSafeListLocation = findArgument(Arguments.TypingSafeListLocation); + const typingSafeListLocation = findArgument(Arguments.TypingSafeListLocation)!; // TODO: GH#18217 const typesMapLocation = findArgument(Arguments.TypesMapLocation) || combinePaths(sys.getExecutingFilePath(), "../typesMap.json"); const npmLocation = findArgument(Arguments.NpmLocation); diff --git a/src/server/session.ts b/src/server/session.ts index ccedad18aac89..43e36dee8b50f 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -68,10 +68,10 @@ namespace ts.server { } function formatDiag(fileName: NormalizedPath, project: Project, diag: Diagnostic): protocol.Diagnostic { - const scriptInfo = project.getScriptInfoForNormalizedPath(fileName); + const scriptInfo = project.getScriptInfoForNormalizedPath(fileName)!; // TODO: GH#18217 return { - start: scriptInfo.positionToLineOffset(diag.start), - end: scriptInfo.positionToLineOffset(diag.start + diag.length), + start: scriptInfo.positionToLineOffset(diag.start!), + end: scriptInfo.positionToLineOffset(diag.start! + diag.length!), // TODO: GH#18217 text: flattenDiagnosticMessageText(diag.messageText, "\n"), code: diag.code, category: diagnosticCategoryName(diag), @@ -87,8 +87,8 @@ namespace ts.server { function formatConfigFileDiag(diag: Diagnostic, includeFileName: true): protocol.DiagnosticWithFileName; function formatConfigFileDiag(diag: Diagnostic, includeFileName: false): protocol.Diagnostic; function formatConfigFileDiag(diag: Diagnostic, includeFileName: boolean): protocol.Diagnostic | protocol.DiagnosticWithFileName { - const start = diag.file && convertToLocation(getLineAndCharacterOfPosition(diag.file, diag.start)); - const end = diag.file && convertToLocation(getLineAndCharacterOfPosition(diag.file, diag.start + diag.length)); + const start = (diag.file && convertToLocation(getLineAndCharacterOfPosition(diag.file, diag.start!)))!; // TODO: GH#18217 + const end = (diag.file && convertToLocation(getLineAndCharacterOfPosition(diag.file, diag.start! + diag.length!)))!; // TODO: GH#18217 const text = flattenDiagnosticMessageText(diag.messageText, "\n"); const { code, source } = diag; const category = diagnosticCategoryName(diag); @@ -177,7 +177,7 @@ namespace ts.server { } public immediate(action: () => void) { - const requestId = this.requestId; + const requestId = this.requestId!; Debug.assert(requestId === this.operationHost.getCurrentRequestId(), "immediate: incorrect request id"); this.setImmediateId(this.operationHost.getServerHost().setImmediate(() => { this.immediateId = undefined; @@ -186,7 +186,7 @@ namespace ts.server { } public delay(ms: number, action: () => void) { - const requestId = this.requestId; + const requestId = this.requestId!; Debug.assert(requestId === this.operationHost.getCurrentRequestId(), "delay: incorrect request id"); this.setTimerHandle(this.operationHost.getServerHost().setTimeout(() => { this.timerHandle = undefined; @@ -223,7 +223,7 @@ namespace ts.server { this.timerHandle = timerHandle; } - private setImmediateId(immediateId: number) { + private setImmediateId(immediateId: number | undefined) { if (this.immediateId !== undefined) { this.operationHost.getServerHost().clearImmediate(this.immediateId); } @@ -319,7 +319,7 @@ namespace ts.server { protected canUseEvents: boolean; private suppressDiagnosticEvents?: boolean; - private eventHandler: ProjectServiceEventHandler; + private eventHandler: ProjectServiceEventHandler | undefined; private readonly noGetErrOnBackgroundUpdate?: boolean; constructor(opts: SessionOptions) { @@ -426,7 +426,7 @@ namespace ts.server { if (err.message) { msg += ":\n" + indent(err.message); if ((err).stack) { - msg += "\n" + indent((err).stack); + msg += "\n" + indent((err).stack!); } } this.logger.msg(msg, Msg.Err); @@ -449,7 +449,7 @@ namespace ts.server { // For backwards-compatibility only. /** @deprecated */ public output(info: any, cmdName: string, reqSeq?: number, errorMsg?: string): void { - this.doOutput(info, cmdName, reqSeq, /*success*/ !errorMsg, errorMsg); + this.doOutput(info, cmdName, reqSeq!, /*success*/ !errorMsg, errorMsg); // TODO: GH#18217 } private doOutput(info: {} | undefined, cmdName: string, reqSeq: number, success: boolean, message?: string): void { @@ -573,16 +573,16 @@ namespace ts.server { return project.getLanguageService().getEncodedSemanticClassifications(file, args); } - private getProject(projectFileName: string) { - return projectFileName && this.projectService.findProject(projectFileName); + private getProject(projectFileName: string | undefined): Project | undefined { + return projectFileName === undefined ? undefined : this.projectService.findProject(projectFileName); } - private getConfigFileAndProject(args: protocol.FileRequestArgs) { + private getConfigFileAndProject(args: protocol.FileRequestArgs): { configFile: NormalizedPath | undefined, project: Project | undefined } { const project = this.getProject(args.projectFileName); const file = toNormalizedPath(args.file); return { - configFile: project && project.hasConfigFile(file) && file, + configFile: project && project.hasConfigFile(file) ? file : undefined, project }; } @@ -592,7 +592,7 @@ namespace ts.server { const optionsErrors = project.getLanguageService().getCompilerOptionsDiagnostics(); const diagnosticsForConfigFile = filter( concatenate(projectErrors, optionsErrors), - diagnostic => diagnostic.file && diagnostic.file.fileName === configFile + diagnostic => !!diagnostic.file && diagnostic.file.fileName === configFile ); return includeLinePosition ? this.convertToDiagnosticsWithLinePositionFromDiagnosticFile(diagnosticsForConfigFile) : @@ -605,17 +605,17 @@ namespace ts.server { private convertToDiagnosticsWithLinePositionFromDiagnosticFile(diagnostics: ReadonlyArray): protocol.DiagnosticWithLinePosition[] { return diagnostics.map(d => ({ message: flattenDiagnosticMessageText(d.messageText, this.host.newLine), - start: d.start, - length: d.length, + start: d.start!, // TODO: GH#18217 + length: d.length!, // TODO: GH#18217 category: diagnosticCategoryName(d), code: d.code, - startLocation: d.file && convertToLocation(getLineAndCharacterOfPosition(d.file, d.start)), - endLocation: d.file && convertToLocation(getLineAndCharacterOfPosition(d.file, d.start + d.length)) + startLocation: (d.file && convertToLocation(getLineAndCharacterOfPosition(d.file, d.start!)))!, // TODO: GH#18217 + endLocation: (d.file && convertToLocation(getLineAndCharacterOfPosition(d.file, d.start! + d.length!)))! // TODO: GH#18217 })); } private getCompilerOptionsDiagnostics(args: protocol.CompilerOptionsDiagnosticsRequestArgs) { - const project = this.getProject(args.projectFileName); + const project = this.getProject(args.projectFileName)!; // Get diagnostics that dont have associated file with them // The diagnostics which have file would be in config file and // would be reported as part of configFileDiagnostics @@ -628,7 +628,7 @@ namespace ts.server { ); } - private convertToDiagnosticsWithLinePosition(diagnostics: ReadonlyArray, scriptInfo: ScriptInfo): protocol.DiagnosticWithLinePosition[] { + private convertToDiagnosticsWithLinePosition(diagnostics: ReadonlyArray, scriptInfo: ScriptInfo | undefined): protocol.DiagnosticWithLinePosition[] { return diagnostics.map(d => { message: flattenDiagnosticMessageText(d.messageText, this.host.newLine), start: d.start, @@ -636,8 +636,8 @@ namespace ts.server { category: diagnosticCategoryName(d), code: d.code, source: d.source, - startLocation: scriptInfo && scriptInfo.positionToLineOffset(d.start), - endLocation: scriptInfo && scriptInfo.positionToLineOffset(d.start + d.length), + startLocation: scriptInfo && scriptInfo.positionToLineOffset(d.start!), // TODO: GH#18217 + endLocation: scriptInfo && scriptInfo.positionToLineOffset(d.start! + d.length!), reportsUnnecessary: d.reportsUnnecessary }); } @@ -675,14 +675,14 @@ namespace ts.server { private getDefinitionAndBoundSpan(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): protocol.DefinitionInfoAndBoundSpan | DefinitionInfoAndBoundSpan { const { file, project } = this.getFileAndProject(args); const position = this.getPositionInFile(args, file); - const scriptInfo = project.getScriptInfo(file); + const scriptInfo = project.getScriptInfo(file)!; const definitionAndBoundSpan = project.getLanguageService().getDefinitionAndBoundSpan(file, position); if (!definitionAndBoundSpan || !definitionAndBoundSpan.definitions) { return { definitions: emptyArray, - textSpan: undefined + textSpan: undefined! // TODO: GH#18217 }; } @@ -726,8 +726,8 @@ namespace ts.server { private toFileSpan(fileName: string, textSpan: TextSpan, project: Project): protocol.FileSpan { const ls = project.getLanguageService(); - const start = ls.toLineColumnOffset(fileName, textSpan.start); - const end = ls.toLineColumnOffset(fileName, textSpanEnd(textSpan)); + const start = ls.toLineColumnOffset!(fileName, textSpan.start); // TODO: GH#18217 + const end = ls.toLineColumnOffset!(fileName, textSpanEnd(textSpan)); return { file: fileName, @@ -775,7 +775,7 @@ namespace ts.server { return occurrences.map(occurrence => { const { fileName, isWriteAccess, textSpan, isInString } = occurrence; - const scriptInfo = project.getScriptInfo(fileName); + const scriptInfo = project.getScriptInfo(fileName)!; const result: protocol.OccurrencesResponseItem = { start: scriptInfo.positionToLineOffset(textSpan.start), end: scriptInfo.positionToLineOffset(textSpanEnd(textSpan)), @@ -797,15 +797,15 @@ namespace ts.server { return emptyArray; } - return this.getDiagnosticsWorker(args, /*isSemantic*/ false, (project, file) => project.getLanguageService().getSyntacticDiagnostics(file), args.includeLinePosition); + return this.getDiagnosticsWorker(args, /*isSemantic*/ false, (project, file) => project.getLanguageService().getSyntacticDiagnostics(file), !!args.includeLinePosition); } private getSemanticDiagnosticsSync(args: protocol.SemanticDiagnosticsSyncRequestArgs): ReadonlyArray | ReadonlyArray { const { configFile, project } = this.getConfigFileAndProject(args); if (configFile) { - return this.getConfigFileDiagnostics(configFile, project, args.includeLinePosition); + return this.getConfigFileDiagnostics(configFile, project!, !!args.includeLinePosition); // TODO: GH#18217 } - return this.getDiagnosticsWorker(args, /*isSemantic*/ true, (project, file) => project.getLanguageService().getSemanticDiagnostics(file), args.includeLinePosition); + return this.getDiagnosticsWorker(args, /*isSemantic*/ true, (project, file) => project.getLanguageService().getSemanticDiagnostics(file), !!args.includeLinePosition); } private getSuggestionDiagnosticsSync(args: protocol.SuggestionDiagnosticsSyncRequestArgs): ReadonlyArray | ReadonlyArray { @@ -815,7 +815,7 @@ namespace ts.server { return emptyArray; } // isSemantic because we don't want to info diagnostics in declaration files for JS-only users - return this.getDiagnosticsWorker(args, /*isSemantic*/ true, (project, file) => project.getLanguageService().getSuggestionDiagnostics(file), args.includeLinePosition); + return this.getDiagnosticsWorker(args, /*isSemantic*/ true, (project, file) => project.getLanguageService().getSuggestionDiagnostics(file), !!args.includeLinePosition); } private getDocumentHighlights(args: protocol.DocumentHighlightsRequestArgs, simplifiedResult: boolean): ReadonlyArray | ReadonlyArray { @@ -837,7 +837,7 @@ namespace ts.server { function convertToDocumentHighlightsItem(documentHighlights: DocumentHighlights): protocol.DocumentHighlightsItem { const { fileName, highlightSpans } = documentHighlights; - const scriptInfo = project.getScriptInfo(fileName); + const scriptInfo = project.getScriptInfo(fileName)!; return { file: fileName, highlightSpans: highlightSpans.map(convertHighlightSpan) @@ -860,7 +860,7 @@ namespace ts.server { return this.getProjectInfoWorker(args.file, args.projectFileName, args.needFileNameList, /*excludeConfigFiles*/ false); } - private getProjectInfoWorker(uncheckedFileName: string, projectFileName: string, needFileNameList: boolean, excludeConfigFiles: boolean) { + private getProjectInfoWorker(uncheckedFileName: string, projectFileName: string | undefined, needFileNameList: boolean, excludeConfigFiles: boolean) { const { project } = this.getFileAndProjectWorker(uncheckedFileName, projectFileName); project.updateGraph(); const projectInfo = { @@ -878,7 +878,7 @@ namespace ts.server { } private getProjects(args: protocol.FileRequestArgs): Projects { - let projects: ReadonlyArray; + let projects: ReadonlyArray | undefined; let symLinkedProjects: MultiMap | undefined; if (args.projectFileName) { const project = this.getProject(args.projectFileName); @@ -887,7 +887,7 @@ namespace ts.server { } } else { - const scriptInfo = this.projectService.getScriptInfo(args.file); + const scriptInfo = this.projectService.getScriptInfo(args.file)!; projects = scriptInfo.containingProjects; symLinkedProjects = this.projectService.getSymlinkedProjects(scriptInfo); } @@ -896,7 +896,7 @@ namespace ts.server { if ((!projects || !projects.length) && !symLinkedProjects) { return Errors.ThrowNoProject(); } - return symLinkedProjects ? { projects, symLinkedProjects } : projects; + return symLinkedProjects ? { projects: projects!, symLinkedProjects } : projects!; // TODO: GH#18217 } private getDefaultProject(args: protocol.FileRequestArgs) { @@ -906,11 +906,11 @@ namespace ts.server { return project; } } - const info = this.projectService.getScriptInfo(args.file); + const info = this.projectService.getScriptInfo(args.file)!; return info.getDefaultProject(); } - private getRenameLocations(args: protocol.RenameRequestArgs, simplifiedResult: boolean): protocol.RenameResponseBody | ReadonlyArray { + private getRenameLocations(args: protocol.RenameRequestArgs, simplifiedResult: boolean): protocol.RenameResponseBody | ReadonlyArray | undefined { const file = toNormalizedPath(args.file); const position = this.getPositionInFile(args, file); const projects = this.getProjects(args); @@ -932,16 +932,16 @@ namespace ts.server { const fileSpans = combineProjectOutput( file, - path => this.projectService.getScriptInfoForPath(path).fileName, + path => this.projectService.getScriptInfoForPath(path)!.fileName, projects, (project, file) => { - const renameLocations = project.getLanguageService().findRenameLocations(file, position, args.findInStrings, args.findInComments); + const renameLocations = project.getLanguageService().findRenameLocations(file, position, args.findInStrings!, args.findInComments!); if (!renameLocations) { return emptyArray; } return renameLocations.map(location => { - const locationScriptInfo = project.getScriptInfo(location.fileName); + const locationScriptInfo = project.getScriptInfo(location.fileName)!; return { file: location.fileName, start: locationScriptInfo.positionToLineOffset(location.textSpan.start), @@ -955,7 +955,7 @@ namespace ts.server { const locs: protocol.SpanGroup[] = []; for (const cur of fileSpans) { - let curFileAccum: protocol.SpanGroup; + let curFileAccum: protocol.SpanGroup | undefined; if (locs.length > 0) { curFileAccum = locs[locs.length - 1]; if (curFileAccum.file !== cur.file) { @@ -974,9 +974,9 @@ namespace ts.server { else { return combineProjectOutput( file, - path => this.projectService.getScriptInfoForPath(path).fileName, + path => this.projectService.getScriptInfoForPath(path)!.fileName, projects, - (p, file) => p.getLanguageService().findRenameLocations(file, position, args.findInStrings, args.findInComments), + (p, file) => p.getLanguageService().findRenameLocations(file, position, args.findInStrings!, args.findInComments!), /*comparer*/ undefined, renameLocationIsEqualTo ); @@ -1021,7 +1021,7 @@ namespace ts.server { const projects = this.getProjects(args); const defaultProject = this.getDefaultProject(args); - const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file); + const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!; const position = this.getPosition(args, scriptInfo); if (simplifiedResult) { const nameInfo = defaultProject.getLanguageService().getQuickInfoAtPosition(file, position); @@ -1034,7 +1034,7 @@ namespace ts.server { const nameText = scriptInfo.getSnapshot().getText(nameSpan.start, textSpanEnd(nameSpan)); const refs = combineProjectOutput( file, - path => this.projectService.getScriptInfoForPath(path).fileName, + path => this.projectService.getScriptInfoForPath(path)!.fileName, projects, (project, file) => { const references = project.getLanguageService().getReferencesAtPosition(file, position); @@ -1043,7 +1043,7 @@ namespace ts.server { } return references.map(ref => { - const refScriptInfo = project.getScriptInfo(ref.fileName); + const refScriptInfo = project.getScriptInfo(ref.fileName)!; const start = refScriptInfo.positionToLineOffset(ref.textSpan.start); const refLineSpan = refScriptInfo.lineToTextSpan(start.line - 1); const lineText = refScriptInfo.getSnapshot().getText(refLineSpan.start, textSpanEnd(refLineSpan)).replace(/\r|\n/g, ""); @@ -1071,7 +1071,7 @@ namespace ts.server { else { return combineProjectOutput( file, - path => this.projectService.getScriptInfoForPath(path).fileName, + path => this.projectService.getScriptInfoForPath(path)!.fileName, projects, (project, file) => project.getLanguageService().findReferences(file, position), /*comparer*/ undefined, @@ -1102,11 +1102,11 @@ namespace ts.server { } private getPositionInFile(args: protocol.FileLocationRequestArgs, file: NormalizedPath): number { - const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file); + const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!; return this.getPosition(args, scriptInfo); } - private getFileAndProject(args: protocol.FileRequestArgs) { + private getFileAndProject(args: protocol.FileRequestArgs): { file: NormalizedPath, project: Project } { return this.getFileAndProjectWorker(args.file, args.projectFileName); } @@ -1124,9 +1124,9 @@ namespace ts.server { }; } - private getFileAndProjectWorker(uncheckedFileName: string, projectFileName: string) { + private getFileAndProjectWorker(uncheckedFileName: string, projectFileName: string | undefined): { file: NormalizedPath, project: Project } { const file = toNormalizedPath(uncheckedFileName); - const project: Project = this.getProject(projectFileName) || this.projectService.getDefaultProjectForFile(file, /*ensureProject*/ true); + const project = this.getProject(projectFileName) || this.projectService.getDefaultProjectForFile(file, /*ensureProject*/ true)!; // TODO: GH#18217 return { file, project }; } @@ -1134,7 +1134,7 @@ namespace ts.server { const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args); const spans = languageService.getOutliningSpans(file); if (simplifiedResult) { - const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file); + const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!; return spans.map(s => ({ textSpan: this.toLocationTextSpan(s.textSpan, scriptInfo), hintSpan: this.toLocationTextSpan(s.hintSpan, scriptInfo), @@ -1192,9 +1192,9 @@ namespace ts.server { return languageService.isValidBraceCompletionAtPosition(file, position, args.openingBrace.charCodeAt(0)); } - private getQuickInfoWorker(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): protocol.QuickInfoResponseBody | QuickInfo { + private getQuickInfoWorker(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): protocol.QuickInfoResponseBody | QuickInfo | undefined { const { file, project } = this.getFileAndProject(args); - const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file); + const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!; const quickInfo = project.getLanguageService().getQuickInfoAtPosition(file, this.getPosition(args, scriptInfo)); if (!quickInfo) { return undefined; @@ -1219,9 +1219,9 @@ namespace ts.server { } } - private getFormattingEditsForRange(args: protocol.FormatRequestArgs): protocol.CodeEdit[] { + private getFormattingEditsForRange(args: protocol.FormatRequestArgs): protocol.CodeEdit[] | undefined { const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args); - const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file); + const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!; const startPosition = scriptInfo.lineOffsetToPosition(args.line, args.offset); const endPosition = scriptInfo.lineOffsetToPosition(args.endLine, args.endOffset); @@ -1238,7 +1238,7 @@ namespace ts.server { private getFormattingEditsForRangeFull(args: protocol.FormatRequestArgs) { const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args); const options = args.options ? convertFormatOptions(args.options) : this.getFormatOptions(file); - return languageService.getFormattingEditsForRange(file, args.position, args.endPosition, options); + return languageService.getFormattingEditsForRange(file, args.position!, args.endPosition!, options); // TODO: GH#18217 } private getFormattingEditsForDocumentFull(args: protocol.FormatRequestArgs) { @@ -1250,12 +1250,12 @@ namespace ts.server { private getFormattingEditsAfterKeystrokeFull(args: protocol.FormatOnKeyRequestArgs) { const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args); const options = args.options ? convertFormatOptions(args.options) : this.getFormatOptions(file); - return languageService.getFormattingEditsAfterKeystroke(file, args.position, args.key, options); + return languageService.getFormattingEditsAfterKeystroke(file, args.position!, args.key, options); // TODO: GH#18217 } - private getFormattingEditsAfterKeystroke(args: protocol.FormatOnKeyRequestArgs): protocol.CodeEdit[] { + private getFormattingEditsAfterKeystroke(args: protocol.FormatOnKeyRequestArgs): protocol.CodeEdit[] | undefined { const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args); - const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file); + const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!; const position = scriptInfo.lineOffsetToPosition(args.line, args.offset); const formatOptions = this.getFormatOptions(file); const edits = languageService.getFormattingEditsAfterKeystroke(file, position, args.key, @@ -1277,7 +1277,7 @@ namespace ts.server { hasIndent++; } else if (lineText.charAt(i) === "\t") { - hasIndent += formatOptions.tabSize; + hasIndent += formatOptions.tabSize!; // TODO: GH#18217 } else { break; @@ -1310,7 +1310,7 @@ namespace ts.server { private getCompletions(args: protocol.CompletionsRequestArgs, simplifiedResult: boolean): ReadonlyArray | CompletionInfo | undefined { const prefix = args.prefix || ""; const { file, project } = this.getFileAndProject(args); - const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file); + const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!; const position = this.getPosition(args, scriptInfo); const completions = project.getLanguageService().getCompletionsAtPosition(file, position, { @@ -1321,7 +1321,7 @@ namespace ts.server { }); if (simplifiedResult) { return mapDefined(completions && completions.entries, entry => { - if (completions.isMemberCompletion || startsWith(entry.name.toLowerCase(), prefix.toLowerCase())) { + if (completions!.isMemberCompletion || startsWith(entry.name.toLowerCase(), prefix.toLowerCase())) { const { name, kind, kindModifiers, sortText, insertText, replacementSpan, hasAction, source, isRecommended } = entry; const convertedSpan = replacementSpan ? this.toLocationTextSpan(replacementSpan, scriptInfo) : undefined; // Use `hasAction || undefined` to avoid serializing `false`. @@ -1336,7 +1336,7 @@ namespace ts.server { private getCompletionEntryDetails(args: protocol.CompletionDetailsRequestArgs, simplifiedResult: boolean): ReadonlyArray | ReadonlyArray { const { file, project } = this.getFileAndProject(args); - const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file); + const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!; const position = this.getPosition(args, scriptInfo); const formattingOptions = project.projectService.getFormatCodeOptions(file); @@ -1356,14 +1356,14 @@ namespace ts.server { } // if specified a project, we only return affected file list in this project - const projects = args.projectFileName ? [this.projectService.findProject(args.projectFileName)] : info.containingProjects; + const projects = args.projectFileName ? [this.projectService.findProject(args.projectFileName)!] : info.containingProjects; const symLinkedProjects = !args.projectFileName && this.projectService.getSymlinkedProjects(info); return combineProjectOutput( info, - path => this.projectService.getScriptInfoForPath(path), + path => this.projectService.getScriptInfoForPath(path)!, symLinkedProjects ? { projects, symLinkedProjects } : projects, (project, info) => { - let result: protocol.CompileOnSaveAffectedFileListSingleProject; + let result: protocol.CompileOnSaveAffectedFileListSingleProject | undefined; if (project.compileOnSaveEnabled && project.languageServiceEnabled && !project.isOrphan() && !project.getCompilationSettings().noEmit) { result = { projectFileName: project.getProjectName(), @@ -1384,13 +1384,13 @@ namespace ts.server { if (!project.languageServiceEnabled) { return false; } - const scriptInfo = project.getScriptInfo(file); + const scriptInfo = project.getScriptInfo(file)!; return project.emitFile(scriptInfo, (path, data, writeByteOrderMark) => this.host.writeFile(path, data, writeByteOrderMark)); } - private getSignatureHelpItems(args: protocol.SignatureHelpRequestArgs, simplifiedResult: boolean): protocol.SignatureHelpItems | SignatureHelpItems { + private getSignatureHelpItems(args: protocol.SignatureHelpRequestArgs, simplifiedResult: boolean): protocol.SignatureHelpItems | SignatureHelpItems | undefined { const { file, project } = this.getFileAndProject(args); - const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file); + const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!; const position = this.getPosition(args, scriptInfo); const helpItems = project.getLanguageService().getSignatureHelpItems(file, position); if (!helpItems) { @@ -1435,7 +1435,7 @@ namespace ts.server { } private change(args: protocol.ChangeRequestArgs) { - const scriptInfo = this.projectService.getScriptInfo(args.file); + const scriptInfo = this.projectService.getScriptInfo(args.file)!; Debug.assert(!!scriptInfo); const start = scriptInfo.lineOffsetToPosition(args.line, args.offset); const end = scriptInfo.lineOffsetToPosition(args.endLine, args.endOffset); @@ -1443,14 +1443,14 @@ namespace ts.server { this.changeSeq++; this.projectService.applyChangesToFile(scriptInfo, [{ span: { start, length: end - start }, - newText: args.insertString + newText: args.insertString! // TODO: GH#18217 }]); } } private reload(args: protocol.ReloadRequestArgs, reqSeq: number) { const file = toNormalizedPath(args.file); - const tempFileName = args.tmpfile && toNormalizedPath(args.tmpfile); + const tempFileName = args.tmpfile === undefined ? undefined : toNormalizedPath(args.tmpfile); const info = this.projectService.getScriptInfoForNormalizedPath(file); if (info) { this.changeSeq++; @@ -1487,13 +1487,13 @@ namespace ts.server { })); } - private getNavigationBarItems(args: protocol.FileRequestArgs, simplifiedResult: boolean): protocol.NavigationBarItem[] | NavigationBarItem[] { + private getNavigationBarItems(args: protocol.FileRequestArgs, simplifiedResult: boolean): protocol.NavigationBarItem[] | NavigationBarItem[] | undefined { const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args); const items = languageService.getNavigationBarItems(file); return !items ? undefined : simplifiedResult - ? this.mapLocationNavigationBarItems(items, this.projectService.getScriptInfoForNormalizedPath(file)) + ? this.mapLocationNavigationBarItems(items, this.projectService.getScriptInfoForNormalizedPath(file)!) : items; } @@ -1514,13 +1514,13 @@ namespace ts.server { }; } - private getNavigationTree(args: protocol.FileRequestArgs, simplifiedResult: boolean): protocol.NavigationTree | NavigationTree { + private getNavigationTree(args: protocol.FileRequestArgs, simplifiedResult: boolean): protocol.NavigationTree | NavigationTree | undefined { const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args); const tree = languageService.getNavigationTree(file); return !tree ? undefined : simplifiedResult - ? this.toLocationNavigationTree(tree, this.projectService.getScriptInfoForNormalizedPath(file)) + ? this.toLocationNavigationTree(tree, this.projectService.getScriptInfoForNormalizedPath(file)!) : tree; } @@ -1544,7 +1544,7 @@ namespace ts.server { } return navItems.map((navItem) => { - const scriptInfo = project.getScriptInfo(navItem.fileName); + const scriptInfo = project.getScriptInfo(navItem.fileName)!; const bakedItem: protocol.NavtoItem = { name: navItem.name, kind: navItem.kind, @@ -1624,8 +1624,8 @@ namespace ts.server { } private extractPositionAndRange(args: protocol.FileLocationOrRangeRequestArgs, scriptInfo: ScriptInfo): { position: number, textRange: TextRange } { - let position: number; - let textRange: TextRange; + let position: number | undefined; + let textRange: TextRange | undefined; if (this.isLocation(args)) { position = getPosition(args); } @@ -1633,7 +1633,7 @@ namespace ts.server { const { startPosition, endPosition } = this.getStartAndEndPosition(args, scriptInfo); textRange = { pos: startPosition, end: endPosition }; } - return { position, textRange }; + return { position: position!, textRange: textRange! }; // TODO: GH#18217 function getPosition(loc: protocol.FileLocationRequestArgs) { return loc.position !== undefined ? loc.position : scriptInfo.lineOffsetToPosition(loc.line, loc.offset); @@ -1642,14 +1642,14 @@ namespace ts.server { private getApplicableRefactors(args: protocol.GetApplicableRefactorsRequestArgs): protocol.ApplicableRefactorInfo[] { const { file, project } = this.getFileAndProject(args); - const scriptInfo = project.getScriptInfoForNormalizedPath(file); + const scriptInfo = project.getScriptInfoForNormalizedPath(file)!; const { position, textRange } = this.extractPositionAndRange(args, scriptInfo); return project.getLanguageService().getApplicableRefactors(file, position || textRange, this.getPreferences(file)); } private getEditsForRefactor(args: protocol.GetEditsForRefactorRequestArgs, simplifiedResult: boolean): RefactorEditInfo | protocol.RefactorEditInfo { const { file, project } = this.getFileAndProject(args); - const scriptInfo = project.getScriptInfoForNormalizedPath(file); + const scriptInfo = project.getScriptInfoForNormalizedPath(file)!; const { position, textRange } = this.extractPositionAndRange(args, scriptInfo); const result = project.getLanguageService().getEditsForRefactor( @@ -1671,7 +1671,7 @@ namespace ts.server { const { renameFilename, renameLocation, edits } = result; let mappedRenameLocation: protocol.Location | undefined; if (renameFilename !== undefined && renameLocation !== undefined) { - const renameScriptInfo = project.getScriptInfoForNormalizedPath(toNormalizedPath(renameFilename)); + const renameScriptInfo = project.getScriptInfoForNormalizedPath(toNormalizedPath(renameFilename))!; mappedRenameLocation = getLocationInNewDocument(getSnapshotText(renameScriptInfo.getSnapshot()), renameFilename, renameLocation, edits); } return { renameLocation: mappedRenameLocation, renameFilename, edits: this.mapTextChangesToCodeEdits(project, edits) }; @@ -1699,16 +1699,16 @@ namespace ts.server { return simplifiedResult ? this.mapTextChangesToCodeEdits(project, changes) : changes; } - private getCodeFixes(args: protocol.CodeFixRequestArgs, simplifiedResult: boolean): ReadonlyArray | ReadonlyArray { - if (args.errorCodes.length === 0) { + private getCodeFixes(args: protocol.CodeFixRequestArgs, simplifiedResult: boolean): ReadonlyArray | ReadonlyArray | undefined { + if (args.errorCodes!.length === 0) { // TODO: GH#18217 return undefined; } const { file, project } = this.getFileAndProject(args); - const scriptInfo = project.getScriptInfoForNormalizedPath(file); + const scriptInfo = project.getScriptInfoForNormalizedPath(file)!; const { startPosition, endPosition } = this.getStartAndEndPosition(args, scriptInfo); - const codeActions = project.getLanguageService().getCodeFixesAtPosition(file, startPosition, endPosition, args.errorCodes, this.getFormatOptions(file), this.getPreferences(file)); + const codeActions = project.getLanguageService().getCodeFixesAtPosition(file, startPosition, endPosition, args.errorCodes!, this.getFormatOptions(file), this.getPreferences(file)); return simplifiedResult ? codeActions.map(codeAction => this.mapCodeFixAction(project, codeAction)) : codeActions; } @@ -1736,7 +1736,7 @@ namespace ts.server { } private getStartAndEndPosition(args: protocol.FileRangeRequestArgs, scriptInfo: ScriptInfo) { - let startPosition: number, endPosition: number; + let startPosition: number | undefined, endPosition: number | undefined; if (args.startPosition !== undefined) { startPosition = args.startPosition; } @@ -1766,7 +1766,7 @@ namespace ts.server { } private mapTextChangesToCodeEdits(project: Project, textChanges: ReadonlyArray): protocol.FileCodeEdits[] { - return textChanges.map(change => this.mapTextChangesToCodeEditsUsingScriptinfo(change, project.getScriptInfoForNormalizedPath(toNormalizedPath(change.fileName)))); + return textChanges.map(change => this.mapTextChangesToCodeEditsUsingScriptinfo(change, project.getScriptInfoForNormalizedPath(toNormalizedPath(change.fileName))!)); } private mapTextChangesToCodeEditsUsingScriptinfo(textChanges: FileTextChanges, scriptInfo: ScriptInfo | undefined): protocol.FileCodeEdits { @@ -1797,9 +1797,9 @@ namespace ts.server { return { fileName: textChanges.fileName, textChanges: [{ start: { line: 0, offset: 0 }, end: { line: 0, offset: 0 }, newText: change.newText }] }; } - private getBraceMatching(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): protocol.TextSpan[] | TextSpan[] { + private getBraceMatching(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): protocol.TextSpan[] | TextSpan[] | undefined { const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args); - const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file); + const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!; const position = this.getPosition(args, scriptInfo); const spans = languageService.getBraceMatchingAtPosition(file, position); @@ -1821,7 +1821,7 @@ namespace ts.server { } // No need to analyze lib.d.ts - const fileNamesInProject = fileNames.filter(value => !stringContains(value, "lib.d.ts")); + const fileNamesInProject = fileNames!.filter(value => !stringContains(value, "lib.d.ts")); // TODO: GH#18217 if (fileNamesInProject.length === 0) { return; } @@ -1832,13 +1832,13 @@ namespace ts.server { const lowPriorityFiles: NormalizedPath[] = []; const veryLowPriorityFiles: NormalizedPath[] = []; const normalizedFileName = toNormalizedPath(fileName); - const project = this.projectService.getDefaultProjectForFile(normalizedFileName, /*ensureProject*/ true); + const project = this.projectService.getDefaultProjectForFile(normalizedFileName, /*ensureProject*/ true)!; for (const fileNameInProject of fileNamesInProject) { if (this.getCanonicalFileName(fileNameInProject) === this.getCanonicalFileName(fileName)) { highPriorityFiles.push(fileNameInProject); } else { - const info = this.projectService.getScriptInfo(fileNameInProject); + const info = this.projectService.getScriptInfo(fileNameInProject)!; // TODO: GH#18217 if (!info.isScriptOpen()) { if (fileExtensionIs(fileNameInProject, Extension.Dts)) { veryLowPriorityFiles.push(fileNameInProject); @@ -1871,7 +1871,7 @@ namespace ts.server { return { responseRequired: false }; } - private requiredResponse(response: {}): HandlerResponse { + private requiredResponse(response: {} | undefined): HandlerResponse { return { response, responseRequired: true }; } @@ -1915,7 +1915,7 @@ namespace ts.server { }, [CommandNames.ApplyChangedToOpenFiles]: (request: protocol.ApplyChangedToOpenFilesRequest) => { this.changeSeq++; - this.projectService.applyChangesInOpenFiles(request.arguments.openFiles, request.arguments.changedFiles, request.arguments.closedFiles); + this.projectService.applyChangesInOpenFiles(request.arguments.openFiles, request.arguments.changedFiles!, request.arguments.closedFiles!); // TODO: GH#18217 // TODO: report errors return this.requiredResponse(/*response*/ true); }, @@ -1963,7 +1963,7 @@ namespace ts.server { this.openClientFile( toNormalizedPath(request.arguments.file), request.arguments.fileContent, - convertScriptKindName(request.arguments.scriptKindName), + convertScriptKindName(request.arguments.scriptKindName!), // TODO: GH#18217 request.arguments.projectRootPath ? toNormalizedPath(request.arguments.projectRootPath) : undefined); return this.notRequired(); }, @@ -2189,7 +2189,7 @@ namespace ts.server { private resetCurrentRequest(requestId: number): void { Debug.assert(this.currentRequestId === requestId); - this.currentRequestId = undefined; + this.currentRequestId = undefined!; // TODO: GH#18217 this.cancellationToken.resetRequest(requestId); } @@ -2217,7 +2217,7 @@ namespace ts.server { public onMessage(message: string) { this.gcTimer.scheduleCollect(); - let start: number[]; + let start: number[] | undefined; if (this.logger.hasLevel(LogLevel.requestTime)) { start = this.hrtime(); if (this.logger.hasLevel(LogLevel.verbose)) { @@ -2225,7 +2225,7 @@ namespace ts.server { } } - let request: protocol.Request; + let request: protocol.Request | undefined; try { request = JSON.parse(message); const { response, responseRequired } = this.executeCommand(request); @@ -2250,7 +2250,7 @@ namespace ts.server { catch (err) { if (err instanceof OperationCanceledException) { // Handle cancellation exceptions - this.doOutput({ canceled: true }, request.command, request.seq, /*success*/ true); + this.doOutput({ canceled: true }, request!.command, request!.seq, /*success*/ true); return; } this.logError(err, message); diff --git a/src/server/typingsCache.ts b/src/server/typingsCache.ts index 7440735ecb24c..12b2303cfd359 100644 --- a/src/server/typingsCache.ts +++ b/src/server/typingsCache.ts @@ -8,7 +8,7 @@ namespace ts.server { export interface ITypingsInstaller { isKnownTypesPackageName(name: string): boolean; installPackage(options: InstallPackageOptionsWithProject): Promise; - enqueueInstallTypingsRequest(p: Project, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray): void; + enqueueInstallTypingsRequest(p: Project, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray | undefined): void; attach(projectService: ProjectService): void; onProjectClosed(p: Project): void; readonly globalTypingsCacheLocation: string | undefined; @@ -21,19 +21,19 @@ namespace ts.server { enqueueInstallTypingsRequest: noop, attach: noop, onProjectClosed: noop, - globalTypingsCacheLocation: undefined + globalTypingsCacheLocation: undefined! // TODO: GH#18217 }; interface TypingsCacheEntry { readonly typeAcquisition: TypeAcquisition; readonly compilerOptions: CompilerOptions; readonly typings: SortedReadonlyArray; - readonly unresolvedImports: SortedReadonlyArray; + readonly unresolvedImports: SortedReadonlyArray | undefined; /* mainly useful for debugging */ poisoned: boolean; } - function setIsEqualTo(arr1: string[], arr2: string[]): boolean { + function setIsEqualTo(arr1: string[] | undefined, arr2: string[] | undefined): boolean { if (arr1 === arr2) { return true; } @@ -43,13 +43,13 @@ namespace ts.server { const set: Map = createMap(); let unique = 0; - for (const v of arr1) { + for (const v of arr1!) { if (set.get(v) !== true) { set.set(v, true); unique++; } } - for (const v of arr2) { + for (const v of arr2!) { const isSet = set.get(v); if (isSet === undefined) { return false; @@ -73,7 +73,7 @@ namespace ts.server { return opt1.allowJs !== opt2.allowJs; } - function unresolvedImportsChanged(imports1: SortedReadonlyArray, imports2: SortedReadonlyArray): boolean { + function unresolvedImportsChanged(imports1: SortedReadonlyArray | undefined, imports2: SortedReadonlyArray | undefined): boolean { if (imports1 === imports2) { return false; } @@ -95,7 +95,7 @@ namespace ts.server { return this.installer.installPackage(options); } - enqueueInstallTypingsForProject(project: Project, unresolvedImports: SortedReadonlyArray, forceRefresh: boolean) { + enqueueInstallTypingsForProject(project: Project, unresolvedImports: SortedReadonlyArray | undefined, forceRefresh: boolean) { const typeAcquisition = project.getTypeAcquisition(); if (!typeAcquisition || !typeAcquisition.enable) { diff --git a/src/server/typingsInstaller/nodeTypingsInstaller.ts b/src/server/typingsInstaller/nodeTypingsInstaller.ts index 875f5d881f003..7132a93f3ef8f 100644 --- a/src/server/typingsInstaller/nodeTypingsInstaller.ts +++ b/src/server/typingsInstaller/nodeTypingsInstaller.ts @@ -1,4 +1,4 @@ -/// +// tslint:disable no-unnecessary-type-assertion (TODO: tslint can't find node types) namespace ts.server.typingsInstaller { const fs: { @@ -22,7 +22,7 @@ namespace ts.server.typingsInstaller { } writeLine = (text: string) => { try { - fs.appendFileSync(this.logFile, `[${nowString()}] ${text}${sys.newLine}`); + fs.appendFileSync(this.logFile!, `[${nowString()}] ${text}${sys.newLine}`); // TODO: GH#18217 } catch (e) { this.logEnabled = false; @@ -53,7 +53,7 @@ namespace ts.server.typingsInstaller { return createMap>(); } try { - const content = JSON.parse(host.readFile(typesRegistryFilePath)); + const content = JSON.parse(host.readFile(typesRegistryFilePath)!); return createMapFromTemplate(content.entries); } catch (e) { @@ -176,7 +176,7 @@ namespace ts.server.typingsInstaller { if (this.log.isEnabled()) { this.log.writeLine(`Sending response:\n ${JSON.stringify(response)}`); } - process.send(response); + process.send!(response); // TODO: GH#18217 if (this.log.isEnabled()) { this.log.writeLine(`Response has been sent.`); } @@ -240,7 +240,7 @@ namespace ts.server.typingsInstaller { } process.exit(0); }); - const installer = new NodeTypingsInstaller(globalTypingsCacheLocation, typingSafeListLocation, typesMapLocation, npmLocation, /*throttleLimit*/5, log); + const installer = new NodeTypingsInstaller(globalTypingsCacheLocation!, typingSafeListLocation!, typesMapLocation!, npmLocation, /*throttleLimit*/5, log); // TODO: GH#18217 installer.listen(); function indent(newline: string, str: string): string { diff --git a/src/server/typingsInstaller/typingsInstaller.ts b/src/server/typingsInstaller/typingsInstaller.ts index 7d8cf02fab08a..5c1fcda618491 100644 --- a/src/server/typingsInstaller/typingsInstaller.ts +++ b/src/server/typingsInstaller/typingsInstaller.ts @@ -17,7 +17,7 @@ namespace ts.server.typingsInstaller { writeLine: noop }; - function typingToFileName(cachePath: string, packageName: string, installTypingHost: InstallTypingHost, log: Log): string { + function typingToFileName(cachePath: string, packageName: string, installTypingHost: InstallTypingHost, log: Log): string | undefined { try { const result = resolveModuleName(packageName, combinePaths(cachePath, "index.d.ts"), { moduleResolution: ModuleResolutionKind.NodeJs }, installTypingHost); return result.resolvedModule && result.resolvedModule.resolvedFileName; @@ -154,7 +154,7 @@ namespace ts.server.typingsInstaller { this.log.isEnabled() ? (s => this.log.writeLine(s)) : undefined, req.fileNames, req.projectRootPath, - this.safeList, + this.safeList!, this.packageNameToTypingLocation, req.typeAcquisition, req.unresolvedImports, @@ -209,8 +209,8 @@ namespace ts.server.typingsInstaller { this.log.writeLine(`Trying to find '${packageJson}'...`); } if (this.installTypingHost.fileExists(packageJson) && this.installTypingHost.fileExists(packageLockJson)) { - const npmConfig = JSON.parse(this.installTypingHost.readFile(packageJson)); - const npmLock = JSON.parse(this.installTypingHost.readFile(packageLockJson)); + const npmConfig = JSON.parse(this.installTypingHost.readFile(packageJson)!); // TODO: GH#18217 + const npmLock = JSON.parse(this.installTypingHost.readFile(packageLockJson)!); // TODO: GH#18217 if (this.log.isEnabled()) { this.log.writeLine(`Loaded content of '${packageJson}': ${JSON.stringify(npmConfig)}`); this.log.writeLine(`Loaded content of '${packageLockJson}'`); @@ -246,7 +246,7 @@ namespace ts.server.typingsInstaller { } const info = getProperty(npmLock.dependencies, key); const version = info && info.version; - const semver = Semver.parse(version); + const semver = Semver.parse(version!); // TODO: GH#18217 const newTyping: JsTyping.CachedTyping = { typingLocation: typingFile, version: semver }; this.packageNameToTypingLocation.set(packageName, newTyping); } @@ -275,7 +275,7 @@ namespace ts.server.typingsInstaller { if (this.log.isEnabled()) this.log.writeLine(`Entry for package '${typing}' does not exist in local types registry - skipping...`); return false; } - if (this.packageNameToTypingLocation.get(typing) && JsTyping.isTypingUpToDate(this.packageNameToTypingLocation.get(typing), this.typesRegistry.get(typing))) { + if (this.packageNameToTypingLocation.get(typing) && JsTyping.isTypingUpToDate(this.packageNameToTypingLocation.get(typing)!, this.typesRegistry.get(typing)!)) { if (this.log.isEnabled()) this.log.writeLine(`'${typing}' already has an up-to-date typing - skipping...`); return false; } @@ -349,7 +349,7 @@ namespace ts.server.typingsInstaller { } // packageName is guaranteed to exist in typesRegistry by filterTypings - const distTags = this.typesRegistry.get(packageName); + const distTags = this.typesRegistry.get(packageName)!; const newVersion = Semver.parse(distTags[`ts${versionMajorMinor}`] || distTags[latestDistTag]); const newTyping: JsTyping.CachedTyping = { typingLocation: typingFile, version: newVersion }; this.packageNameToTypingLocation.set(packageName, newTyping); @@ -392,7 +392,7 @@ namespace ts.server.typingsInstaller { return; } - let watchers = this.projectWatchers.get(projectName); + let watchers = this.projectWatchers.get(projectName)!; const toRemove = createMap(); if (!watchers) { watchers = createMap(); @@ -418,7 +418,7 @@ namespace ts.server.typingsInstaller { if (isLoggingEnabled) { this.log.writeLine(`FileWatcher:: Added:: WatchInfo: ${file}`); } - const watcher = this.installTypingHost.watchFile(file, (f, eventKind) => { + const watcher = this.installTypingHost.watchFile!(file, (f, eventKind) => { // TODO: GH#18217 if (isLoggingEnabled) { this.log.writeLine(`FileWatcher:: Triggered with ${f} eventKind: ${FileWatcherEventKind[eventKind]}:: WatchInfo: ${file}:: handler is already invoked '${watchers.isInvoked}'`); } @@ -439,7 +439,7 @@ namespace ts.server.typingsInstaller { if (isLoggingEnabled) { this.log.writeLine(`DirectoryWatcher:: Added:: WatchInfo: ${dir} recursive`); } - const watcher = this.installTypingHost.watchDirectory(dir, f => { + const watcher = this.installTypingHost.watchDirectory!(dir, f => { // TODO: GH#18217 if (isLoggingEnabled) { this.log.writeLine(`DirectoryWatcher:: Triggered with ${f} :: WatchInfo: ${dir} recursive :: handler is already invoked '${watchers.isInvoked}'`); } @@ -512,7 +512,7 @@ namespace ts.server.typingsInstaller { private executeWithThrottling() { while (this.inFlightRequestCount < this.throttleLimit && this.pendingRunRequests.length) { this.inFlightRequestCount++; - const request = this.pendingRunRequests.pop(); + const request = this.pendingRunRequests.pop()!; this.installWorker(request.requestId, request.packageNames, request.cwd, ok => { this.inFlightRequestCount--; request.onRequestCompleted(ok); diff --git a/src/server/utilities.ts b/src/server/utilities.ts index 5705960f3d255..36a013e6104d5 100644 --- a/src/server/utilities.ts +++ b/src/server/utilities.ts @@ -17,7 +17,7 @@ namespace ts.server { startGroup(): void; endGroup(): void; msg(s: string, type?: Msg): void; - getLogFileName(): string; + getLogFileName(): string | undefined; } // TODO: Use a const enum (https://github.com/Microsoft/TypeScript/issues/16804) @@ -96,7 +96,7 @@ namespace ts.server { } export interface NormalizedPathMap { - get(path: NormalizedPath): T; + get(path: NormalizedPath): T | undefined; set(path: NormalizedPath, value: T): void; contains(path: NormalizedPath): boolean; remove(path: NormalizedPath): void; @@ -150,7 +150,7 @@ namespace ts.server { } export function createSortedArray(): SortedArray { - return [] as SortedArray; + return [] as any as SortedArray; // TODO: GH#19873 } } @@ -160,7 +160,7 @@ namespace ts.server { private readonly pendingTimeouts: Map = createMap(); private readonly logger?: Logger | undefined; constructor(private readonly host: ServerHost, logger: Logger) { - this.logger = logger.hasLevel(LogLevel.verbose) && logger; + this.logger = logger.hasLevel(LogLevel.verbose) ? logger : undefined; } /** @@ -208,11 +208,11 @@ namespace ts.server { self.timerId = undefined; const log = self.logger.hasLevel(LogLevel.requestTime); - const before = log && self.host.getMemoryUsage(); + const before = log && self.host.getMemoryUsage!(); // TODO: GH#18217 - self.host.gc(); + self.host.gc!(); // TODO: GH#18217 if (log) { - const after = self.host.getMemoryUsage(); + const after = self.host.getMemoryUsage!(); // TODO: GH#18217 self.logger.perftrc(`GC::before ${before}, after ${after}`); } } diff --git a/src/services/breakpoints.ts b/src/services/breakpoints.ts index 6815be9863d1a..812a8a45dd059 100644 --- a/src/services/breakpoints.ts +++ b/src/services/breakpoints.ts @@ -17,12 +17,13 @@ namespace ts.BreakpointResolver { // let y = 10; // token at position will return let keyword on second line as the token but we would like to use // token on same line if trailing trivia (comments or white spaces on same line) part of the last token on that line - tokenAtLocation = findPrecedingToken(tokenAtLocation.pos, sourceFile); + const preceding = findPrecedingToken(tokenAtLocation.pos, sourceFile); // It's a blank line - if (!tokenAtLocation || sourceFile.getLineAndCharacterOfPosition(tokenAtLocation.getEnd()).line !== lineOfPosition) { + if (!preceding || sourceFile.getLineAndCharacterOfPosition(preceding.getEnd()).line !== lineOfPosition) { return undefined; } + tokenAtLocation = preceding; } // Cannot set breakpoint in ambient declarations @@ -44,7 +45,7 @@ namespace ts.BreakpointResolver { return textSpan(startNode, findNextToken(previousTokenToFindNextEndToken, previousTokenToFindNextEndToken.parent, sourceFile)); } - function spanInNodeIfStartsOnSameLine(node: Node, otherwiseOnNode?: Node): TextSpan { + function spanInNodeIfStartsOnSameLine(node: Node | undefined, otherwiseOnNode?: Node): TextSpan | undefined { if (node && lineOfPosition === sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line) { return spanInNode(node); } @@ -55,16 +56,17 @@ namespace ts.BreakpointResolver { return createTextSpanFromBounds(skipTrivia(sourceFile.text, nodeArray.pos), nodeArray.end); } - function spanInPreviousNode(node: Node): TextSpan { + function spanInPreviousNode(node: Node): TextSpan | undefined { return spanInNode(findPrecedingToken(node.pos, sourceFile)); } - function spanInNextNode(node: Node): TextSpan { + function spanInNextNode(node: Node): TextSpan | undefined { return spanInNode(findNextToken(node, node.parent, sourceFile)); } - function spanInNode(node: Node): TextSpan { + function spanInNode(node: Node | undefined): TextSpan | undefined { if (node) { + const { parent } = node; switch (node.kind) { case SyntaxKind.VariableStatement: // Span on first variable declaration @@ -195,7 +197,7 @@ namespace ts.BreakpointResolver { return spanInNode((node).statement); case SyntaxKind.Decorator: - return spanInNodeArray(node.parent.decorators); + return spanInNodeArray(parent.decorators!); case SyntaxKind.ObjectBindingPattern: case SyntaxKind.ArrayBindingPattern: @@ -263,7 +265,7 @@ namespace ts.BreakpointResolver { node.kind === SyntaxKind.SpreadElement || node.kind === SyntaxKind.PropertyAssignment || node.kind === SyntaxKind.ShorthandPropertyAssignment) && - isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent)) { + isArrayLiteralOrObjectLiteralDestructuringPattern(parent)) { return textSpan(node); } @@ -292,7 +294,7 @@ namespace ts.BreakpointResolver { } if (isExpressionNode(node)) { - switch (node.parent.kind) { + switch (parent.kind) { case SyntaxKind.DoStatement: // Set span as if on while keyword return spanInPreviousNode(node); @@ -367,7 +369,7 @@ namespace ts.BreakpointResolver { function textSpanFromVariableDeclaration(variableDeclaration: VariableDeclaration | PropertyDeclaration | PropertySignature): TextSpan { if (isVariableDeclarationList(variableDeclaration.parent) && variableDeclaration.parent.declarations[0] === variableDeclaration) { // First declaration - include let keyword - return textSpan(findPrecedingToken(variableDeclaration.pos, sourceFile, variableDeclaration.parent), variableDeclaration); + return textSpan(findPrecedingToken(variableDeclaration.pos, sourceFile, variableDeclaration.parent)!, variableDeclaration); } else { // Span only on this declaration @@ -375,12 +377,13 @@ namespace ts.BreakpointResolver { } } - function spanInVariableDeclaration(variableDeclaration: VariableDeclaration | PropertyDeclaration | PropertySignature): TextSpan { + function spanInVariableDeclaration(variableDeclaration: VariableDeclaration | PropertyDeclaration | PropertySignature): TextSpan | undefined { // If declaration of for in statement, just set the span in parent if (variableDeclaration.parent.parent.kind === SyntaxKind.ForInStatement) { return spanInNode(variableDeclaration.parent.parent); } + const parent = variableDeclaration.parent; // If this is a destructuring pattern, set breakpoint in binding pattern if (isBindingPattern(variableDeclaration.name)) { return spanInBindingPattern(variableDeclaration.name); @@ -390,7 +393,7 @@ namespace ts.BreakpointResolver { // or its declaration from 'for of' if (variableDeclaration.initializer || hasModifier(variableDeclaration, ModifierFlags.Export) || - variableDeclaration.parent.parent.kind === SyntaxKind.ForOfStatement) { + parent.parent.kind === SyntaxKind.ForOfStatement) { return textSpanFromVariableDeclaration(variableDeclaration); } @@ -410,7 +413,7 @@ namespace ts.BreakpointResolver { hasModifier(parameter, ModifierFlags.Public | ModifierFlags.Private); } - function spanInParameterDeclaration(parameter: ParameterDeclaration): TextSpan { + function spanInParameterDeclaration(parameter: ParameterDeclaration): TextSpan | undefined { if (isBindingPattern(parameter.name)) { // Set breakpoint in binding pattern return spanInBindingPattern(parameter.name); @@ -438,7 +441,7 @@ namespace ts.BreakpointResolver { (functionDeclaration.parent.kind === SyntaxKind.ClassDeclaration && functionDeclaration.kind !== SyntaxKind.Constructor); } - function spanInFunctionDeclaration(functionDeclaration: FunctionLikeDeclaration): TextSpan { + function spanInFunctionDeclaration(functionDeclaration: FunctionLikeDeclaration): TextSpan | undefined { // No breakpoints in the function signature if (!functionDeclaration.body) { return undefined; @@ -453,7 +456,7 @@ namespace ts.BreakpointResolver { return spanInNode(functionDeclaration.body); } - function spanInFunctionBlock(block: Block): TextSpan { + function spanInFunctionBlock(block: Block): TextSpan | undefined { const nodeForSpanInBlock = block.statements.length ? block.statements[0] : block.getLastToken(); if (canFunctionHaveSpanInWholeDeclaration(block.parent)) { return spanInNodeIfStartsOnSameLine(block.parent, nodeForSpanInBlock); @@ -462,7 +465,7 @@ namespace ts.BreakpointResolver { return spanInNode(nodeForSpanInBlock); } - function spanInBlock(block: Block): TextSpan { + function spanInBlock(block: Block): TextSpan | undefined { switch (block.parent.kind) { case SyntaxKind.ModuleDeclaration: if (getModuleInstanceState(block.parent as ModuleDeclaration) !== ModuleInstanceState.Instantiated) { @@ -486,8 +489,8 @@ namespace ts.BreakpointResolver { return spanInNode(block.statements[0]); } - function spanInInitializerOfForLike(forLikeStatement: ForStatement | ForOfStatement | ForInStatement): TextSpan { - if (forLikeStatement.initializer.kind === SyntaxKind.VariableDeclarationList) { + function spanInInitializerOfForLike(forLikeStatement: ForStatement | ForOfStatement | ForInStatement): TextSpan | undefined { + if (forLikeStatement.initializer!.kind === SyntaxKind.VariableDeclarationList) { // Declaration list - set breakpoint in first declaration const variableDeclarationList = forLikeStatement.initializer; if (variableDeclarationList.declarations.length > 0) { @@ -500,7 +503,7 @@ namespace ts.BreakpointResolver { } } - function spanInForStatement(forStatement: ForStatement): TextSpan { + function spanInForStatement(forStatement: ForStatement): TextSpan | undefined { if (forStatement.initializer) { return spanInInitializerOfForLike(forStatement); } @@ -513,7 +516,7 @@ namespace ts.BreakpointResolver { } } - function spanInBindingPattern(bindingPattern: BindingPattern): TextSpan { + function spanInBindingPattern(bindingPattern: BindingPattern): TextSpan | undefined { // Set breakpoint in first binding element const firstBindingElement = forEach(bindingPattern.elements, element => element.kind !== SyntaxKind.OmittedExpression ? element : undefined); @@ -531,7 +534,7 @@ namespace ts.BreakpointResolver { return textSpanFromVariableDeclaration(bindingPattern.parent); } - function spanInArrayLiteralOrObjectLiteralDestructuringPattern(node: DestructuringPattern): TextSpan { + function spanInArrayLiteralOrObjectLiteralDestructuringPattern(node: DestructuringPattern): TextSpan | undefined { Debug.assert(node.kind !== SyntaxKind.ArrayBindingPattern && node.kind !== SyntaxKind.ObjectBindingPattern); const elements: NodeArray = node.kind === SyntaxKind.ArrayLiteralExpression ? node.elements : (node as ObjectLiteralExpression).properties; @@ -550,7 +553,7 @@ namespace ts.BreakpointResolver { } // Tokens: - function spanInOpenBraceToken(node: Node): TextSpan { + function spanInOpenBraceToken(node: Node): TextSpan | undefined { switch (node.parent.kind) { case SyntaxKind.EnumDeclaration: const enumDeclaration = node.parent; @@ -568,7 +571,7 @@ namespace ts.BreakpointResolver { return spanInNode(node.parent); } - function spanInCloseBraceToken(node: Node): TextSpan { + function spanInCloseBraceToken(node: Node): TextSpan | undefined { switch (node.parent.kind) { case SyntaxKind.ModuleBlock: // If this is not an instantiated module block, no bp span @@ -617,7 +620,7 @@ namespace ts.BreakpointResolver { } } - function spanInCloseBracketToken(node: Node): TextSpan { + function spanInCloseBracketToken(node: Node): TextSpan | undefined { switch (node.parent.kind) { case SyntaxKind.ArrayBindingPattern: // Breakpoint in last binding element or binding pattern if it contains no elements @@ -636,7 +639,7 @@ namespace ts.BreakpointResolver { } } - function spanInOpenParenToken(node: Node): TextSpan { + function spanInOpenParenToken(node: Node): TextSpan | undefined { if (node.parent.kind === SyntaxKind.DoStatement || // Go to while keyword and do action instead node.parent.kind === SyntaxKind.CallExpression || node.parent.kind === SyntaxKind.NewExpression) { @@ -651,7 +654,7 @@ namespace ts.BreakpointResolver { return spanInNode(node.parent); } - function spanInCloseParenToken(node: Node): TextSpan { + function spanInCloseParenToken(node: Node): TextSpan | undefined { // Is this close paren token of parameter list, set span in previous token switch (node.parent.kind) { case SyntaxKind.FunctionExpression: @@ -677,7 +680,7 @@ namespace ts.BreakpointResolver { } } - function spanInColonToken(node: Node): TextSpan { + function spanInColonToken(node: Node): TextSpan | undefined { // Is this : specifying return annotation of the function declaration if (isFunctionLike(node.parent) || node.parent.kind === SyntaxKind.PropertyAssignment || @@ -688,7 +691,7 @@ namespace ts.BreakpointResolver { return spanInNode(node.parent); } - function spanInGreaterThanOrLessThanToken(node: Node): TextSpan { + function spanInGreaterThanOrLessThanToken(node: Node): TextSpan | undefined { if (node.parent.kind === SyntaxKind.TypeAssertionExpression) { return spanInNextNode(node); } @@ -696,7 +699,7 @@ namespace ts.BreakpointResolver { return spanInNode(node.parent); } - function spanInWhileKeyword(node: Node): TextSpan { + function spanInWhileKeyword(node: Node): TextSpan | undefined { if (node.parent.kind === SyntaxKind.DoStatement) { // Set span on while expression return textSpanEndingAtNextToken(node, (node.parent).expression); @@ -706,7 +709,7 @@ namespace ts.BreakpointResolver { return spanInNode(node.parent); } - function spanInOfKeyword(node: Node): TextSpan { + function spanInOfKeyword(node: Node): TextSpan | undefined { if (node.parent.kind === SyntaxKind.ForOfStatement) { // Set using next token return spanInNextNode(node); diff --git a/src/services/classifier.ts b/src/services/classifier.ts index 9719a1ccdad91..5c18eae4aa1ee 100644 --- a/src/services/classifier.ts +++ b/src/services/classifier.ts @@ -300,6 +300,8 @@ namespace ts { case ClassificationType.text: case ClassificationType.parameterName: return TokenClass.Identifier; + default: + return undefined!; // TODO: GH#18217 Debug.assertNever(type); } } @@ -559,6 +561,7 @@ namespace ts { case ClassificationType.jsxAttribute: return ClassificationTypeNames.jsxAttribute; case ClassificationType.jsxText: return ClassificationTypeNames.jsxText; case ClassificationType.jsxAttributeStringLiteralValue: return ClassificationTypeNames.jsxAttributeStringLiteralValue; + default: return undefined!; // TODO: GH#18217 throw Debug.assertNever(type); } } @@ -813,7 +816,7 @@ namespace ts { return true; } - function tryClassifyJsxElementName(token: Node): ClassificationType { + function tryClassifyJsxElementName(token: Node): ClassificationType | undefined { switch (token.parent && token.parent.kind) { case SyntaxKind.JsxOpeningElement: if ((token.parent).tagName === token) { @@ -842,7 +845,7 @@ namespace ts { // for accurate classification, the actual token should be passed in. however, for // cases like 'disabled merge code' classification, we just get the token kind and // classify based on that instead. - function classifyTokenType(tokenKind: SyntaxKind, token?: Node): ClassificationType { + function classifyTokenType(tokenKind: SyntaxKind, token?: Node): ClassificationType | undefined { if (isKeyword(tokenKind)) { return ClassificationType.keyword; } @@ -859,20 +862,21 @@ namespace ts { if (isPunctuation(tokenKind)) { if (token) { + const parent = token.parent; if (tokenKind === SyntaxKind.EqualsToken) { // the '=' in a variable declaration is special cased here. - if (token.parent.kind === SyntaxKind.VariableDeclaration || - token.parent.kind === SyntaxKind.PropertyDeclaration || - token.parent.kind === SyntaxKind.Parameter || - token.parent.kind === SyntaxKind.JsxAttribute) { + if (parent.kind === SyntaxKind.VariableDeclaration || + parent.kind === SyntaxKind.PropertyDeclaration || + parent.kind === SyntaxKind.Parameter || + parent.kind === SyntaxKind.JsxAttribute) { return ClassificationType.operator; } } - if (token.parent.kind === SyntaxKind.BinaryExpression || - token.parent.kind === SyntaxKind.PrefixUnaryExpression || - token.parent.kind === SyntaxKind.PostfixUnaryExpression || - token.parent.kind === SyntaxKind.ConditionalExpression) { + if (parent.kind === SyntaxKind.BinaryExpression || + parent.kind === SyntaxKind.PrefixUnaryExpression || + parent.kind === SyntaxKind.PostfixUnaryExpression || + parent.kind === SyntaxKind.ConditionalExpression) { return ClassificationType.operator; } } @@ -883,7 +887,8 @@ namespace ts { return ClassificationType.numericLiteral; } else if (tokenKind === SyntaxKind.StringLiteral) { - return token.parent.kind === SyntaxKind.JsxAttribute ? ClassificationType.jsxAttributeStringLiteralValue : ClassificationType.stringLiteral; + // TODO: GH#18217 + return token!.parent.kind === SyntaxKind.JsxAttribute ? ClassificationType.jsxAttributeStringLiteralValue : ClassificationType.stringLiteral; } else if (tokenKind === SyntaxKind.RegularExpressionLiteral) { // TODO: we should get another classification type for these literals. @@ -935,7 +940,7 @@ namespace ts { } } - function processElement(element: Node) { + function processElement(element: Node | undefined) { if (!element) { return; } diff --git a/src/services/codefixes/annotateWithTypeFromJSDoc.ts b/src/services/codefixes/annotateWithTypeFromJSDoc.ts index b3fc09b7bc4b2..36664ead4a46f 100644 --- a/src/services/codefixes/annotateWithTypeFromJSDoc.ts +++ b/src/services/codefixes/annotateWithTypeFromJSDoc.ts @@ -73,7 +73,7 @@ namespace ts.codefix { node.kind === SyntaxKind.PropertyDeclaration; } - function transformJSDocType(node: TypeNode): TypeNode | undefined { + function transformJSDocType(node: TypeNode): TypeNode { switch (node.kind) { case SyntaxKind.JSDocAllType: case SyntaxKind.JSDocUnknownType: @@ -91,7 +91,7 @@ namespace ts.codefix { case SyntaxKind.TypeReference: return transformJSDocTypeReference(node as TypeReferenceNode); default: - const visited = visitEachChild(node, transformJSDocType, /*context*/ undefined); + const visited = visitEachChild(node, transformJSDocType, /*context*/ undefined!); // TODO: GH#18217 setEmitFlags(visited, EmitFlags.SingleLine); return visited; } @@ -115,7 +115,7 @@ namespace ts.codefix { function transformJSDocParameter(node: ParameterDeclaration) { const index = node.parent.parameters.indexOf(node); - const isRest = node.type.kind === SyntaxKind.JSDocVariadicType && index === node.parent.parameters.length - 1; + const isRest = node.type!.kind === SyntaxKind.JSDocVariadicType && index === node.parent.parameters.length - 1; // TODO: GH#18217 const name = node.name || (isRest ? "rest" : "arg" + index); const dotdotdot = isRest ? createToken(SyntaxKind.DotDotDotToken) : node.dotDotDotToken; return createParameter(node.decorators, node.modifiers, dotdotdot, name, node.questionToken, visitNode(node.type, transformJSDocType), node.initializer); @@ -158,11 +158,11 @@ namespace ts.codefix { /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, - node.typeArguments[0].kind === SyntaxKind.NumberKeyword ? "n" : "s", + node.typeArguments![0].kind === SyntaxKind.NumberKeyword ? "n" : "s", /*questionToken*/ undefined, - createTypeReferenceNode(node.typeArguments[0].kind === SyntaxKind.NumberKeyword ? "number" : "string", []), + createTypeReferenceNode(node.typeArguments![0].kind === SyntaxKind.NumberKeyword ? "number" : "string", []), /*initializer*/ undefined); - const indexSignature = createTypeLiteralNode([createIndexSignature(/*decorators*/ undefined, /*modifiers*/ undefined, [index], node.typeArguments[1])]); + const indexSignature = createTypeLiteralNode([createIndexSignature(/*decorators*/ undefined, /*modifiers*/ undefined, [index], node.typeArguments![1])]); setEmitFlags(indexSignature, EmitFlags.SingleLine); return indexSignature; } diff --git a/src/services/codefixes/convertFunctionToEs6Class.ts b/src/services/codefixes/convertFunctionToEs6Class.ts index d137785a7e782..cd1baeb14a0c2 100644 --- a/src/services/codefixes/convertFunctionToEs6Class.ts +++ b/src/services/codefixes/convertFunctionToEs6Class.ts @@ -9,12 +9,12 @@ namespace ts.codefix { return [createCodeFixAction(fixId, changes, Diagnostics.Convert_function_to_an_ES2015_class, fixId, Diagnostics.Convert_all_constructor_functions_to_classes)]; }, fixIds: [fixId], - getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, err) => doChange(changes, err.file!, err.start, context.program.getTypeChecker())), + getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, err) => doChange(changes, err.file, err.start, context.program.getTypeChecker())), }); function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, position: number, checker: TypeChecker): void { const deletedNodes: { node: Node, inList: boolean }[] = []; - const ctorSymbol = checker.getSymbolAtLocation(getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false)); + const ctorSymbol = checker.getSymbolAtLocation(getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false))!; if (!ctorSymbol || !(ctorSymbol.flags & (SymbolFlags.Function | SymbolFlags.Variable))) { // Bad input @@ -23,8 +23,8 @@ namespace ts.codefix { const ctorDeclaration = ctorSymbol.valueDeclaration; - let precedingNode: Node; - let newClassDeclaration: ClassDeclaration; + let precedingNode: Node | undefined; + let newClassDeclaration: ClassDeclaration | undefined; switch (ctorDeclaration.kind) { case SyntaxKind.FunctionDeclaration: precedingNode = ctorDeclaration; @@ -36,7 +36,7 @@ namespace ts.codefix { precedingNode = ctorDeclaration.parent.parent; newClassDeclaration = createClassFromVariableDeclaration(ctorDeclaration as VariableDeclaration); if ((ctorDeclaration.parent).declarations.length === 1) { - copyComments(precedingNode, newClassDeclaration, sourceFile); + copyComments(precedingNode, newClassDeclaration!, sourceFile); // TODO: GH#18217 deleteNode(precedingNode); } else { @@ -52,7 +52,7 @@ namespace ts.codefix { copyComments(ctorDeclaration, newClassDeclaration, sourceFile); // Because the preceding node could be touched, we need to insert nodes before delete nodes. - changes.insertNodeAfter(sourceFile, precedingNode, newClassDeclaration); + changes.insertNodeAfter(sourceFile, precedingNode!, newClassDeclaration); for (const { node, inList } of deletedNodes) { if (inList) { changes.deleteNodeInList(sourceFile, node); @@ -99,7 +99,7 @@ namespace ts.codefix { return isFunctionLike(source); } - function createClassElement(symbol: Symbol, modifiers: Modifier[]): ClassElement { + function createClassElement(symbol: Symbol, modifiers: Modifier[] | undefined): ClassElement | undefined { // Right now the only thing we can convert are function expressions, which are marked as methods if (!(symbol.flags & SymbolFlags.Method)) { return; @@ -166,7 +166,7 @@ namespace ts.codefix { } } - function createClassFromVariableDeclaration(node: VariableDeclaration): ClassDeclaration { + function createClassFromVariableDeclaration(node: VariableDeclaration): ClassDeclaration | undefined { const initializer = node.initializer as FunctionExpression; if (!initializer || initializer.kind !== SyntaxKind.FunctionExpression) { return undefined; @@ -181,7 +181,7 @@ namespace ts.codefix { memberElements.unshift(createConstructor(/*decorators*/ undefined, /*modifiers*/ undefined, initializer.parameters, initializer.body)); } - const modifiers = getModifierKindFromSource(precedingNode, SyntaxKind.ExportKeyword); + const modifiers = getModifierKindFromSource(precedingNode!, SyntaxKind.ExportKeyword); const cls = createClassDeclaration(/*decorators*/ undefined, modifiers, node.name, /*typeParameters*/ undefined, /*heritageClauses*/ undefined, memberElements); // Don't call copyComments here because we'll already leave them in place @@ -218,7 +218,7 @@ namespace ts.codefix { }); } - function getModifierKindFromSource(source: Node, kind: SyntaxKind): ReadonlyArray { + function getModifierKindFromSource(source: Node, kind: SyntaxKind): ReadonlyArray | undefined { return filter(source.modifiers, modifier => modifier.kind === kind); } } diff --git a/src/services/codefixes/convertToEs6Module.ts b/src/services/codefixes/convertToEs6Module.ts index 92a14b1d20d33..c0a444b42e0e9 100644 --- a/src/services/codefixes/convertToEs6Module.ts +++ b/src/services/codefixes/convertToEs6Module.ts @@ -5,7 +5,7 @@ namespace ts.codefix { getCodeActions(context) { const { sourceFile, program } = context; const changes = textChanges.ChangeTracker.with(context, changes => { - const moduleExportsChangedToDefault = convertFileToEs6Module(sourceFile, program.getTypeChecker(), changes, program.getCompilerOptions().target); + const moduleExportsChangedToDefault = convertFileToEs6Module(sourceFile, program.getTypeChecker(), changes, program.getCompilerOptions().target!); if (moduleExportsChangedToDefault) { for (const importingFile of program.getSourceFiles()) { fixImportOfModuleExports(importingFile, sourceFile, changes); @@ -170,7 +170,7 @@ namespace ts.codefix { // `const a = require("b").c` --> `import { c as a } from "./b"; return [makeSingleImport(name.text, propertyName, moduleSpecifier)]; default: - Debug.assertNever(name); + return Debug.assertNever(name); } } @@ -265,7 +265,7 @@ namespace ts.codefix { // `module.exports = require("x");` ==> `export * from "x"; export { default } from "x";` const moduleSpecifier = reExported.text; const moduleSymbol = checker.getSymbolAtLocation(reExported); - const exports = moduleSymbol ? moduleSymbol.exports : emptyUnderscoreEscapedMap; + const exports = moduleSymbol ? moduleSymbol.exports! : emptyUnderscoreEscapedMap; return exports.has("export=" as __String) ? [[reExportDefault(moduleSpecifier)], true] : !exports.has("default" as __String) @@ -323,7 +323,7 @@ namespace ts.codefix { function exportConst() { // `exports.x = 0;` --> `export const x = 0;` - return makeConst(modifiers, createIdentifier(name), exported); + return makeConst(modifiers, createIdentifier(name!), exported); // TODO: GH#18217 } } @@ -346,7 +346,7 @@ namespace ts.codefix { const importSpecifiers = mapAllOrFail(name.elements, e => e.dotDotDotToken || e.initializer || e.propertyName && !isIdentifier(e.propertyName) || !isIdentifier(e.name) ? undefined - : makeImportSpecifier(e.propertyName && (e.propertyName as Identifier).text, e.name.text)); + : makeImportSpecifier(e.propertyName && (e.propertyName as Identifier).text, e.name.text)); // tslint:disable-line no-unnecessary-type-assertion (TODO: GH#18217) if (importSpecifiers) { return [makeImport(/*name*/ undefined, importSpecifiers, moduleSpecifier)]; } @@ -366,7 +366,7 @@ namespace ts.codefix { case SyntaxKind.Identifier: return convertSingleIdentifierImport(file, name, moduleSpecifier, changes, checker, identifiers); default: - Debug.assertNever(name); + return Debug.assertNever(name); } } @@ -381,7 +381,7 @@ namespace ts.codefix { // True if there is some non-property use like `x()` or `f(x)`. let needDefaultImport = false; - for (const use of identifiers.original.get(name.text)) { + for (const use of identifiers.original.get(name.text)!) { if (checker.getSymbolAtLocation(use) !== nameSymbol || use === name) { // This was a use of a different symbol with the same name, due to shadowing. Ignore. continue; @@ -468,7 +468,7 @@ namespace ts.codefix { getSynthesizedDeepClones(fn.typeParameters), getSynthesizedDeepClones(fn.parameters), getSynthesizedDeepClone(fn.type), - convertToFunctionBody(getSynthesizedDeepClone(fn.body))); + convertToFunctionBody(getSynthesizedDeepClone(fn.body!))); } function classExpressionToDeclaration(name: string | undefined, additionalModifiers: ReadonlyArray, cls: ClassExpression): ClassDeclaration { diff --git a/src/services/codefixes/fixAddMissingMember.ts b/src/services/codefixes/fixAddMissingMember.ts index c2a8316db379a..2eafb5cdd6f91 100644 --- a/src/services/codefixes/fixAddMissingMember.ts +++ b/src/services/codefixes/fixAddMissingMember.ts @@ -60,7 +60,7 @@ namespace ts.codefix { const { parent } = token; if (!isPropertyAccessExpression(parent)) return undefined; - const leftExpressionType = skipConstraint(checker.getTypeAtLocation(parent.expression)); + const leftExpressionType = skipConstraint(checker.getTypeAtLocation(parent.expression)!); const { symbol } = leftExpressionType; const classDeclaration = symbol && symbol.declarations && find(symbol.declarations, isClassLike); if (!classDeclaration) return undefined; @@ -84,7 +84,7 @@ namespace ts.codefix { if (classDeclaration.kind === SyntaxKind.ClassExpression) { return; } - const className = classDeclaration.name.getText(); + const className = classDeclaration.name!.getText(); const staticInitialization = initializePropertyToUndefined(createIdentifier(className), tokenName); changeTracker.insertNodeAfter(classDeclarationSourceFile, classDeclaration, staticInitialization); } @@ -109,11 +109,11 @@ namespace ts.codefix { } function getTypeNode(checker: TypeChecker, classDeclaration: ClassLikeDeclaration, token: Node) { - let typeNode: TypeNode; + let typeNode: TypeNode | undefined; if (token.parent.parent.kind === SyntaxKind.BinaryExpression) { const binaryExpression = token.parent.parent as BinaryExpression; const otherExpression = token.parent === binaryExpression.left ? binaryExpression.right : binaryExpression.left; - const widenedType = checker.getWidenedType(checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(otherExpression))); + const widenedType = checker.getWidenedType(checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(otherExpression)!)); // TODO: GH#18217 typeNode = checker.typeToTypeNode(widenedType, classDeclaration); } return typeNode || createKeywordTypeNode(SyntaxKind.AnyKeyword); diff --git a/src/services/codefixes/fixAddModuleReferTypeMissingTypeof.ts b/src/services/codefixes/fixAddModuleReferTypeMissingTypeof.ts index 15d282342eafe..ac79c29fde2a7 100644 --- a/src/services/codefixes/fixAddModuleReferTypeMissingTypeof.ts +++ b/src/services/codefixes/fixAddModuleReferTypeMissingTypeof.ts @@ -13,7 +13,7 @@ namespace ts.codefix { }, fixIds: [fixId], getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => - doChange(changes, context.sourceFile, getImportTypeNode(diag.file, diag.start!))), + doChange(changes, context.sourceFile, getImportTypeNode(diag.file, diag.start))), }); function getImportTypeNode(sourceFile: SourceFile, pos: number): ImportTypeNode { diff --git a/src/services/codefixes/fixAwaitInSyncFunction.ts b/src/services/codefixes/fixAwaitInSyncFunction.ts index fd00498573c76..fd990aebcd4c2 100644 --- a/src/services/codefixes/fixAwaitInSyncFunction.ts +++ b/src/services/codefixes/fixAwaitInSyncFunction.ts @@ -56,7 +56,7 @@ namespace ts.codefix { return; } - return { + return insertBefore && { insertBefore, returnType: getReturnType(containingFunction) }; @@ -65,7 +65,7 @@ namespace ts.codefix { function doChange( changes: textChanges.ChangeTracker, sourceFile: SourceFile, - { insertBefore, returnType }: { insertBefore: Node | undefined, returnType: TypeNode | undefined }): void { + { insertBefore, returnType }: { insertBefore: Node, returnType: TypeNode | undefined }): void { if (returnType) { const entityName = getEntityNameFromTypeNode(returnType); diff --git a/src/services/codefixes/fixCannotFindModule.ts b/src/services/codefixes/fixCannotFindModule.ts index fec421171d077..78532f152723a 100644 --- a/src/services/codefixes/fixCannotFindModule.ts +++ b/src/services/codefixes/fixCannotFindModule.ts @@ -32,6 +32,6 @@ namespace ts.codefix { const { packageName } = getPackageName(moduleName); return diagCode === errorCodeCannotFindModule ? (JsTyping.nodeCoreModules.has(packageName) ? "@types/node" : undefined) - : (host.isKnownTypesPackageName(packageName) ? getTypesPackageName(packageName) : undefined); + : (host.isKnownTypesPackageName!(packageName) ? getTypesPackageName(packageName) : undefined); // TODO: GH#18217 } } diff --git a/src/services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts b/src/services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts index d59df7a02b302..95de8857eb2f8 100644 --- a/src/services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts +++ b/src/services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts @@ -33,8 +33,8 @@ namespace ts.codefix { } function addMissingMembers(classDeclaration: ClassLikeDeclaration, sourceFile: SourceFile, checker: TypeChecker, changeTracker: textChanges.ChangeTracker, preferences: UserPreferences): void { - const extendsNode = getClassExtendsHeritageClauseElement(classDeclaration); - const instantiatedExtendsType = checker.getTypeAtLocation(extendsNode); + const extendsNode = getClassExtendsHeritageClauseElement(classDeclaration)!; + const instantiatedExtendsType = checker.getTypeAtLocation(extendsNode)!; // Note that this is ultimately derived from a map indexed by symbol names, // so duplicates cannot occur. @@ -46,7 +46,7 @@ namespace ts.codefix { function symbolPointsToNonPrivateAndAbstractMember(symbol: Symbol): boolean { // See `codeFixClassExtendAbstractProtectedProperty.ts` in https://github.com/Microsoft/TypeScript/pull/11547/files // (now named `codeFixClassExtendAbstractPrivateProperty.ts`) - const flags = getModifierFlags(first(symbol.getDeclarations())); + const flags = getModifierFlags(first(symbol.getDeclarations()!)); return !(flags & ModifierFlags.Private) && !!(flags & ModifierFlags.Abstract); } } diff --git a/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts b/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts index 0da45c46873dd..29567db03d50d 100644 --- a/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts +++ b/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts @@ -20,7 +20,7 @@ namespace ts.codefix { return codeFixAll(context, errorCodes, (changes, diag) => { const classDeclaration = getClass(diag.file, diag.start); if (addToSeen(seenClassDeclarations, getNodeId(classDeclaration))) { - for (const implementedTypeNode of getClassImplementsHeritageClauseElements(classDeclaration)) { + for (const implementedTypeNode of getClassImplementsHeritageClauseElements(classDeclaration)!) { addMissingDeclarations(context.program.getTypeChecker(), implementedTypeNode, diag.file, classDeclaration, changes, context.preferences); } } @@ -46,7 +46,7 @@ namespace ts.codefix { const implementedTypeSymbols = checker.getPropertiesOfType(implementedType); const nonPrivateMembers = implementedTypeSymbols.filter(symbol => !(getModifierFlags(symbol.valueDeclaration) & ModifierFlags.Private)); - const classType = checker.getTypeAtLocation(classDeclaration); + const classType = checker.getTypeAtLocation(classDeclaration)!; if (!classType.getNumberIndexType()) { createMissingIndexSignatureDeclaration(implementedType, IndexKind.Number); @@ -60,7 +60,7 @@ namespace ts.codefix { function createMissingIndexSignatureDeclaration(type: InterfaceType, kind: IndexKind): void { const indexInfoOfKind = checker.getIndexInfoOfType(type, kind); if (indexInfoOfKind) { - changeTracker.insertNodeAtClassStart(sourceFile, classDeclaration, checker.indexInfoToIndexSignatureDeclaration(indexInfoOfKind, kind, classDeclaration)); + changeTracker.insertNodeAtClassStart(sourceFile, classDeclaration, checker.indexInfoToIndexSignatureDeclaration(indexInfoOfKind, kind, classDeclaration)!); } } } diff --git a/src/services/codefixes/fixClassSuperMustPrecedeThisAccess.ts b/src/services/codefixes/fixClassSuperMustPrecedeThisAccess.ts index 2f7daf93dc735..6a68b9b600488 100644 --- a/src/services/codefixes/fixClassSuperMustPrecedeThisAccess.ts +++ b/src/services/codefixes/fixClassSuperMustPrecedeThisAccess.ts @@ -32,11 +32,11 @@ namespace ts.codefix { changes.deleteNode(sourceFile, superCall); } - function getNodes(sourceFile: SourceFile, pos: number): { readonly constructor: ConstructorDeclaration, readonly superCall: ExpressionStatement } { + function getNodes(sourceFile: SourceFile, pos: number): { readonly constructor: ConstructorDeclaration, readonly superCall: ExpressionStatement } | undefined { const token = getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); if (token.kind !== SyntaxKind.ThisKeyword) return undefined; const constructor = getContainingFunction(token) as ConstructorDeclaration; - const superCall = findSuperCall(constructor.body); + const superCall = findSuperCall(constructor.body!); // figure out if the `this` access is actually inside the supercall // i.e. super(this.a), since in that case we won't suggest a fix return superCall && !superCall.expression.arguments.some(arg => isPropertyAccessExpression(arg) && arg.expression === token) ? { constructor, superCall } : undefined; diff --git a/src/services/codefixes/fixExtendsInterfaceBecomesImplements.ts b/src/services/codefixes/fixExtendsInterfaceBecomesImplements.ts index 4320513fb617c..c2c040b42adf0 100644 --- a/src/services/codefixes/fixExtendsInterfaceBecomesImplements.ts +++ b/src/services/codefixes/fixExtendsInterfaceBecomesImplements.ts @@ -21,8 +21,8 @@ namespace ts.codefix { function getNodes(sourceFile: SourceFile, pos: number) { const token = getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); - const heritageClauses = getContainingClass(token)!.heritageClauses; - const extendsToken = heritageClauses[0].getFirstToken(); + const heritageClauses = getContainingClass(token)!.heritageClauses!; + const extendsToken = heritageClauses[0].getFirstToken()!; return extendsToken.kind === SyntaxKind.ExtendsKeyword ? { extendsToken, heritageClauses } : undefined; } diff --git a/src/services/codefixes/fixForgottenThisPropertyAccess.ts b/src/services/codefixes/fixForgottenThisPropertyAccess.ts index ce066277a27e2..82954673d4fe7 100644 --- a/src/services/codefixes/fixForgottenThisPropertyAccess.ts +++ b/src/services/codefixes/fixForgottenThisPropertyAccess.ts @@ -19,7 +19,8 @@ namespace ts.codefix { }, fixIds: [fixId], getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => { - doChange(changes, context.sourceFile, getInfo(diag.file, diag.start, diag.code)); + const info = getInfo(diag.file, diag.start, diag.code); + if (info) doChange(changes, context.sourceFile, info); }), }); @@ -27,7 +28,7 @@ namespace ts.codefix { function getInfo(sourceFile: SourceFile, pos: number, diagCode: number): Info | undefined { const node = getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); if (!isIdentifier(node)) return undefined; - return { node, className: diagCode === didYouMeanStaticMemberCode ? getContainingClass(node).name.text : undefined }; + return { node, className: diagCode === didYouMeanStaticMemberCode ? getContainingClass(node)!.name!.text : undefined }; } function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, { node, className }: Info): void { diff --git a/src/services/codefixes/fixInvalidImportSyntax.ts b/src/services/codefixes/fixInvalidImportSyntax.ts index 89a9aca461cb5..192375791ce08 100644 --- a/src/services/codefixes/fixInvalidImportSyntax.ts +++ b/src/services/codefixes/fixInvalidImportSyntax.ts @@ -64,12 +64,12 @@ namespace ts.codefix { return []; } const expr = node.expression; - const type = context.program.getTypeChecker().getTypeAtLocation(expr); + const type = context.program.getTypeChecker().getTypeAtLocation(expr)!; // TODO: GH#18217 if (!(type.symbol && (type.symbol as TransientSymbol).originatingImport)) { return []; } const fixes: CodeFixAction[] = []; - const relatedImport = (type.symbol as TransientSymbol).originatingImport; + const relatedImport = (type.symbol as TransientSymbol).originatingImport!; // TODO: GH#18217 if (!isImportCall(relatedImport)) { addRange(fixes, getCodeFixesForImportDeclaration(context, relatedImport)); } diff --git a/src/services/codefixes/fixJSDocTypes.ts b/src/services/codefixes/fixJSDocTypes.ts index 1919b0742f020..043ed018aa7d8 100644 --- a/src/services/codefixes/fixJSDocTypes.ts +++ b/src/services/codefixes/fixJSDocTypes.ts @@ -30,7 +30,7 @@ namespace ts.codefix { const { fixId, program, sourceFile } = context; const checker = program.getTypeChecker(); return codeFixAll(context, errorCodes, (changes, err) => { - const info = getInfo(err.file, err.start!, checker); + const info = getInfo(err.file, err.start, checker); if (!info) return; const { typeNode, type } = info; const fixedType = typeNode.kind === SyntaxKind.JSDocNullableType && fixId === fixIdNullable ? checker.getNullableType(type, TypeFlags.Undefined) : type; @@ -40,10 +40,10 @@ namespace ts.codefix { }); function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, oldTypeNode: TypeNode, newType: Type, checker: TypeChecker): void { - changes.replaceNode(sourceFile, oldTypeNode, checker.typeToTypeNode(newType, /*enclosingDeclaration*/ oldTypeNode)); + changes.replaceNode(sourceFile, oldTypeNode, checker.typeToTypeNode(newType, /*enclosingDeclaration*/ oldTypeNode)!); // TODO: GH#18217 } - function getInfo(sourceFile: SourceFile, pos: number, checker: TypeChecker): { readonly typeNode: TypeNode, type: Type } { + function getInfo(sourceFile: SourceFile, pos: number, checker: TypeChecker): { readonly typeNode: TypeNode, readonly type: Type } | undefined { const decl = findAncestor(getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false), isTypeContainer); const typeNode = decl && decl.type; return typeNode && { typeNode, type: checker.getTypeFromTypeNode(typeNode) }; diff --git a/src/services/codefixes/fixSpelling.ts b/src/services/codefixes/fixSpelling.ts index dbb23c3ac09dd..6986e161f4aa5 100644 --- a/src/services/codefixes/fixSpelling.ts +++ b/src/services/codefixes/fixSpelling.ts @@ -14,14 +14,14 @@ namespace ts.codefix { if (!info) return undefined; const { node, suggestion } = info; const { target } = context.host.getCompilationSettings(); - const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, node, suggestion, target)); + const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, node, suggestion, target!)); return [createCodeFixAction("spelling", changes, [Diagnostics.Change_spelling_to_0, suggestion], fixId, Diagnostics.Fix_all_detected_spelling_errors)]; }, fixIds: [fixId], getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => { const info = getInfo(diag.file, diag.start, context); const { target } = context.host.getCompilationSettings(); - if (info) doChange(changes, context.sourceFile, info.node, info.suggestion, target); + if (info) doChange(changes, context.sourceFile, info.node, info.suggestion, target!); }), }); @@ -32,15 +32,15 @@ namespace ts.codefix { const node = getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); // TODO: GH#15852 const checker = context.program.getTypeChecker(); - let suggestion: string; + let suggestion: string | undefined; if (isPropertyAccessExpression(node.parent) && node.parent.name === node) { Debug.assert(node.kind === SyntaxKind.Identifier); - const containingType = checker.getTypeAtLocation(node.parent.expression); + const containingType = checker.getTypeAtLocation(node.parent.expression)!; suggestion = checker.getSuggestionForNonexistentProperty(node as Identifier, containingType); } else if (isImportSpecifier(node.parent) && node.parent.name === node) { Debug.assert(node.kind === SyntaxKind.Identifier); - const importDeclaration = findAncestor(node, isImportDeclaration); + const importDeclaration = findAncestor(node, isImportDeclaration)!; const resolvedSourceFile = getResolvedSourceFileFromImportDeclaration(sourceFile, context, importDeclaration); if (resolvedSourceFile && resolvedSourceFile.symbol) { suggestion = checker.getSuggestionForNonexistentModule(node as Identifier, resolvedSourceFile.symbol); diff --git a/src/services/codefixes/fixStrictClassInitialization.ts b/src/services/codefixes/fixStrictClassInitialization.ts index 6c211b86f8d46..40a26da204abe 100644 --- a/src/services/codefixes/fixStrictClassInitialization.ts +++ b/src/services/codefixes/fixStrictClassInitialization.ts @@ -77,8 +77,9 @@ namespace ts.codefix { function addUndefinedType(changeTracker: textChanges.ChangeTracker, propertyDeclarationSourceFile: SourceFile, propertyDeclaration: PropertyDeclaration): void { const undefinedTypeNode = createKeywordTypeNode(SyntaxKind.UndefinedKeyword); - const types = isUnionTypeNode(propertyDeclaration.type) ? propertyDeclaration.type.types.concat(undefinedTypeNode) : [propertyDeclaration.type, undefinedTypeNode]; - changeTracker.replaceNode(propertyDeclarationSourceFile, propertyDeclaration.type, createUnionTypeNode(types)); + const type = propertyDeclaration.type!; // TODO: GH#18217 + const types = isUnionTypeNode(type) ? type.types.concat(undefinedTypeNode) : [type, undefinedTypeNode]; + changeTracker.replaceNode(propertyDeclarationSourceFile, type, createUnionTypeNode(types)); } function getActionForAddMissingInitializer(context: CodeFixContext, propertyDeclaration: PropertyDeclaration): CodeFixAction | undefined { @@ -104,7 +105,7 @@ namespace ts.codefix { } function getInitializer(checker: TypeChecker, propertyDeclaration: PropertyDeclaration): Expression | undefined { - return getDefaultValueFromType(checker, checker.getTypeFromTypeNode(propertyDeclaration.type)); + return getDefaultValueFromType(checker, checker.getTypeFromTypeNode(propertyDeclaration.type!)); // TODO: GH#18217 } function getDefaultValueFromType (checker: TypeChecker, type: Type): Expression | undefined { diff --git a/src/services/codefixes/fixUnreachableCode.ts b/src/services/codefixes/fixUnreachableCode.ts index 96241c2263c6d..aed55f96f2ad6 100644 --- a/src/services/codefixes/fixUnreachableCode.ts +++ b/src/services/codefixes/fixUnreachableCode.ts @@ -14,7 +14,7 @@ namespace ts.codefix { function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, start: number): void { const token = getTokenAtPosition(sourceFile, start, /*includeJsDocComment*/ false); - const statement = findAncestor(token, isStatement); + const statement = findAncestor(token, isStatement)!; Debug.assert(statement.getStart(sourceFile) === token.getStart(sourceFile)); const container = (isBlock(statement.parent) ? statement.parent : statement).parent; @@ -60,6 +60,8 @@ namespace ts.codefix { return getModuleInstanceState(s as ModuleDeclaration) !== ModuleInstanceState.Instantiated; case SyntaxKind.EnumDeclaration: return hasModifier(s, ModifierFlags.Const); + default: + return false; } } diff --git a/src/services/codefixes/fixUnusedIdentifier.ts b/src/services/codefixes/fixUnusedIdentifier.ts index 6ba592ca2b8b5..dffcbac91ab65 100644 --- a/src/services/codefixes/fixUnusedIdentifier.ts +++ b/src/services/codefixes/fixUnusedIdentifier.ts @@ -53,7 +53,7 @@ namespace ts.codefix { return codeFixAll(context, errorCodes, (changes, diag) => { const { sourceFile } = context; const startToken = getTokenAtPosition(sourceFile, diag.start, /*includeJsDocComment*/ false); - const token = findPrecedingToken(textSpanEnd(diag), diag.file); + const token = findPrecedingToken(textSpanEnd(diag), diag.file)!; switch (context.fixId) { case fixIdPrefix: if (isIdentifier(token) && canPrefix(token)) { @@ -116,9 +116,9 @@ namespace ts.codefix { } function getToken(sourceFile: SourceFile, pos: number): Node { - const token = findPrecedingToken(pos, sourceFile, /*startNode*/ undefined, /*includeJsDoc*/ true); + const token = findPrecedingToken(pos, sourceFile, /*startNode*/ undefined, /*includeJsDoc*/ true)!; // this handles var ["computed"] = 12; - return token.kind === SyntaxKind.CloseBracketToken ? findPrecedingToken(pos - 1, sourceFile) : token; + return token.kind === SyntaxKind.CloseBracketToken ? findPrecedingToken(pos - 1, sourceFile)! : token; } function tryPrefixDeclaration(changes: textChanges.ChangeTracker, errorCode: number, sourceFile: SourceFile, token: Node): void { @@ -208,7 +208,7 @@ namespace ts.codefix { oldFunction, oldFunction.modifiers, oldFunction.typeParameters, - /*parameters*/ undefined, + /*parameters*/ undefined!, // TODO: GH#18217 oldFunction.type, oldFunction.equalsGreaterThanToken, oldFunction.body); @@ -242,7 +242,7 @@ namespace ts.codefix { // handle case where 'import a = A;' case SyntaxKind.ImportEqualsDeclaration: - const importEquals = getAncestor(identifier, SyntaxKind.ImportEqualsDeclaration); + const importEquals = getAncestor(identifier, SyntaxKind.ImportEqualsDeclaration)!; changes.deleteNode(sourceFile, importEquals); break; @@ -264,15 +264,15 @@ namespace ts.codefix { } else { // import |d,| * as ns from './file' - const start = importClause.name.getStart(sourceFile); - const nextToken = getTokenAtPosition(sourceFile, importClause.name.end, /*includeJsDocComment*/ false); + const start = importClause.name!.getStart(sourceFile); + const nextToken = getTokenAtPosition(sourceFile, importClause.name!.end, /*includeJsDocComment*/ false); if (nextToken && nextToken.kind === SyntaxKind.CommaToken) { // shift first non-whitespace position after comma to the start position of the node const end = skipTrivia(sourceFile.text, nextToken.end, /*stopAfterLineBreaks*/ false, /*stopAtComments*/ true); changes.deleteRange(sourceFile, { pos: start, end }); } else { - changes.deleteNode(sourceFile, importClause.name); + changes.deleteNode(sourceFile, importClause.name!); } } break; @@ -301,7 +301,7 @@ namespace ts.codefix { // Delete the entire import declaration // |import * as ns from './file'| // |import { a } from './file'| - const importDecl = getAncestor(namedBindings, SyntaxKind.ImportDeclaration); + const importDecl = getAncestor(namedBindings, SyntaxKind.ImportDeclaration)!; changes.deleteNode(sourceFile, importDecl); } } diff --git a/src/services/codefixes/helpers.ts b/src/services/codefixes/helpers.ts index cd3c5339a2961..5d033a82cb312 100644 --- a/src/services/codefixes/helpers.ts +++ b/src/services/codefixes/helpers.ts @@ -7,7 +7,7 @@ namespace ts.codefix { * @returns Empty string iff there are no member insertions. */ export function createMissingMemberNodes(classDeclaration: ClassLikeDeclaration, possiblyMissingSymbols: ReadonlyArray, checker: TypeChecker, preferences: UserPreferences, out: (node: ClassElement) => void): void { - const classMembers = classDeclaration.symbol.members; + const classMembers = classDeclaration.symbol.members!; for (const symbol of possiblyMissingSymbols) { if (!classMembers.has(symbol.escapedName)) { addNewNodeForMemberSymbol(symbol, classDeclaration, checker, preferences, out); @@ -72,7 +72,7 @@ namespace ts.codefix { } if (declarations.length > signatures.length) { - const signature = checker.getSignatureFromDeclaration(declarations[declarations.length - 1] as SignatureDeclaration); + const signature = checker.getSignatureFromDeclaration(declarations[declarations.length - 1] as SignatureDeclaration)!; outputMethod(signature, modifiers, name, createStubbedMethodBody(preferences)); } else { @@ -82,13 +82,21 @@ namespace ts.codefix { break; } - function outputMethod(signature: Signature, modifiers: NodeArray, name: PropertyName, body?: Block): void { + function outputMethod(signature: Signature, modifiers: NodeArray | undefined, name: PropertyName, body?: Block): void { const method = signatureToMethodDeclaration(checker, signature, enclosingDeclaration, modifiers, name, optional, body); if (method) out(method); } } - function signatureToMethodDeclaration(checker: TypeChecker, signature: Signature, enclosingDeclaration: ClassLikeDeclaration, modifiers: NodeArray, name: PropertyName, optional: boolean, body: Block | undefined) { + function signatureToMethodDeclaration( + checker: TypeChecker, + signature: Signature, + enclosingDeclaration: ClassLikeDeclaration, + modifiers: NodeArray | undefined, + name: PropertyName, + optional: boolean, + body: Block | undefined, + ): MethodDeclaration | undefined { const signatureDeclaration = checker.signatureToSignatureDeclaration(signature, SyntaxKind.MethodDeclaration, enclosingDeclaration, NodeBuilderFlags.SuppressAnyReturnType); if (!signatureDeclaration) { return undefined; @@ -116,7 +124,7 @@ namespace ts.codefix { methodName, /*questionToken*/ undefined, /*typeParameters*/ inJs ? undefined : map(typeArguments, (_, i) => - createTypeParameterDeclaration(CharacterCodes.T + typeArguments.length - 1 <= CharacterCodes.Z ? String.fromCharCode(CharacterCodes.T + i) : `T${i}`)), + createTypeParameterDeclaration(CharacterCodes.T + typeArguments!.length - 1 <= CharacterCodes.Z ? String.fromCharCode(CharacterCodes.T + i) : `T${i}`)), /*parameters*/ createDummyParameters(args.length, /*names*/ undefined, /*minArgumentCount*/ undefined, inJs), /*type*/ inJs ? undefined : createKeywordTypeNode(SyntaxKind.AnyKeyword), createStubbedMethodBody(preferences)); @@ -190,7 +198,7 @@ namespace ts.codefix { } function createStubbedMethod( - modifiers: ReadonlyArray, + modifiers: ReadonlyArray | undefined, name: PropertyName, optional: boolean, typeParameters: ReadonlyArray | undefined, diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index eaa0a7c0611d6..01fbc26403fd5 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -25,7 +25,7 @@ namespace ts.codefix { } interface ImportCodeFixContext extends SymbolContext { - symbolToken: Node; + symbolToken: Node | undefined; program: Program; checker: TypeChecker; compilerOptions: CompilerOptions; @@ -148,8 +148,8 @@ namespace ts.codefix { for (const { declaration } of existingImports) { const namespace = getNamespaceImportName(declaration); if (namespace) { - const moduleSymbol = context.checker.getAliasedSymbol(context.checker.getSymbolAtLocation(namespace)); - if (moduleSymbol && moduleSymbol.exports.has(escapeLeadingUnderscores(context.symbolName))) { + const moduleSymbol = context.checker.getAliasedSymbol(context.checker.getSymbolAtLocation(namespace)!); + if (moduleSymbol && moduleSymbol.exports!.has(escapeLeadingUnderscores(context.symbolName))) { useExisting.push(getCodeActionForUseExistingNamespaceImport(namespace.text, context, context.symbolToken)); } } @@ -263,7 +263,7 @@ namespace ts.codefix { ): void { const fromExistingImport = firstDefined(existingImports, ({ declaration, importKind }) => { if (declaration.kind === SyntaxKind.ImportDeclaration && declaration.importClause) { - const changes = tryUpdateExistingImport(ctx, isImportClause(declaration.importClause) && declaration.importClause || undefined, importKind); + const changes = tryUpdateExistingImport(ctx, (isImportClause(declaration.importClause) && declaration.importClause || undefined)!, importKind); // TODO: GH#18217 if (changes) { const moduleSpecifierWithoutQuotes = stripQuotes(declaration.moduleSpecifier.getText()); return createCodeAction(Diagnostics.Add_0_to_existing_import_declaration_from_1, [ctx.symbolName, moduleSpecifierWithoutQuotes], changes); @@ -296,7 +296,7 @@ namespace ts.codefix { function tryUpdateExistingImport(context: SymbolContext, importClause: ImportClause | ImportEqualsDeclaration, importKind: ImportKind): FileTextChanges[] | undefined { const { symbolName, sourceFile } = context; const { name } = importClause; - const { namedBindings } = importClause.kind !== SyntaxKind.ImportEqualsDeclaration && importClause; + const { namedBindings } = (importClause.kind !== SyntaxKind.ImportEqualsDeclaration && importClause) as ImportClause; // TODO: GH#18217 switch (importKind) { case ImportKind.Default: return name ? undefined : ChangeTracker.with(context, t => @@ -348,13 +348,13 @@ namespace ts.codefix { return createCodeAction(Diagnostics.Change_0_to_1, [symbolName, `${namespacePrefix}.${symbolName}`], changes); } - function getImportCodeActions(context: CodeFixContext): CodeFixAction[] { + function getImportCodeActions(context: CodeFixContext): CodeFixAction[] | undefined { return context.errorCode === Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead.code ? getActionsForUMDImport(context) : getActionsForNonUMDImport(context); } - function getActionsForUMDImport(context: CodeFixContext): CodeFixAction[] { + function getActionsForUMDImport(context: CodeFixContext): CodeFixAction[] | undefined { const token = getTokenAtPosition(context.sourceFile, context.span.start, /*includeJsDocComment*/ false); const checker = context.program.getTypeChecker(); @@ -376,10 +376,10 @@ namespace ts.codefix { } if (isUMDExportSymbol(umdSymbol)) { - const symbol = checker.getAliasedSymbol(umdSymbol); + const symbol = checker.getAliasedSymbol(umdSymbol!); if (symbol) { return getCodeActionsForImport([{ moduleSymbol: symbol, importKind: getUmdImportKind(context.program.getCompilerOptions()) }], - convertToImportCodeFixContext(context, token, umdSymbol.name)); + convertToImportCodeFixContext(context, token, umdSymbol!.name)); } } @@ -443,7 +443,7 @@ namespace ts.codefix { if (( localSymbol && localSymbol.escapedName === symbolName || getEscapedNameForExportDefault(defaultExport) === symbolName || - moduleSymbolToValidIdentifier(moduleSymbol, program.getCompilerOptions().target) === symbolName + moduleSymbolToValidIdentifier(moduleSymbol, program.getCompilerOptions().target!) === symbolName ) && checkSymbolHasMeaning(localSymbol || defaultExport, currentTokenMeaning)) { addSymbol(moduleSymbol, localSymbol || defaultExport, ImportKind.Default); } @@ -456,7 +456,7 @@ namespace ts.codefix { } function getEscapedNameForExportDefault(symbol: Symbol): __String | undefined { - return firstDefined(symbol.declarations, declaration => { + return symbol.declarations && firstDefined(symbol.declarations, declaration => { if (isExportAssignment(declaration)) { if (isIdentifier(declaration.expression)) { return declaration.expression.escapedText; diff --git a/src/services/codefixes/inferFromUsage.ts b/src/services/codefixes/inferFromUsage.ts index 92f4ab05e3c8b..c58c001b403ee 100644 --- a/src/services/codefixes/inferFromUsage.ts +++ b/src/services/codefixes/inferFromUsage.ts @@ -31,17 +31,17 @@ namespace ts.codefix { } const token = getTokenAtPosition(sourceFile, start, /*includeJsDocComment*/ false); - let declaration!: Declaration; + let declaration!: Declaration | undefined; const changes = textChanges.ChangeTracker.with(context, changes => { declaration = doChange(changes, sourceFile, token, errorCode, program, cancellationToken, /*markSeenseen*/ returnTrue); }); return changes.length === 0 ? undefined - : [createCodeFixAction(fixId, changes, [getDiagnostic(errorCode, token), getNameOfDeclaration(declaration).getText(sourceFile)], fixId, Diagnostics.Infer_all_types_from_usage)]; + : [createCodeFixAction(fixId, changes, [getDiagnostic(errorCode, token), getNameOfDeclaration(declaration!).getText(sourceFile)], fixId, Diagnostics.Infer_all_types_from_usage)]; }, fixIds: [fixId], getAllCodeActions(context) { const { sourceFile, program, cancellationToken } = context; const markSeen = nodeSeenTracker(); return codeFixAll(context, errorCodes, (changes, err) => { - doChange(changes, sourceFile, getTokenAtPosition(err.file!, err.start!, /*includeJsDocComment*/ false), err.code, program, cancellationToken, markSeen); + doChange(changes, sourceFile, getTokenAtPosition(err.file, err.start, /*includeJsDocComment*/ false), err.code, program, cancellationToken, markSeen); }); }, }); @@ -49,7 +49,7 @@ namespace ts.codefix { function getDiagnostic(errorCode: number, token: Node): DiagnosticMessage { switch (errorCode) { case Diagnostics.Parameter_0_implicitly_has_an_1_type.code: - return isSetAccessor(getContainingFunction(token)) ? Diagnostics.Infer_type_of_0_from_usage : Diagnostics.Infer_parameter_types_from_usage; + return isSetAccessor(getContainingFunction(token)!) ? Diagnostics.Infer_type_of_0_from_usage : Diagnostics.Infer_parameter_types_from_usage; // TODO: GH#18217 case Diagnostics.Rest_parameter_0_implicitly_has_an_any_type.code: return Diagnostics.Infer_parameter_types_from_usage; default: @@ -182,7 +182,8 @@ namespace ts.codefix { const notAccessible = () => { typeIsAccessible = false; }; const res = checker.typeToTypeNode(type, enclosingScope, /*flags*/ undefined, { trackSymbol: (symbol, declaration, meaning) => { - typeIsAccessible = typeIsAccessible && checker.isSymbolAccessible(symbol, declaration, meaning, /*shouldComputeAliasToMarkVisible*/ false).accessibility === SymbolAccessibility.Accessible; + // TODO: GH#18217 + typeIsAccessible = typeIsAccessible && checker.isSymbolAccessible(symbol, declaration, meaning!, /*shouldComputeAliasToMarkVisible*/ false).accessibility === SymbolAccessibility.Accessible; }, reportInaccessibleThisError: notAccessible, reportPrivateInBaseOfClassExpression: notAccessible, @@ -399,7 +400,7 @@ namespace ts.codefix { case SyntaxKind.LessThanEqualsToken: case SyntaxKind.GreaterThanToken: case SyntaxKind.GreaterThanEqualsToken: - const operandType = checker.getTypeAtLocation(parent.left === node ? parent.right : parent.left); + const operandType = checker.getTypeAtLocation(parent.left === node ? parent.right : parent.left)!; if (operandType.flags & TypeFlags.EnumLike) { addCandidateType(usageContext, operandType); } @@ -410,7 +411,7 @@ namespace ts.codefix { case SyntaxKind.PlusEqualsToken: case SyntaxKind.PlusToken: - const otherOperandType = checker.getTypeAtLocation(parent.left === node ? parent.right : parent.left); + const otherOperandType = checker.getTypeAtLocation(parent.left === node ? parent.right : parent.left)!; if (otherOperandType.flags & TypeFlags.EnumLike) { addCandidateType(usageContext, otherOperandType); } @@ -470,7 +471,7 @@ namespace ts.codefix { if (parent.arguments) { for (const argument of parent.arguments) { - callContext.argumentTypes.push(checker.getTypeAtLocation(argument)); + callContext.argumentTypes.push(checker.getTypeAtLocation(argument)!); } } @@ -499,7 +500,7 @@ namespace ts.codefix { return; } else { - const indexType = checker.getTypeAtLocation(parent); + const indexType = checker.getTypeAtLocation(parent)!; const indexUsageContext = {}; inferTypeFromContext(parent, checker, indexUsageContext); if (indexType.flags & TypeFlags.NumberLike) { @@ -525,19 +526,19 @@ namespace ts.codefix { return checker.getWidenedType(checker.getUnionType(usageContext.candidateTypes.map(t => checker.getBaseTypeOfLiteralType(t)), UnionReduction.Subtype)); } else if (usageContext.properties && hasCallContext(usageContext.properties.get("then" as __String))) { - const paramType = getParameterTypeFromCallContexts(0, usageContext.properties.get("then" as __String).callContexts, /*isRestParameter*/ false, checker); + const paramType = getParameterTypeFromCallContexts(0, usageContext.properties.get("then" as __String)!.callContexts!, /*isRestParameter*/ false, checker)!; // TODO: GH#18217 const types = paramType.getCallSignatures().map(c => c.getReturnType()); return checker.createPromiseType(types.length ? checker.getUnionType(types, UnionReduction.Subtype) : checker.getAnyType()); } else if (usageContext.properties && hasCallContext(usageContext.properties.get("push" as __String))) { - return checker.createArrayType(getParameterTypeFromCallContexts(0, usageContext.properties.get("push" as __String).callContexts, /*isRestParameter*/ false, checker)); + return checker.createArrayType(getParameterTypeFromCallContexts(0, usageContext.properties.get("push" as __String)!.callContexts!, /*isRestParameter*/ false, checker)!); } else if (usageContext.properties || usageContext.callContexts || usageContext.constructContexts || usageContext.numberIndexContext || usageContext.stringIndexContext) { const members = createUnderscoreEscapedMap(); const callSignatures: Signature[] = []; const constructSignatures: Signature[] = []; - let stringIndexInfo: IndexInfo; - let numberIndexInfo: IndexInfo; + let stringIndexInfo: IndexInfo | undefined; + let numberIndexInfo: IndexInfo | undefined; if (usageContext.properties) { usageContext.properties.forEach((context, name) => { @@ -560,14 +561,14 @@ namespace ts.codefix { } if (usageContext.numberIndexContext) { - numberIndexInfo = checker.createIndexInfo(getTypeFromUsageContext(usageContext.numberIndexContext, checker), /*isReadonly*/ false); + numberIndexInfo = checker.createIndexInfo(getTypeFromUsageContext(usageContext.numberIndexContext, checker)!, /*isReadonly*/ false); // TODO: GH#18217 } if (usageContext.stringIndexContext) { - stringIndexInfo = checker.createIndexInfo(getTypeFromUsageContext(usageContext.stringIndexContext, checker), /*isReadonly*/ false); + stringIndexInfo = checker.createIndexInfo(getTypeFromUsageContext(usageContext.stringIndexContext, checker)!, /*isReadonly*/ false); } - return checker.createAnonymousType(/*symbol*/ undefined, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); + return checker.createAnonymousType(/*symbol*/ undefined!, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); // TODO: GH#18217 } else { return undefined; @@ -604,17 +605,18 @@ namespace ts.codefix { parameters.push(symbol); } const returnType = getTypeFromUsageContext(callContext.returnType, checker) || checker.getVoidType(); - return checker.createSignature(/*declaration*/ undefined, /*typeParameters*/ undefined, /*thisParameter*/ undefined, parameters, returnType, /*typePredicate*/ undefined, callContext.argumentTypes.length, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); + // TODO: GH#18217 + return checker.createSignature(/*declaration*/ undefined!, /*typeParameters*/ undefined, /*thisParameter*/ undefined, parameters, returnType, /*typePredicate*/ undefined, callContext.argumentTypes.length, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); } - function addCandidateType(context: UsageContext, type: Type) { + function addCandidateType(context: UsageContext, type: Type | undefined) { if (type && !(type.flags & TypeFlags.Any) && !(type.flags & TypeFlags.Never)) { (context.candidateTypes || (context.candidateTypes = [])).push(type); } } - function hasCallContext(usageContext: UsageContext) { - return usageContext && usageContext.callContexts; + function hasCallContext(usageContext: UsageContext | undefined): boolean { + return !!usageContext && !!usageContext.callContexts; } } } diff --git a/src/services/codefixes/moduleSpecifiers.ts b/src/services/codefixes/moduleSpecifiers.ts index 94b7846d8e610..5279c3cb84f75 100644 --- a/src/services/codefixes/moduleSpecifiers.ts +++ b/src/services/codefixes/moduleSpecifiers.ts @@ -182,7 +182,7 @@ namespace ts.moduleSpecifiers { return undefined; } - const parts = getNodeModulePathParts(moduleFileName); + const parts: NodeModulePathParts = getNodeModulePathParts(moduleFileName)!; if (!parts) { return undefined; @@ -201,8 +201,8 @@ namespace ts.moduleSpecifiers { // If the file is the main module, it can be imported by the package name const packageRootPath = path.substring(0, parts.packageRootIndex); const packageJsonPath = combinePaths(packageRootPath, "package.json"); - if (host.fileExists(packageJsonPath)) { - const packageJsonContent = JSON.parse(host.readFile(packageJsonPath)); + if (host.fileExists!(packageJsonPath)) { // TODO: GH#18217 + const packageJsonContent = JSON.parse(host.readFile!(packageJsonPath)!); if (packageJsonContent) { const mainFileRelative = packageJsonContent.typings || packageJsonContent.types || packageJsonContent.main; if (mainFileRelative) { @@ -237,7 +237,13 @@ namespace ts.moduleSpecifiers { } } - function getNodeModulePathParts(fullPath: string) { + interface NodeModulePathParts { + readonly topLevelNodeModulesIndex: number; + readonly topLevelPackageNameIndex: number; + readonly packageRootIndex: number; + readonly fileNameIndex: number; + } + function getNodeModulePathParts(fullPath: string): NodeModulePathParts | undefined { // If fullPath can't be valid module file within node_modules, returns undefined. // Example of expected pattern: /base/path/node_modules/[@scope/otherpackage/@otherscope/node_modules/]package/[subdirectory/]file.js // Returns indices: ^ ^ ^ ^ @@ -297,7 +303,7 @@ namespace ts.moduleSpecifiers { function getPathRelativeToRootDirs(path: string, rootDirs: ReadonlyArray, getCanonicalFileName: GetCanonicalFileName): string | undefined { return firstDefined(rootDirs, rootDir => { - const relativePath = getRelativePathIfInDirectory(path, rootDir, getCanonicalFileName); + const relativePath = getRelativePathIfInDirectory(path, rootDir, getCanonicalFileName)!; // TODO: GH#18217 return isPathRelativeToParent(relativePath) ? undefined : relativePath; }); } diff --git a/src/services/completions.ts b/src/services/completions.ts index 932dc6334d437..e70398067628a 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -34,7 +34,7 @@ namespace ts.Completions { } const contextToken = findPrecedingToken(position, sourceFile); - if (triggerCharacter && !isValidTrigger(sourceFile, triggerCharacter, contextToken, position)) return undefined; + if (triggerCharacter && !isValidTrigger(sourceFile, triggerCharacter, contextToken!, position)) return undefined; // TODO: GH#18217 if (isInString(sourceFile, position, contextToken)) { return !contextToken || !isStringLiteralLike(contextToken) @@ -100,7 +100,7 @@ namespace ts.Completions { return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, entries }; } - function completionInfoFromData(sourceFile: SourceFile, typeChecker: TypeChecker, compilerOptions: CompilerOptions, log: Log, completionData: CompletionData, preferences: UserPreferences): CompletionInfo { + function completionInfoFromData(sourceFile: SourceFile, typeChecker: TypeChecker, compilerOptions: CompilerOptions, log: Log, completionData: CompletionData, preferences: UserPreferences): CompletionInfo | undefined { const { symbols, completionKind, isInSnippetScope, isNewIdentifierLocation, location, propertyAccessToConvert, keywordFilters, symbolToOriginInfoMap, recommendedCompletion, isJsxInitializer } = completionData; if (sourceFile.languageVariant === LanguageVariant.JSX && location && location.parent && isJsxClosingElement(location.parent)) { @@ -122,15 +122,15 @@ namespace ts.Completions { const entries: CompletionEntry[] = []; if (isUncheckedFile(sourceFile, compilerOptions)) { - const uniqueNames = getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, compilerOptions.target, log, completionKind, preferences, propertyAccessToConvert, isJsxInitializer, recommendedCompletion, symbolToOriginInfoMap); - getJavaScriptCompletionEntries(sourceFile, location.pos, uniqueNames, compilerOptions.target, entries); + const uniqueNames = getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, compilerOptions.target!, log, completionKind, preferences, propertyAccessToConvert, isJsxInitializer, recommendedCompletion, symbolToOriginInfoMap); + getJavaScriptCompletionEntries(sourceFile, location!.pos, uniqueNames, compilerOptions.target!, entries); // TODO: GH#18217 } else { if ((!symbols || symbols.length === 0) && keywordFilters === KeywordCompletionFilters.None) { return undefined; } - getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, compilerOptions.target, log, completionKind, preferences, propertyAccessToConvert, isJsxInitializer, recommendedCompletion, symbolToOriginInfoMap); + getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, compilerOptions.target!, log, completionKind, preferences, propertyAccessToConvert, isJsxInitializer, recommendedCompletion, symbolToOriginInfoMap); } // TODO add filter for keyword based on type/value/namespace and also location @@ -186,7 +186,7 @@ namespace ts.Completions { function createCompletionEntry( symbol: Symbol, - location: Node, + location: Node | undefined, sourceFile: SourceFile, typeChecker: TypeChecker, target: ScriptTarget, @@ -194,7 +194,7 @@ namespace ts.Completions { origin: SymbolOriginInfo | undefined, recommendedCompletion: Symbol | undefined, propertyAccessToConvert: PropertyAccessExpression | undefined, - isJsxInitializer: IsJsxInitializer, + isJsxInitializer: IsJsxInitializer | undefined, preferences: UserPreferences, ): CompletionEntry | undefined { const info = getCompletionEntryDisplayNameForSymbol(symbol, target, origin, kind); @@ -212,7 +212,7 @@ namespace ts.Completions { // Somehow there was a global with a non-identifier name. Hopefully someone will complain about getting a "foo bar" global completion and provide a repro. else if ((origin && origin.type === "symbol-member" || needsConvertPropertyAccess) && propertyAccessToConvert) { insertText = needsConvertPropertyAccess ? `[${quote(name, preferences)}]` : `[${name}]`; - const dot = findChildOfKind(propertyAccessToConvert!, SyntaxKind.DotToken, sourceFile)!; + const dot = findChildOfKind(propertyAccessToConvert, SyntaxKind.DotToken, sourceFile)!; // If the text after the '.' starts with this name, write over it. Else, add new text. const end = startsWith(name, propertyAccessToConvert.name.text) ? propertyAccessToConvert.name.end : dot.end; replacementSpan = createTextSpanFromBounds(dot.getStart(sourceFile), end); @@ -240,7 +240,7 @@ namespace ts.Completions { // entries (like JavaScript identifier entries). return { name, - kind: SymbolDisplay.getSymbolKind(typeChecker, symbol, location), + kind: SymbolDisplay.getSymbolKind(typeChecker, symbol, location!), // TODO: GH#18217 kindModifiers: SymbolDisplay.getSymbolModifiers(symbol), sortText: "0", source: getSourceFromOrigin(origin), @@ -264,7 +264,7 @@ namespace ts.Completions { } } - function isRecommendedCompletionMatch(localSymbol: Symbol, recommendedCompletion: Symbol, checker: TypeChecker): boolean { + function isRecommendedCompletionMatch(localSymbol: Symbol, recommendedCompletion: Symbol | undefined, checker: TypeChecker): boolean { return localSymbol === recommendedCompletion || !!(localSymbol.flags & SymbolFlags.ExportValue) && checker.getExportSymbolOfSymbol(localSymbol) === recommendedCompletion; } @@ -280,7 +280,7 @@ namespace ts.Completions { function getCompletionEntriesFromSymbols( symbols: ReadonlyArray, entries: Push, - location: Node, + location: Node | undefined, sourceFile: SourceFile, typeChecker: TypeChecker, target: ScriptTarget, @@ -311,7 +311,7 @@ namespace ts.Completions { } // Latter case tests whether this is a global variable. - if (!origin && !(symbol.parent === undefined && !some(symbol.declarations, d => d.getSourceFile() === location.getSourceFile()))) { + if (!origin && !(symbol.parent === undefined && !some(symbol.declarations, d => d.getSourceFile() === location!.getSourceFile()))) { // TODO: GH#18217 uniques.set(name, true); } @@ -460,7 +460,7 @@ namespace ts.Completions { checker.getResolvedSignature(argumentInfo.invocation, candidates, argumentInfo.argumentCount); const types = flatMap(candidates, candidate => { if (!candidate.hasRestParameter && argumentInfo.argumentCount > candidate.parameters.length) return; - const type = checker.getParameterType(candidate, argumentInfo.argumentIndex); + const type = checker.getParameterType(candidate, argumentInfo.argumentIndex!); // TODO: GH#18217 isNewIdentifier = isNewIdentifier || !!(type.flags & TypeFlags.String); return getStringLiteralTypes(type, checker, uniques); }); @@ -472,7 +472,7 @@ namespace ts.Completions { return type && { kind: StringLiteralCompletionKind.Properties, symbols: type.getApparentProperties(), hasIndexSignature: hasIndexSignature(type) }; } - function getStringLiteralTypes(type: Type | undefined, typeChecker: TypeChecker, uniques = createMap()): ReadonlyArray | undefined { + function getStringLiteralTypes(type: Type | undefined, typeChecker: TypeChecker, uniques = createMap()): ReadonlyArray { if (!type) return emptyArray; type = skipConstraint(type); return type.isUnion() @@ -485,9 +485,9 @@ namespace ts.Completions { interface SymbolCompletion { type: "symbol"; symbol: Symbol; - location: Node; + location: Node | undefined; symbolToOriginInfoMap: SymbolOriginInfoMap; - previousToken: Node; + previousToken: Node | undefined; readonly isJsxInitializer: IsJsxInitializer; } function getSymbolCompletionFromEntryId(program: Program, log: Log, sourceFile: SourceFile, position: number, entryId: CompletionEntryIdentifier, @@ -507,9 +507,9 @@ namespace ts.Completions { // We don't need to perform character checks here because we're only comparing the // name against 'entryName' (which is known to be good), not building a new // completion entry. - return firstDefined(symbols, (symbol): SymbolCompletion => { // TODO: Shouldn't need return type annotation (GH#12632) + return firstDefined(symbols, (symbol): SymbolCompletion | undefined => { // TODO: Shouldn't need return type annotation (GH#12632) const origin = symbolToOriginInfoMap[getSymbolId(symbol)]; - const info = getCompletionEntryDisplayNameForSymbol(symbol, compilerOptions.target, origin, completionKind); + const info = getCompletionEntryDisplayNameForSymbol(symbol, compilerOptions.target!, origin, completionKind); return info && info.name === entryId.name && getSourceFromOrigin(origin) === entryId.source ? { type: "symbol" as "symbol", symbol, location, symbolToOriginInfoMap, previousToken, isJsxInitializer } : undefined; @@ -540,7 +540,7 @@ namespace ts.Completions { getCanonicalFileName: GetCanonicalFileName, preferences: UserPreferences, cancellationToken: CancellationToken, - ): CompletionEntryDetails { + ): CompletionEntryDetails | undefined { const typeChecker = program.getTypeChecker(); const compilerOptions = program.getCompilerOptions(); const { name } = entryId; @@ -550,7 +550,7 @@ namespace ts.Completions { const stringLiteralCompletions = !contextToken || !isStringLiteralLike(contextToken) ? undefined : getStringLiteralCompletionEntries(sourceFile, contextToken, position, typeChecker, compilerOptions, host); - return stringLiteralCompletions && stringLiteralCompletionDetails(name, contextToken, stringLiteralCompletions, sourceFile, typeChecker, cancellationToken); + return stringLiteralCompletions && stringLiteralCompletionDetails(name, contextToken!, stringLiteralCompletions, sourceFile, typeChecker, cancellationToken); // TODO: GH#18217 } // Compute all the completion symbols again. @@ -572,7 +572,7 @@ namespace ts.Completions { case "symbol": { const { symbol, location, symbolToOriginInfoMap, previousToken } = symbolCompletion; const { codeActions, sourceDisplay } = getCompletionEntryCodeActionsAndSourceDisplay(symbolToOriginInfoMap, symbol, program, typeChecker, host, compilerOptions, sourceFile, previousToken, formatContext, getCanonicalFileName, program.getSourceFiles(), preferences); - return createCompletionDetailsForSymbol(symbol, typeChecker, sourceFile, location, cancellationToken, codeActions, sourceDisplay); + return createCompletionDetailsForSymbol(symbol, typeChecker, sourceFile, location!, cancellationToken, codeActions, sourceDisplay); // TODO: GH#18217 } case "none": // Didn't find a symbol with this name. See if we can find a keyword instead. @@ -621,7 +621,7 @@ namespace ts.Completions { host: LanguageServiceHost, compilerOptions: CompilerOptions, sourceFile: SourceFile, - previousToken: Node, + previousToken: Node | undefined, formatContext: formatting.FormatContext, getCanonicalFileName: GetCanonicalFileName, allSourceFiles: ReadonlyArray, @@ -638,7 +638,7 @@ namespace ts.Completions { exportedSymbol, moduleSymbol, sourceFile, - getSymbolName(symbol, symbolOriginInfo, compilerOptions.target), + getSymbolName(symbol, symbolOriginInfo, compilerOptions.target!), host, program, checker, @@ -705,7 +705,7 @@ namespace ts.Completions { case SyntaxKind.EqualsToken: switch (parent.kind) { case SyntaxKind.VariableDeclaration: - return checker.getContextualType((parent as VariableDeclaration).initializer); + return checker.getContextualType((parent as VariableDeclaration).initializer!); // TODO: GH#18217 case SyntaxKind.BinaryExpression: return checker.getTypeAtLocation((parent as BinaryExpression).left); case SyntaxKind.JsxAttribute: @@ -723,7 +723,7 @@ namespace ts.Completions { const argInfo = SignatureHelp.getImmediatelyContainingArgumentInfo(currentToken, position, sourceFile); return argInfo // At `,`, treat this as the next argument after the comma. - ? checker.getContextualTypeForArgumentAtIndex(argInfo.invocation, argInfo.argumentIndex + (currentToken.kind === SyntaxKind.CommaToken ? 1 : 0)) + ? checker.getContextualTypeForArgumentAtIndex(argInfo.invocation, argInfo.argumentIndex! + (currentToken.kind === SyntaxKind.CommaToken ? 1 : 0)) // TODO: GH#18217 : isEqualityOperatorKind(currentToken.kind) && isBinaryExpression(parent) && isEqualityOperatorKind(parent.operatorToken.kind) // completion at `x ===/**/` should be for the right side ? checker.getTypeAtLocation(parent.left) @@ -749,7 +749,7 @@ namespace ts.Completions { } } - function getSwitchedType(caseClause: CaseClause, checker: TypeChecker): Type { + function getSwitchedType(caseClause: CaseClause, checker: TypeChecker): Type | undefined { return checker.getTypeAtLocation(caseClause.parent.parent.expression); } @@ -850,7 +850,7 @@ namespace ts.Completions { } start = timestamp(); - const previousToken = findPrecedingToken(position, sourceFile, /*startNode*/ undefined, insideJsDocTagTypeExpression); + const previousToken = findPrecedingToken(position, sourceFile, /*startNode*/ undefined, insideJsDocTagTypeExpression)!; // TODO: GH#18217 log("getCompletionData: Get previous token 1: " + (timestamp() - start)); // The decision to provide completion depends on the contextToken, which is determined through the previousToken. @@ -861,7 +861,7 @@ namespace ts.Completions { // Skip this partial identifier and adjust the contextToken to the token that precedes it. if (contextToken && position <= contextToken.end && (isIdentifier(contextToken) || isKeyword(contextToken.kind))) { const start = timestamp(); - contextToken = findPrecedingToken(contextToken.getFullStart(), sourceFile, /*startNode*/ undefined, insideJsDocTagTypeExpression); + contextToken = findPrecedingToken(contextToken.getFullStart(), sourceFile, /*startNode*/ undefined, insideJsDocTagTypeExpression)!; // TODO: GH#18217 log("getCompletionData: Get previous token 2: " + (timestamp() - start)); } @@ -1017,6 +1017,8 @@ namespace ts.Completions { case SyntaxKind.JSDocTypeTag: case SyntaxKind.JSDocTypedefTag: return true; + default: + return false; } } @@ -1060,7 +1062,7 @@ namespace ts.Completions { } if (!isTypeLocation) { - addTypeProperties(typeChecker.getTypeAtLocation(node)); + addTypeProperties(typeChecker.getTypeAtLocation(node)!); } } @@ -1131,7 +1133,7 @@ namespace ts.Completions { // Cursor is inside a JSX self-closing element or opening element const attrsType = jsxContainer && typeChecker.getAllAttributesTypeFromJsxOpeningLikeElement(jsxContainer); if (!attrsType) return GlobalsSearch.Continue; - symbols = filterJsxAttributes(typeChecker.getPropertiesOfType(attrsType), jsxContainer.attributes.properties); + symbols = filterJsxAttributes(typeChecker.getPropertiesOfType(attrsType), jsxContainer!.attributes.properties); completionKind = CompletionKind.MemberLike; isNewIdentifierLocation = false; return GlobalsSearch.Success; @@ -1197,7 +1199,7 @@ namespace ts.Completions { } if (shouldOfferImportCompletions()) { - getSymbolsFromOtherSourceFileExports(symbols, previousToken && isIdentifier(previousToken) ? previousToken.text : "", program.getCompilerOptions().target); + getSymbolsFromOtherSourceFileExports(symbols, previousToken && isIdentifier(previousToken) ? previousToken.text : "", program.getCompilerOptions().target!); } filterGlobalCompletion(symbols); } @@ -1305,6 +1307,7 @@ namespace ts.Completions { // symbol can be referenced at locations where type is allowed return exportedSymbols.some(symbolCanBeReferencedAtTypeLocation); } + return false; } function getSymbolsFromOtherSourceFileExports(symbols: Symbol[], tokenText: string, target: ScriptTarget): void { @@ -1323,7 +1326,7 @@ namespace ts.Completions { // // If `symbol.parent !== ...`, this comes from an `export * from "foo"` re-export. Those don't create new symbols. // If `some(...)`, this comes from an `export { foo } from "foo"` re-export, which creates a new symbol (thus isn't caught by the first check). - if (typeChecker.getMergedSymbol(symbol.parent) !== typeChecker.resolveExternalModuleSymbol(moduleSymbol) + if (typeChecker.getMergedSymbol(symbol.parent!) !== typeChecker.resolveExternalModuleSymbol(moduleSymbol) || some(symbol.declarations, d => isExportSpecifier(d) && !!d.parent.parent.moduleSpecifier)) { continue; } @@ -1370,8 +1373,8 @@ namespace ts.Completions { * Finds the first node that "embraces" the position, so that one may * accurately aggregate locals from the closest containing scope. */ - function getScopeNode(initialToken: Node, position: number, sourceFile: SourceFile) { - let scope = initialToken; + function getScopeNode(initialToken: Node | undefined, position: number, sourceFile: SourceFile) { + let scope: Node | undefined = initialToken; while (scope && !positionBelongsToNode(scope, position, sourceFile)) { scope = scope.parent; } @@ -1399,13 +1402,13 @@ namespace ts.Completions { } if (contextToken.parent.kind === SyntaxKind.JsxClosingElement || contextToken.parent.kind === SyntaxKind.JsxSelfClosingElement) { - return contextToken.parent.parent && contextToken.parent.parent.kind === SyntaxKind.JsxElement; + return !!contextToken.parent.parent && contextToken.parent.parent.kind === SyntaxKind.JsxElement; } } return false; } - function isNewIdentifierDefinitionLocation(previousToken: Node): boolean { + function isNewIdentifierDefinitionLocation(previousToken: Node | undefined): boolean { if (previousToken) { const containingNodeKind = previousToken.parent.kind; switch (previousToken.kind) { @@ -1504,8 +1507,8 @@ namespace ts.Completions { // We're looking up possible property names from contextual/inferred/declared type. completionKind = CompletionKind.ObjectPropertyDeclaration; - let typeMembers: Symbol[]; - let existingMembers: ReadonlyArray; + let typeMembers: Symbol[] | undefined; + let existingMembers: ReadonlyArray | undefined; if (objectLikeContainer.kind === SyntaxKind.ObjectLiteralExpression) { const typeForObject = typeChecker.getContextualType(objectLikeContainer); @@ -1576,7 +1579,7 @@ namespace ts.Completions { // cursor is in an import clause // try to show exported member for imported module const { moduleSpecifier } = namedImportsOrExports.kind === SyntaxKind.NamedImports ? namedImportsOrExports.parent.parent : namedImportsOrExports.parent; - const moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(moduleSpecifier); + const moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(moduleSpecifier!); // TODO: GH#18217 if (!moduleSpecifierSymbol) return GlobalsSearch.Fail; completionKind = CompletionKind.MemberLike; @@ -1605,7 +1608,7 @@ namespace ts.Completions { if (!isClassLike(decl)) return GlobalsSearch.Success; const classElement = contextToken.parent; - let classElementModifierFlags = isClassElement(classElement) && getModifierFlags(classElement); + let classElementModifierFlags = isClassElement(classElement) ? getModifierFlags(classElement) : ModifierFlags.None; // If this is context token is not something we are editing now, consider if this would lead to be modifier if (contextToken.kind === SyntaxKind.Identifier && !isCurrentlyEditingNode(contextToken)) { switch (contextToken.getText()) { @@ -1622,7 +1625,7 @@ namespace ts.Completions { if (!(classElementModifierFlags & ModifierFlags.Private)) { // List of property symbols of base type that are not private and already implemented const baseSymbols = flatMap(getAllSuperTypeNodes(decl), baseTypeNode => { - const type = typeChecker.getTypeAtLocation(baseTypeNode); + const type = typeChecker.getTypeAtLocation(baseTypeNode)!; // TODO: GH#18217 return typeChecker.getPropertiesOfType(classElementModifierFlags & ModifierFlags.Static ? typeChecker.getTypeOfSymbolAtLocation(type.symbol, decl) : type); }); symbols = filterClassMembersList(baseSymbols, decl.members, classElementModifierFlags); @@ -1635,7 +1638,7 @@ namespace ts.Completions { * Returns the immediate owning object literal or binding pattern of a context token, * on the condition that one exists and that the context implies completion should be given. */ - function tryGetObjectLikeCompletionContainer(contextToken: Node): ObjectLiteralExpression | ObjectBindingPattern { + function tryGetObjectLikeCompletionContainer(contextToken: Node): ObjectLiteralExpression | ObjectBindingPattern | undefined { if (contextToken) { switch (contextToken.kind) { case SyntaxKind.OpenBraceToken: // const x = { | @@ -1660,23 +1663,24 @@ namespace ts.Completions { * Returns the immediate owning class declaration of a context token, * on the condition that one exists and that the context implies completion should be given. */ - function tryGetConstructorLikeCompletionContainer(contextToken: Node): ConstructorDeclaration { + function tryGetConstructorLikeCompletionContainer(contextToken: Node): ConstructorDeclaration | undefined { if (contextToken) { + const parent = contextToken.parent; switch (contextToken.kind) { case SyntaxKind.OpenParenToken: case SyntaxKind.CommaToken: - return isConstructorDeclaration(contextToken.parent) && contextToken.parent; + return isConstructorDeclaration(contextToken.parent) ? contextToken.parent : undefined; default: if (isConstructorParameterCompletion(contextToken)) { - return contextToken.parent.parent as ConstructorDeclaration; + return parent.parent as ConstructorDeclaration; } } } return undefined; } - function tryGetFunctionLikeBodyCompletionContainer(contextToken: Node): FunctionLikeDeclaration { + function tryGetFunctionLikeBodyCompletionContainer(contextToken: Node): FunctionLikeDeclaration | undefined { if (contextToken) { let prev: Node; const container = findAncestor(contextToken.parent, (node: Node) => { @@ -1687,12 +1691,13 @@ namespace ts.Completions { return true; } prev = node; + return false; }); return container && container as FunctionLikeDeclaration; } } - function tryGetContainingJsxElement(contextToken: Node): JsxOpeningLikeElement { + function tryGetContainingJsxElement(contextToken: Node): JsxOpeningLikeElement | undefined { if (contextToken) { const parent = contextToken.parent; switch (contextToken.kind) { @@ -1759,7 +1764,8 @@ namespace ts.Completions { * @returns true if we are certain that the currently edited location must define a new location; false otherwise. */ function isSolelyIdentifierDefinitionLocation(contextToken: Node): boolean { - const containingNodeKind = contextToken.parent.kind; + const parent = contextToken.parent; + const containingNodeKind = parent.kind; switch (contextToken.kind) { case SyntaxKind.CommaToken: return containingNodeKind === SyntaxKind.VariableDeclaration || @@ -1772,9 +1778,9 @@ namespace ts.Completions { containingNodeKind === SyntaxKind.TypeAliasDeclaration || // type Map, K, | // class A= contextToken.pos); + (isClassLike(parent) && + !!parent.typeParameters && + parent.typeParameters.end >= contextToken.pos); case SyntaxKind.DotToken: return containingNodeKind === SyntaxKind.ArrayBindingPattern; // var [.| @@ -1800,17 +1806,16 @@ namespace ts.Completions { isFunctionLikeKind(containingNodeKind); case SyntaxKind.StaticKeyword: - return containingNodeKind === SyntaxKind.PropertyDeclaration && !isClassLike(contextToken.parent.parent); + return containingNodeKind === SyntaxKind.PropertyDeclaration && !isClassLike(parent.parent); case SyntaxKind.DotDotDotToken: return containingNodeKind === SyntaxKind.Parameter || - (contextToken.parent && contextToken.parent.parent && - contextToken.parent.parent.kind === SyntaxKind.ArrayBindingPattern); // var [...z| + (!!parent.parent && parent.parent.kind === SyntaxKind.ArrayBindingPattern); // var [...z| case SyntaxKind.PublicKeyword: case SyntaxKind.PrivateKeyword: case SyntaxKind.ProtectedKeyword: - return containingNodeKind === SyntaxKind.Parameter && !isConstructorDeclaration(contextToken.parent.parent); + return containingNodeKind === SyntaxKind.Parameter && !isConstructorDeclaration(parent.parent); case SyntaxKind.AsKeyword: return containingNodeKind === SyntaxKind.ImportSpecifier || @@ -1922,12 +1927,12 @@ namespace ts.Completions { continue; } - let existingName: __String; + let existingName: __String | undefined; - if (m.kind === SyntaxKind.BindingElement && (m).propertyName) { + if (isBindingElement(m) && m.propertyName) { // include only identifiers in completion list - if ((m).propertyName.kind === SyntaxKind.Identifier) { - existingName = ((m).propertyName).escapedText; + if (m.propertyName.kind === SyntaxKind.Identifier) { + existingName = m.propertyName.escapedText; } } else { @@ -1938,7 +1943,7 @@ namespace ts.Completions { existingName = isPropertyNameLiteral(name) ? getEscapedTextOfIdentifierOrLiteral(name) : undefined; } - existingMemberNames.set(existingName, true); + existingMemberNames.set(existingName!, true); // TODO: GH#18217 } return contextualMemberSymbols.filter(m => !existingMemberNames.get(m.escapedName)); @@ -1975,7 +1980,7 @@ namespace ts.Completions { continue; } - const existingName = getPropertyNameForPropertyNameNode(m.name); + const existingName = getPropertyNameForPropertyNameNode(m.name!); if (existingName) { existingMemberNames.set(existingName, true); } @@ -2060,7 +2065,7 @@ namespace ts.Completions { const res: CompletionEntry[] = []; for (let i = SyntaxKind.FirstKeyword; i <= SyntaxKind.LastKeyword; i++) { res.push({ - name: tokenToString(i), + name: tokenToString(i)!, kind: ScriptElementKind.keyword, kindModifiers: ScriptElementKindModifier.none, sortText: "0" @@ -2070,7 +2075,7 @@ namespace ts.Completions { }); function getKeywordCompletions(keywordFilter: KeywordCompletionFilters): ReadonlyArray { return _keywordCompletions[keywordFilter] || (_keywordCompletions[keywordFilter] = allKeywordsCompletions().filter(entry => { - const kind = stringToToken(entry.name); + const kind = stringToToken(entry.name)!; switch (keywordFilter) { case KeywordCompletionFilters.None: // "undefined" is a global variable, so don't need a keyword completion for it. @@ -2199,7 +2204,7 @@ namespace ts.Completions { default: if (!isFromObjectTypeDeclaration(contextToken)) return undefined; const isValidKeyword = isClassLike(contextToken.parent.parent) ? isClassMemberCompletionKeyword : isInterfaceOrTypeLiteralCompletionKeyword; - return (isValidKeyword(contextToken.kind) || isIdentifier(contextToken) && isValidKeyword(stringToToken(contextToken.text))) + return (isValidKeyword(contextToken.kind) || isIdentifier(contextToken) && isValidKeyword(stringToToken(contextToken.text)!)) // TODO: GH#18217 ? contextToken.parent.parent as ObjectTypeDeclaration : undefined; } } diff --git a/src/services/documentHighlights.ts b/src/services/documentHighlights.ts index 65653483d0755..e6a78e098e941 100644 --- a/src/services/documentHighlights.ts +++ b/src/services/documentHighlights.ts @@ -30,7 +30,7 @@ namespace ts.DocumentHighlights { if (!sourceFilesSet.has(fileName)) { Debug.assert(program.redirectTargetsSet.has(fileName)); const redirectTarget = program.getSourceFile(fileName); - const redirect = find(sourceFilesToSearch, f => f.redirectInfo && f.redirectInfo.redirectTarget === redirectTarget)!; + const redirect = find(sourceFilesToSearch, f => !!f.redirectInfo && f.redirectInfo.redirectTarget === redirectTarget)!; fileName = redirect.fileName; Debug.assert(sourceFilesSet.has(fileName)); } @@ -38,7 +38,7 @@ namespace ts.DocumentHighlights { }); } - function getSyntacticDocumentHighlights(node: Node, sourceFile: SourceFile): DocumentHighlights[] { + function getSyntacticDocumentHighlights(node: Node, sourceFile: SourceFile): DocumentHighlights[] | undefined { const highlightSpans = getHighlightSpans(node, sourceFile); return highlightSpans && [{ fileName: sourceFile.fileName, highlightSpans }]; } @@ -110,7 +110,7 @@ namespace ts.DocumentHighlights { // Exceptions thrown within a try block lacking a catch clause are "owned" in the current context. return concatenate( node.catchClause ? aggregateOwnedThrowStatements(node.catchClause) : node.tryBlock && aggregateOwnedThrowStatements(node.tryBlock), - aggregateOwnedThrowStatements(node.finallyBlock)); + node.finallyBlock && aggregateOwnedThrowStatements(node.finallyBlock)); } // Do not cross function boundaries. return isFunctionLike(node) ? undefined : flatMapChildren(node, aggregateOwnedThrowStatements); @@ -121,7 +121,7 @@ namespace ts.DocumentHighlights { * nearest ancestor that is a try-block (whose try statement has a catch clause), * function-block, or source file. */ - function getThrowStatementOwner(throwStatement: ThrowStatement): Node { + function getThrowStatementOwner(throwStatement: ThrowStatement): Node | undefined { let child: Node = throwStatement; while (child.parent) { @@ -160,11 +160,10 @@ namespace ts.DocumentHighlights { function ownsBreakOrContinueStatement(owner: Node, statement: BreakOrContinueStatement): boolean { const actualOwner = getBreakOrContinueOwner(statement); - - return actualOwner && actualOwner === owner; + return !!actualOwner && actualOwner === owner; } - function getBreakOrContinueOwner(statement: BreakOrContinueStatement): Node { + function getBreakOrContinueOwner(statement: BreakOrContinueStatement): Node | undefined { return findAncestor(statement, node => { switch (node.kind) { case SyntaxKind.SwitchStatement: @@ -190,14 +189,14 @@ namespace ts.DocumentHighlights { const modifierFlag = modifierToFlag(modifier); return mapDefined(getNodesToSearchForModifier(declaration, modifierFlag), node => { if (getModifierFlags(node) & modifierFlag) { - const mod = find(node.modifiers, m => m.kind === modifier); + const mod = find(node.modifiers!, m => m.kind === modifier); Debug.assert(!!mod); return mod; } }); } - function getNodesToSearchForModifier(declaration: Node, modifierFlag: ModifierFlags): ReadonlyArray { + function getNodesToSearchForModifier(declaration: Node, modifierFlag: ModifierFlags): ReadonlyArray | undefined { // Types of node whose children might have modifiers. const container = declaration.parent as ModuleBlock | SourceFile | Block | CaseClause | DefaultClause | ConstructorDeclaration | MethodDeclaration | FunctionDeclaration | ClassLikeDeclaration; switch (container.kind) { @@ -215,9 +214,8 @@ namespace ts.DocumentHighlights { } case SyntaxKind.Constructor: case SyntaxKind.MethodDeclaration: - case SyntaxKind.FunctionDeclaration: { + case SyntaxKind.FunctionDeclaration: return [...container.parameters, ...(isClassLike(container.parent) ? container.parent.members : [])]; - } case SyntaxKind.ClassDeclaration: case SyntaxKind.ClassExpression: const nodes = container.members; @@ -251,7 +249,7 @@ namespace ts.DocumentHighlights { function getLoopBreakContinueOccurrences(loopNode: IterationStatement): Node[] { const keywords: Node[] = []; - if (pushKeywordIf(keywords, loopNode.getFirstToken(), SyntaxKind.ForKeyword, SyntaxKind.WhileKeyword, SyntaxKind.DoKeyword)) { + if (pushKeywordIf(keywords, loopNode.getFirstToken()!, SyntaxKind.ForKeyword, SyntaxKind.WhileKeyword, SyntaxKind.DoKeyword)) { // If we succeeded and got a do-while loop, then start looking for a 'while' keyword. if (loopNode.kind === SyntaxKind.DoStatement) { const loopTokens = loopNode.getChildren(); @@ -266,14 +264,14 @@ namespace ts.DocumentHighlights { forEach(aggregateAllBreakAndContinueStatements(loopNode.statement), statement => { if (ownsBreakOrContinueStatement(loopNode, statement)) { - pushKeywordIf(keywords, statement.getFirstToken(), SyntaxKind.BreakKeyword, SyntaxKind.ContinueKeyword); + pushKeywordIf(keywords, statement.getFirstToken()!, SyntaxKind.BreakKeyword, SyntaxKind.ContinueKeyword); } }); return keywords; } - function getBreakOrContinueStatementOccurrences(breakOrContinueStatement: BreakOrContinueStatement): Node[] { + function getBreakOrContinueStatementOccurrences(breakOrContinueStatement: BreakOrContinueStatement): Node[] | undefined { const owner = getBreakOrContinueOwner(breakOrContinueStatement); if (owner) { @@ -296,15 +294,15 @@ namespace ts.DocumentHighlights { function getSwitchCaseDefaultOccurrences(switchStatement: SwitchStatement): Node[] { const keywords: Node[] = []; - pushKeywordIf(keywords, switchStatement.getFirstToken(), SyntaxKind.SwitchKeyword); + pushKeywordIf(keywords, switchStatement.getFirstToken()!, SyntaxKind.SwitchKeyword); // Go through each clause in the switch statement, collecting the 'case'/'default' keywords. forEach(switchStatement.caseBlock.clauses, clause => { - pushKeywordIf(keywords, clause.getFirstToken(), SyntaxKind.CaseKeyword, SyntaxKind.DefaultKeyword); + pushKeywordIf(keywords, clause.getFirstToken()!, SyntaxKind.CaseKeyword, SyntaxKind.DefaultKeyword); forEach(aggregateAllBreakAndContinueStatements(clause), statement => { if (ownsBreakOrContinueStatement(switchStatement, statement)) { - pushKeywordIf(keywords, statement.getFirstToken(), SyntaxKind.BreakKeyword); + pushKeywordIf(keywords, statement.getFirstToken()!, SyntaxKind.BreakKeyword); } }); }); @@ -315,21 +313,21 @@ namespace ts.DocumentHighlights { function getTryCatchFinallyOccurrences(tryStatement: TryStatement, sourceFile: SourceFile): Node[] { const keywords: Node[] = []; - pushKeywordIf(keywords, tryStatement.getFirstToken(), SyntaxKind.TryKeyword); + pushKeywordIf(keywords, tryStatement.getFirstToken()!, SyntaxKind.TryKeyword); if (tryStatement.catchClause) { - pushKeywordIf(keywords, tryStatement.catchClause.getFirstToken(), SyntaxKind.CatchKeyword); + pushKeywordIf(keywords, tryStatement.catchClause.getFirstToken()!, SyntaxKind.CatchKeyword); } if (tryStatement.finallyBlock) { - const finallyKeyword = findChildOfKind(tryStatement, SyntaxKind.FinallyKeyword, sourceFile); + const finallyKeyword = findChildOfKind(tryStatement, SyntaxKind.FinallyKeyword, sourceFile)!; pushKeywordIf(keywords, finallyKeyword, SyntaxKind.FinallyKeyword); } return keywords; } - function getThrowOccurrences(throwStatement: ThrowStatement, sourceFile: SourceFile): Node[] { + function getThrowOccurrences(throwStatement: ThrowStatement, sourceFile: SourceFile): Node[] | undefined { const owner = getThrowStatementOwner(throwStatement); if (!owner) { @@ -365,7 +363,7 @@ namespace ts.DocumentHighlights { }); // Include 'throw' statements that do not occur within a try block. - forEach(aggregateOwnedThrowStatements(func.body), throwStatement => { + forEach(aggregateOwnedThrowStatements(func.body!), throwStatement => { keywords.push(findChildOfKind(throwStatement, SyntaxKind.ThrowKeyword, sourceFile)!); }); @@ -392,7 +390,7 @@ namespace ts.DocumentHighlights { function aggregate(node: Node): void { if (isAwaitExpression(node)) { - pushKeywordIf(keywords, node.getFirstToken(), SyntaxKind.AwaitKeyword); + pushKeywordIf(keywords, node.getFirstToken()!, SyntaxKind.AwaitKeyword); } // Do not cross function boundaries. if (!isFunctionLike(node) && !isClassLike(node) && !isInterfaceDeclaration(node) && !isModuleDeclaration(node) && !isTypeAliasDeclaration(node) && !isTypeNode(node)) { diff --git a/src/services/documentRegistry.ts b/src/services/documentRegistry.ts index 05f6548c62b73..ee99aed930c4e 100644 --- a/src/services/documentRegistry.ts +++ b/src/services/documentRegistry.ts @@ -130,12 +130,12 @@ namespace ts { if (!bucket && createIfMissing) { buckets.set(key, bucket = createMap()); } - return bucket; + return bucket!; // TODO: GH#18217 } function reportStats() { const bucketInfoArray = arrayFrom(buckets.keys()).filter(name => name && name.charAt(0) === "_").map(name => { - const entries = buckets.get(name); + const entries = buckets.get(name)!; const sourceFiles: { name: string; refCount: number; }[] = []; entries.forEach((entry, name) => { sourceFiles.push({ @@ -199,7 +199,7 @@ namespace ts { if (!entry) { // Have never seen this file with these settings. Create a new source file for it. - const sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, scriptTarget, version, /*setNodeParents*/ false, scriptKind); + const sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, scriptTarget!, version, /*setNodeParents*/ false, scriptKind); // TODO: GH#18217 if (externalCache) { externalCache.setDocument(key, path, sourceFile); } @@ -215,7 +215,7 @@ namespace ts { // return it as is. if (entry.sourceFile.version !== version) { entry.sourceFile = updateLanguageServiceSourceFile(entry.sourceFile, scriptSnapshot, version, - scriptSnapshot.getChangeRange(entry.sourceFile.scriptSnapshot)); + scriptSnapshot.getChangeRange(entry.sourceFile.scriptSnapshot!)); // TODO: GH#18217 if (externalCache) { externalCache.setDocument(key, path, entry.sourceFile); } @@ -245,7 +245,7 @@ namespace ts { const bucket = getBucketForCompilationSettings(key, /*createIfMissing*/ false); Debug.assert(bucket !== undefined); - const entry = bucket.get(path); + const entry = bucket.get(path)!; entry.languageServiceRefCount--; Debug.assert(entry.languageServiceRefCount >= 0); diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 5f4d653ca3dba..cc13cfd28c4db 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -51,7 +51,7 @@ namespace ts.FindAllReferences { }); } - export function getImplementationsAtPosition(program: Program, cancellationToken: CancellationToken, sourceFiles: ReadonlyArray, sourceFile: SourceFile, position: number): ImplementationLocation[] { + export function getImplementationsAtPosition(program: Program, cancellationToken: CancellationToken, sourceFiles: ReadonlyArray, sourceFile: SourceFile, position: number): ImplementationLocation[] | undefined { // A node in a JSDoc comment can't have an implementation anyway. const node = getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ false); const referenceEntries = getImplementationReferenceEntries(program, cancellationToken, sourceFiles, node, position); @@ -75,7 +75,7 @@ namespace ts.FindAllReferences { else if (node.kind === SyntaxKind.SuperKeyword || isSuperProperty(node.parent)) { // References to and accesses on the super keyword only have one possible implementation, so no // need to "Find all References" - const symbol = checker.getSymbolAtLocation(node); + const symbol = checker.getSymbolAtLocation(node)!; return symbol.valueDeclaration && [nodeEntry(symbol.valueDeclaration)]; } else { @@ -93,11 +93,11 @@ namespace ts.FindAllReferences { return flattenEntries(Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options, sourceFilesSet)); } - function flattenEntries(referenceSymbols: SymbolAndEntries[]): Entry[] { + function flattenEntries(referenceSymbols: SymbolAndEntries[] | undefined): Entry[] | undefined { return referenceSymbols && flatMap(referenceSymbols, r => r.references); } - function definitionToReferencedSymbolDefinitionInfo(def: Definition, checker: TypeChecker, originalNode: Node): ReferencedSymbolDefinitionInfo | undefined { + function definitionToReferencedSymbolDefinitionInfo(def: Definition, checker: TypeChecker, originalNode: Node): ReferencedSymbolDefinitionInfo { const info = (() => { switch (def.type) { case "symbol": { @@ -112,7 +112,7 @@ namespace ts.FindAllReferences { } case "keyword": { const { node } = def; - const name = tokenToString(node.kind); + const name = tokenToString(node.kind)!; return { node, name, kind: ScriptElementKind.keyword, displayParts: [{ text: name, kind: ScriptElementKind.keyword }] }; } case "this": { @@ -257,20 +257,21 @@ namespace ts.FindAllReferences.Core { let moduleReferences: SymbolAndEntries[] = emptyArray; const moduleSourceFile = isModuleSymbol(symbol); + let referencedNode: Node | undefined = node; if (moduleSourceFile) { - const exportEquals = symbol.exports.get(InternalSymbolName.ExportEquals); + const exportEquals = symbol.exports!.get(InternalSymbolName.ExportEquals); // If !!exportEquals, we're about to add references to `import("mod")` anyway, so don't double-count them. moduleReferences = getReferencedSymbolsForModule(program, symbol, !!exportEquals, sourceFiles, sourceFilesSet); if (!exportEquals || !sourceFilesSet.has(moduleSourceFile.fileName)) return moduleReferences; // Continue to get references to 'export ='. symbol = skipAlias(exportEquals, checker); - node = undefined; + referencedNode = undefined; } - return concatenate(moduleReferences, getReferencedSymbolsForSymbol(symbol, node, sourceFiles, sourceFilesSet, checker, cancellationToken, options)); + return concatenate(moduleReferences, getReferencedSymbolsForSymbol(symbol, referencedNode, sourceFiles, sourceFilesSet, checker, cancellationToken, options)); } function isModuleSymbol(symbol: Symbol): SourceFile | undefined { - return symbol.flags & SymbolFlags.Module && find(symbol.declarations, isSourceFile); + return symbol.flags & SymbolFlags.Module ? find(symbol.declarations, isSourceFile) : undefined; } function getReferencedSymbolsForModule(program: Program, symbol: Symbol, excludeImportTypeOfExportEquals: boolean, sourceFiles: ReadonlyArray, sourceFilesSet: ReadonlyMap): SymbolAndEntries[] { @@ -360,7 +361,7 @@ namespace ts.FindAllReferences.Core { searchForImportsOfExport(node, symbol, { exportingModuleSymbol: Debug.assertDefined(symbol.parent, "Expected export symbol to have a parent"), exportKind: ExportKind.Default }, state); } else { - const search = state.createSearch(node, symbol, /*comingFrom*/ undefined, { allSearchSymbols: node ? populateSearchSymbolSet(symbol, node, checker, options.implementations) : [symbol] }); + const search = state.createSearch(node, symbol, /*comingFrom*/ undefined, { allSearchSymbols: node ? populateSearchSymbolSet(symbol, node, checker, !!options.implementations) : [symbol] }); // Try to get the smallest valid scope that we can limit our search to; // otherwise we'll need to search globally (i.e. include each file). @@ -403,7 +404,7 @@ namespace ts.FindAllReferences.Core { } if (isImportSpecifier(parent) && parent.propertyName === node) { // We're at `foo` in `import { foo as bar }`. Probably intended to find all refs on the original, not just on the import. - return checker.getImmediateAliasedSymbol(symbol); + return checker.getImmediateAliasedSymbol(symbol)!; } // If the symbol is declared as part of a declaration like `{ type: "a" } | { type: "b" }`, use the property on the union type to get more references. @@ -496,7 +497,7 @@ namespace ts.FindAllReferences.Core { /** Gets every place to look for references of an exported symbols. See `ImportsResult` in `importTracker.ts` for more documentation. */ getImportSearches(exportSymbol: Symbol, exportInfo: ExportInfo): ImportsResult { if (!this.importTracker) this.importTracker = createImportTracker(this.sourceFiles, this.sourceFilesSet, this.checker, this.cancellationToken); - return this.importTracker(exportSymbol, exportInfo, this.options.isForRename); + return this.importTracker(exportSymbol, exportInfo, !!this.options.isForRename); } /** @param allSearchSymbols set of additinal symbols for use by `includes`. */ @@ -510,7 +511,7 @@ namespace ts.FindAllReferences.Core { allSearchSymbols = [symbol], } = searchOptions; const escapedText = escapeLeadingUnderscores(text); - const parents = this.options.implementations && location && getParentSymbolsOfPropertyAccess(location, symbol, this.checker); + const parents = this.options.implementations && location ? getParentSymbolsOfPropertyAccess(location, symbol, this.checker) : undefined; return { symbol, comingFrom, text, escapedText, parents, allSearchSymbols, includes: sym => contains(allSearchSymbols, sym) }; } @@ -616,8 +617,9 @@ namespace ts.FindAllReferences.Core { } function getPropertySymbolOfDestructuringAssignment(location: Node, checker: TypeChecker): Symbol | undefined { - return isArrayLiteralOrObjectLiteralDestructuringPattern(location.parent.parent) && - checker.getPropertySymbolOfDestructuringAssignment(location); + return isArrayLiteralOrObjectLiteralDestructuringPattern(location.parent.parent) + ? checker.getPropertySymbolOfDestructuringAssignment(location) + : undefined; } function getObjectBindingElementWithoutPropertyName(symbol: Symbol): BindingElement & { name: Identifier } | undefined { @@ -679,7 +681,7 @@ namespace ts.FindAllReferences.Core { - But if the parent has `export as namespace`, the symbol is globally visible through that namespace. */ const exposedByParent = parent && !(symbol.flags & SymbolFlags.TypeParameter); - if (exposedByParent && !((parent.flags & SymbolFlags.Module) && isExternalModuleSymbol(parent) && !parent.globalExports)) { + if (exposedByParent && !((parent!.flags & SymbolFlags.Module) && isExternalModuleSymbol(parent!) && !parent!.globalExports)) { return undefined; } @@ -706,7 +708,7 @@ namespace ts.FindAllReferences.Core { // declare module "a" { export type T = number; } // declare module "b" { import { T } from "a"; export const x: T; } // So we must search the whole source file. (Because we will mark the source file as seen, we we won't return to it when searching for imports.) - return exposedByParent ? scope.getSourceFile() : scope; + return exposedByParent ? scope!.getSourceFile() : scope; // TODO: GH#18217 } /** Used as a quick check for whether a symbol is used at all in a file (besides its definition). */ @@ -715,7 +717,7 @@ namespace ts.FindAllReferences.Core { if (!symbol) return true; // Be lenient with invalid code. return getPossibleSymbolReferenceNodes(sourceFile, symbol.name).some(token => { if (!isIdentifier(token) || token === definition || token.escapedText !== definition.escapedText) return false; - const referenceSymbol = checker.getSymbolAtLocation(token); + const referenceSymbol = checker.getSymbolAtLocation(token)!; return referenceSymbol === symbol || checker.getShorthandAssignmentValueSymbol(token.parent) === symbol || isExportSpecifier(token.parent) && getLocalSymbolForExportSpecifier(token, referenceSymbol, token.parent, checker) === symbol; @@ -793,10 +795,10 @@ namespace ts.FindAllReferences.Core { } } - function getAllReferencesForKeyword(sourceFiles: ReadonlyArray, keywordKind: SyntaxKind, cancellationToken: CancellationToken): SymbolAndEntries[] { + function getAllReferencesForKeyword(sourceFiles: ReadonlyArray, keywordKind: SyntaxKind, cancellationToken: CancellationToken): SymbolAndEntries[] | undefined { const references = flatMap(sourceFiles, sourceFile => { cancellationToken.throwIfCancellationRequested(); - return mapDefined(getPossibleSymbolReferenceNodes(sourceFile, tokenToString(keywordKind), sourceFile), referenceLocation => + return mapDefined(getPossibleSymbolReferenceNodes(sourceFile, tokenToString(keywordKind)!, sourceFile), referenceLocation => referenceLocation.kind === keywordKind ? nodeEntry(referenceLocation) : undefined); }); return references.length ? [{ definition: { type: "keyword", node: references[0].node }, references }] : undefined; @@ -851,7 +853,7 @@ namespace ts.FindAllReferences.Core { return; } - const { parent } = referenceLocation; + const parent = referenceLocation.parent; if (isImportSpecifier(parent) && parent.propertyName === referenceLocation) { // This is added through `singleReferences` in ImportsResult. If we happen to see it again, don't add it again. return; @@ -921,7 +923,7 @@ namespace ts.FindAllReferences.Core { if (!(referenceLocation === propertyName && state.options.isForRename)) { const exportKind = referenceLocation.originalKeywordKind === SyntaxKind.DefaultKeyword ? ExportKind.Default : ExportKind.Named; const exportInfo = getExportInfo(referenceSymbol, exportKind, state.checker); - Debug.assert(!!exportInfo); + if (!exportInfo) return Debug.fail(); searchForImportsOfExport(referenceLocation, referenceSymbol, exportInfo, state); } @@ -972,7 +974,7 @@ namespace ts.FindAllReferences.Core { } function getReferenceForShorthandProperty({ flags, valueDeclaration }: Symbol, search: Search, state: State): void { - const shorthandValueSymbol = state.checker.getShorthandAssignmentValueSymbol(valueDeclaration); + const shorthandValueSymbol = state.checker.getShorthandAssignmentValueSymbol(valueDeclaration)!; /* * Because in short-hand property assignment, an identifier which stored as name of the short-hand property assignment * has two meanings: property name and property value. Therefore when we do findAllReference at the position where @@ -1027,7 +1029,7 @@ namespace ts.FindAllReferences.Core { if (!(isMethodOrAccessor(member) && hasModifier(member, ModifierFlags.Static))) { continue; } - member.body.forEachChild(function cb(node) { + member.body!.forEachChild(function cb(node) { if (node.kind === SyntaxKind.ThisKeyword) { addRef(node); } @@ -1043,13 +1045,13 @@ namespace ts.FindAllReferences.Core { * Reference the constructor and all calls to `new this()`. */ function findOwnConstructorReferences(classSymbol: Symbol, sourceFile: SourceFile, addNode: (node: Node) => void): void { - for (const decl of classSymbol.members.get(InternalSymbolName.Constructor).declarations) { + for (const decl of classSymbol.members!.get(InternalSymbolName.Constructor)!.declarations) { const ctrKeyword = findChildOfKind(decl, SyntaxKind.ConstructorKeyword, sourceFile)!; Debug.assert(decl.kind === SyntaxKind.Constructor && !!ctrKeyword); addNode(ctrKeyword); } - classSymbol.exports.forEach(member => { + classSymbol.exports!.forEach(member => { const decl = member.valueDeclaration; if (decl && decl.kind === SyntaxKind.MethodDeclaration) { const body = (decl).body; @@ -1066,8 +1068,7 @@ namespace ts.FindAllReferences.Core { /** Find references to `super` in the constructor of an extending class. */ function findSuperConstructorAccesses(cls: ClassLikeDeclaration, addNode: (node: Node) => void): void { - const symbol = cls.symbol; - const ctr = symbol.members.get(InternalSymbolName.Constructor); + const ctr = cls.symbol.members!.get(InternalSymbolName.Constructor); if (!ctr) { return; } @@ -1110,14 +1111,14 @@ namespace ts.FindAllReferences.Core { // If we got a type reference, try and see if the reference applies to any expressions that can implement an interface // Find the first node whose parent isn't a type node -- i.e., the highest type node. - const typeNode = findAncestor(refNode, a => !isQualifiedName(a.parent) && !isTypeNode(a.parent) && !isTypeElement(a.parent)); + const typeNode = findAncestor(refNode, a => !isQualifiedName(a.parent) && !isTypeNode(a.parent) && !isTypeElement(a.parent))!; const typeHavingNode = typeNode.parent; if (hasType(typeHavingNode) && typeHavingNode.type === typeNode && state.markSeenContainingTypeReference(typeHavingNode)) { if (hasInitializer(typeHavingNode)) { - addIfImplementation(typeHavingNode.initializer); + addIfImplementation(typeHavingNode.initializer!); } else if (isFunctionLike(typeHavingNode) && (typeHavingNode as FunctionLikeDeclaration).body) { - const body = (typeHavingNode as FunctionLikeDeclaration).body; + const body = (typeHavingNode as FunctionLikeDeclaration).body!; if (body.kind === SyntaxKind.Block) { forEachReturnStatement(body, returnStatement => { if (returnStatement.expression) addIfImplementation(returnStatement.expression); @@ -1137,7 +1138,7 @@ namespace ts.FindAllReferences.Core { } } - function getContainingClassIfInHeritageClause(node: Node): ClassLikeDeclaration | InterfaceDeclaration { + function getContainingClassIfInHeritageClause(node: Node): ClassLikeDeclaration | InterfaceDeclaration | undefined { return isIdentifier(node) || isPropertyAccessExpression(node) ? getContainingClassIfInHeritageClause(node.parent) : isExpressionWithTypeArguments(node) ? tryCast(node.parent.parent, isClassLike) : undefined; } @@ -1202,7 +1203,7 @@ namespace ts.FindAllReferences.Core { return inherits; } - function getReferencesForSuperKeyword(superKeyword: Node): SymbolAndEntries[] { + function getReferencesForSuperKeyword(superKeyword: Node): SymbolAndEntries[] | undefined { let searchSpaceNode = getSuperContainer(superKeyword, /*stopOnFunctions*/ false); if (!searchSpaceNode) { return undefined; @@ -1242,7 +1243,7 @@ namespace ts.FindAllReferences.Core { return [{ definition: { type: "symbol", symbol: searchSpaceNode.symbol }, references }]; } - function getReferencesForThisKeyword(thisOrSuperKeyword: Node, sourceFiles: ReadonlyArray, cancellationToken: CancellationToken): SymbolAndEntries[] { + function getReferencesForThisKeyword(thisOrSuperKeyword: Node, sourceFiles: ReadonlyArray, cancellationToken: CancellationToken): SymbolAndEntries[] | undefined { let searchSpaceNode = getThisContainer(thisOrSuperKeyword, /* includeArrowFunctions */ false); // Whether 'this' occurs in a static context within a class. @@ -1421,7 +1422,7 @@ namespace ts.FindAllReferences.Core { const type = checker.getTypeAtLocation(typeReference); const propertySymbol = type && type.symbol && checker.getPropertyOfType(type, propertyName); // Visit the typeReference as well to see if it directly or indirectly uses that property - return propertySymbol && (firstDefined(checker.getRootSymbols(propertySymbol), cb) || recur(type.symbol)); + return propertySymbol && (firstDefined(checker.getRootSymbols(propertySymbol), cb) || recur(type!.symbol)); })); } } @@ -1434,16 +1435,16 @@ namespace ts.FindAllReferences.Core { ? rootSymbol && !(getCheckFlags(sym) & CheckFlags.Synthetic) ? rootSymbol : sym : undefined, /*allowBaseTypes*/ rootSymbol => - !(search.parents && !search.parents.some(parent => explicitlyInheritsFrom(rootSymbol.parent, parent, state.inheritsFromCache, checker)))); + !(search.parents && !search.parents.some(parent => explicitlyInheritsFrom(rootSymbol.parent!, parent, state.inheritsFromCache, checker)))); } /** Gets all symbols for one property. Does not get symbols for every property. */ function getPropertySymbolsFromContextualType(node: ObjectLiteralElement, checker: TypeChecker): ReadonlyArray { const contextualType = checker.getContextualType(node.parent); - const name = getNameFromPropertyName(node.name); + const name = getNameFromPropertyName(node.name!); const symbol = contextualType && name && contextualType.getProperty(name); return symbol ? [symbol] : - contextualType && contextualType.isUnion() ? mapDefined(contextualType.types, t => t.getProperty(name)) : emptyArray; + contextualType && contextualType.isUnion() ? mapDefined(contextualType.types, t => t.getProperty(name!)) : emptyArray; // TODO: GH#18217 } /** @@ -1489,11 +1490,11 @@ namespace ts.FindAllReferences.Core { } export function getReferenceEntriesForShorthandPropertyAssignment(node: Node, checker: TypeChecker, addReference: (node: Node) => void): void { - const refSymbol = checker.getSymbolAtLocation(node); + const refSymbol = checker.getSymbolAtLocation(node)!; const shorthandSymbol = checker.getShorthandAssignmentValueSymbol(refSymbol.valueDeclaration); if (shorthandSymbol) { - for (const declaration of shorthandSymbol.getDeclarations()) { + for (const declaration of shorthandSymbol.getDeclarations()!) { if (getMeaningFromDeclaration(declaration) & SemanticMeaning.Value) { addReference(declaration); } diff --git a/src/services/formatting/formatting.ts b/src/services/formatting/formatting.ts index b0273cc18e7a4..eeec4b15ea7a8 100644 --- a/src/services/formatting/formatting.ts +++ b/src/services/formatting/formatting.ts @@ -14,9 +14,9 @@ namespace ts.formatting { } export interface TokenInfo { - leadingTrivia: TextRangeWithTriviaKind[]; + leadingTrivia: TextRangeWithTriviaKind[] | undefined; token: TextRangeWithKind; - trailingTrivia: TextRangeWithTriviaKind[]; + trailingTrivia: TextRangeWithTriviaKind[] | undefined; } const enum Constants { @@ -120,7 +120,7 @@ namespace ts.formatting { * and we wouldn't want to move the closing brace. */ const textRange: TextRange = { - pos: getLineStartPositionForPosition(outermostNode.getStart(sourceFile), sourceFile), + pos: getLineStartPositionForPosition(outermostNode!.getStart(sourceFile), sourceFile), // TODO: GH#18217 end: position }; @@ -174,11 +174,11 @@ namespace ts.formatting { * Upon typing the closing curly, we want to format the entire `while`-statement, but not the preceding * variable declaration. */ - function findOutermostNodeWithinListLevel(node: Node) { + function findOutermostNodeWithinListLevel(node: Node | undefined) { let current = node; while (current && current.parent && - current.parent.end === node.end && + current.parent.end === node!.end && !isListElement(current.parent, current)) { current = current.parent; } @@ -195,7 +195,7 @@ namespace ts.formatting { return rangeContainsRange((parent).members, node); case SyntaxKind.ModuleDeclaration: const body = (parent).body; - return body && body.kind === SyntaxKind.ModuleBlock && rangeContainsRange(body.statements, node); + return !!body && body.kind === SyntaxKind.ModuleBlock && rangeContainsRange(body.statements, node); case SyntaxKind.SourceFile: case SyntaxKind.Block: case SyntaxKind.ModuleBlock: @@ -235,8 +235,8 @@ namespace ts.formatting { // pick only errors that fall in range const sorted = errors - .filter(d => rangeOverlapsWithStartEnd(originalRange, d.start, d.start + d.length)) - .sort((e1, e2) => e1.start - e2.start); + .filter(d => rangeOverlapsWithStartEnd(originalRange, d.start!, d.start! + d.length!)) // TODO: GH#18217 + .sort((e1, e2) => e1.start! - e2.start!); if (!sorted.length) { return rangeHasNoErrors; @@ -254,12 +254,12 @@ namespace ts.formatting { } const error = sorted[index]; - if (r.end <= error.start) { + if (r.end <= error.start!) { // specified range ends before the error refered by 'index' - no error in range return false; } - if (startEndOverlapsWithStartEnd(r.pos, r.end, error.start, error.start + error.length)) { + if (startEndOverlapsWithStartEnd(r.pos, r.end, error.start!, error.start! + error.length!)) { // specified range overlaps with error range return true; } @@ -316,7 +316,7 @@ namespace ts.formatting { */ function getOwnOrInheritedDelta(n: Node, options: FormatCodeSettings, sourceFile: SourceFile): number { let previousLine = Constants.Unknown; - let child: Node; + let child: Node | undefined; while (n) { const line = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)).line; if (previousLine !== Constants.Unknown && line !== previousLine) { @@ -324,7 +324,7 @@ namespace ts.formatting { } if (SmartIndenter.shouldIndentChildNode(options, n, child, sourceFile)) { - return options.indentSize; + return options.indentSize!; } previousLine = line; @@ -349,7 +349,7 @@ namespace ts.formatting { sourceFileLike)); } - function formatNodeLines(node: Node, sourceFile: SourceFile, formatContext: FormatContext, requestKind: FormattingRequestKind): TextChange[] { + function formatNodeLines(node: Node | undefined, sourceFile: SourceFile, formatContext: FormatContext, requestKind: FormattingRequestKind): TextChange[] { if (!node) { return []; } @@ -413,7 +413,7 @@ namespace ts.formatting { if (!formattingScanner.isOnToken()) { const leadingTrivia = formattingScanner.getCurrentLeadingTrivia(); if (leadingTrivia) { - processTrivia(leadingTrivia, enclosingNode, enclosingNode, /*dynamicIndentation*/ undefined); + processTrivia(leadingTrivia, enclosingNode, enclosingNode, /*dynamicIndentation*/ undefined!); // TODO: GH#18217 trimTrailingWhitespacesForRemainingRange(); } } @@ -465,7 +465,7 @@ namespace ts.formatting { parentDynamicIndentation: DynamicIndentation, effectiveParentStartLine: number ): { indentation: number, delta: number } { - const delta = SmartIndenter.shouldIndentChildNode(options, node) ? options.indentSize : 0; + const delta = SmartIndenter.shouldIndentChildNode(options, node) ? options.indentSize! : 0; if (effectiveParentStartLine === startLine) { // if node is located on the same line with the parent @@ -473,7 +473,7 @@ namespace ts.formatting { // - push children if either parent of node itself has non-zero delta return { indentation: startLine === lastIndentedLine ? indentationOnLastIndentedLine : parentDynamicIndentation.getIndentation(), - delta: Math.min(options.indentSize, parentDynamicIndentation.getDelta(node) + delta) + delta: Math.min(options.indentSize!, parentDynamicIndentation.getDelta(node) + delta) }; } else if (inheritedIndentation === Constants.Unknown) { @@ -537,8 +537,8 @@ namespace ts.formatting { getDelta, recomputeIndentation: lineAdded => { if (node.parent && SmartIndenter.shouldIndentChildNode(options, node.parent, node, sourceFile)) { - indentation += lineAdded ? options.indentSize : -options.indentSize; - delta = SmartIndenter.shouldIndentChildNode(options, node) ? options.indentSize : 0; + indentation += lineAdded ? options.indentSize! : -options.indentSize!; + delta = SmartIndenter.shouldIndentChildNode(options, node) ? options.indentSize! : 0; } } }; @@ -855,6 +855,7 @@ namespace ts.formatting { } } + // TODO: GH#18217 use an enum instead of `boolean | undefined` function processRange(range: TextRangeWithKind, rangeStart: LineAndCharacter, parent: Node, @@ -934,7 +935,7 @@ namespace ts.formatting { return lineAction; } - function insertIndentation(pos: number, indentation: number, lineAdded: boolean): void { + function insertIndentation(pos: number, indentation: number, lineAdded: boolean | undefined): void { const indentationString = getIndentationString(indentation, options); if (lineAdded) { // new line is added before the token by the formatting rules @@ -954,7 +955,7 @@ namespace ts.formatting { let column = 0; for (let i = 0; i < characterInLine; i++) { if (sourceFile.text.charCodeAt(startLinePosition + i) === CharacterCodes.tab) { - column += options.tabSize - column % options.tabSize; + column += options.tabSize! - column % options.tabSize!; } else { column++; @@ -1114,7 +1115,7 @@ namespace ts.formatting { // edit should not be applied if we have one line feed between elements const lineDelta = currentStartLine - previousStartLine; if (lineDelta !== 1) { - recordReplace(previousRange.end, currentRange.pos - previousRange.end, options.newLineCharacter); + recordReplace(previousRange.end, currentRange.pos - previousRange.end, options.newLineCharacter!); return onLaterLine ? LineAction.None : LineAction.LineAdded; } break; @@ -1231,8 +1232,8 @@ namespace ts.formatting { } let internedSizes: { tabSize: number; indentSize: number }; - let internedTabsIndentation: string[]; - let internedSpacesIndentation: string[]; + let internedTabsIndentation: string[] | undefined; + let internedSpacesIndentation: string[] | undefined; export function getIndentationString(indentation: number, options: EditorSettings): string { // reset interned strings if FormatCodeOptions were changed @@ -1240,13 +1241,13 @@ namespace ts.formatting { !internedSizes || (internedSizes.tabSize !== options.tabSize || internedSizes.indentSize !== options.indentSize); if (resetInternedStrings) { - internedSizes = { tabSize: options.tabSize, indentSize: options.indentSize }; + internedSizes = { tabSize: options.tabSize!, indentSize: options.indentSize! }; internedTabsIndentation = internedSpacesIndentation = undefined; } if (!options.convertTabsToSpaces) { - const tabs = Math.floor(indentation / options.tabSize); - const spaces = indentation - tabs * options.tabSize; + const tabs = Math.floor(indentation / options.tabSize!); + const spaces = indentation - tabs * options.tabSize!; let tabString: string; if (!internedTabsIndentation) { @@ -1264,14 +1265,14 @@ namespace ts.formatting { } else { let spacesString: string; - const quotient = Math.floor(indentation / options.indentSize); - const remainder = indentation % options.indentSize; + const quotient = Math.floor(indentation / options.indentSize!); + const remainder = indentation % options.indentSize!; if (!internedSpacesIndentation) { internedSpacesIndentation = []; } if (internedSpacesIndentation[quotient] === undefined) { - spacesString = repeatString(" ", options.indentSize * quotient); + spacesString = repeatString(" ", options.indentSize! * quotient); internedSpacesIndentation[quotient] = spacesString; } else { diff --git a/src/services/formatting/formattingContext.ts b/src/services/formatting/formattingContext.ts index 036cc64c98e3c..0ccf87680fee1 100644 --- a/src/services/formatting/formattingContext.ts +++ b/src/services/formatting/formattingContext.ts @@ -16,11 +16,11 @@ namespace ts.formatting { public currentTokenParent: Node; public nextTokenParent: Node; - private contextNodeAllOnSameLine: boolean; - private nextNodeAllOnSameLine: boolean; - private tokensAreOnSameLine: boolean; - private contextNodeBlockIsOnOneLine: boolean; - private nextNodeBlockIsOnOneLine: boolean; + private contextNodeAllOnSameLine: boolean | undefined; + private nextNodeAllOnSameLine: boolean | undefined; + private tokensAreOnSameLine: boolean | undefined; + private contextNodeBlockIsOnOneLine: boolean | undefined; + private nextNodeBlockIsOnOneLine: boolean | undefined; constructor(public readonly sourceFile: SourceFileLike, public formattingRequestKind: FormattingRequestKind, public options: FormatCodeSettings) { } diff --git a/src/services/formatting/formattingScanner.ts b/src/services/formatting/formattingScanner.ts index a53a1e5ce269f..2787f90af03a5 100644 --- a/src/services/formatting/formattingScanner.ts +++ b/src/services/formatting/formattingScanner.ts @@ -7,7 +7,7 @@ namespace ts.formatting { advance(): void; isOnToken(): boolean; readTokenInfo(n: Node): TokenInfo; - getCurrentLeadingTrivia(): TextRangeWithKind[]; + getCurrentLeadingTrivia(): TextRangeWithKind[] | undefined; lastTrailingTriviaWasNewLine(): boolean; skipToEndOf(node: Node): void; } @@ -54,7 +54,7 @@ namespace ts.formatting { const isStarted = scanner.getStartPos() !== startPos; if (isStarted) { - wasNewLine = trailingTrivia && lastOrUndefined(trailingTrivia)!.kind === SyntaxKind.NewLineTrivia; + wasNewLine = !!trailingTrivia && last(trailingTrivia).kind === SyntaxKind.NewLineTrivia; } else { scanner.scan(); diff --git a/src/services/formatting/rules.ts b/src/services/formatting/rules.ts index 901dbf761f3ee..5e64119fcb1df 100644 --- a/src/services/formatting/rules.ts +++ b/src/services/formatting/rules.ts @@ -677,7 +677,7 @@ namespace ts.formatting { function isEndOfDecoratorContextOnSameLine(context: FormattingContext): boolean { return context.TokensAreOnSameLine() && - context.contextNode.decorators && + !!context.contextNode.decorators && nodeIsInDecoratorContext(context.currentTokenParent) && !nodeIsInDecoratorContext(context.nextTokenParent); } diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index 31e04f14eb767..8602347244fbf 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -111,6 +111,7 @@ namespace ts.formatting { // if such node is found - compute initial indentation for 'position' inside this node let previous: Node | undefined; let current = precedingToken; + while (current) { if (positionBelongsToNode(current, position, sourceFile) && shouldIndentChildNode(options, current, previous, sourceFile, /*isNextChild*/ true)) { const currentStart = getStartLineAndCharacterForNode(current, sourceFile); @@ -119,7 +120,7 @@ namespace ts.formatting { // handle cases when codefix is about to be inserted before the close brace ? assumeNewLineBeforeCloseBrace && nextTokenKind === NextTokenKind.CloseBrace ? options.indentSize : 0 : lineAtPosition !== currentStart.line ? options.indentSize : 0; - return getIndentationForNodeWorker(current, currentStart, /*ignoreActualIndentationRange*/ undefined, indentationDelta, sourceFile, /*isNextChild*/ true, options); + return getIndentationForNodeWorker(current, currentStart, /*ignoreActualIndentationRange*/ undefined, indentationDelta!, sourceFile, /*isNextChild*/ true, options); // TODO: GH#18217 } // check if current node is a list item - if yes, take indentation from it @@ -129,7 +130,7 @@ namespace ts.formatting { } actualIndentation = getLineIndentationWhenExpressionIsInMultiLine(current, sourceFile, options); if (actualIndentation !== Value.Unknown) { - return actualIndentation + options.indentSize; + return actualIndentation + options.indentSize!; // TODO: GH#18217 } previous = current; @@ -151,12 +152,13 @@ namespace ts.formatting { function getIndentationForNodeWorker( current: Node, currentStart: LineAndCharacter, - ignoreActualIndentationRange: TextRange, + ignoreActualIndentationRange: TextRange | undefined, indentationDelta: number, sourceFile: SourceFile, isNextChild: boolean, options: EditorSettings): number { - let parent = current.parent!; + let parent = current.parent; + // Walk up the tree and collect indentation for parent-child node pairs. Indentation is not added if // * parent and child nodes start on the same line, or // * parent is an IfStatement and child starts on the same line as an 'else clause'. @@ -194,7 +196,7 @@ namespace ts.formatting { // increase indentation if parent node wants its content to be indented and parent and child nodes don't start on the same line if (shouldIndentChildNode(options, parent, current, sourceFile, isNextChild) && !parentAndChildShareLine) { - indentationDelta += options.indentSize; + indentationDelta += options.indentSize!; } // In our AST, a call argument's `parent` is the call-expression, not the argument list. @@ -311,7 +313,7 @@ namespace ts.formatting { export function childStartsOnTheSameLineWithElseInIfStatement(parent: Node, child: TextRangeWithKind, childStartLine: number, sourceFile: SourceFileLike): boolean { if (parent.kind === SyntaxKind.IfStatement && (parent).elseStatement === child) { - const elseKeyword = findChildOfKind(parent, SyntaxKind.ElseKeyword, sourceFile); + const elseKeyword = findChildOfKind(parent, SyntaxKind.ElseKeyword, sourceFile)!; Debug.assert(elseKeyword !== undefined); const elseKeywordStartLine = getStartLineAndCharacterForNode(elseKeyword, sourceFile).line; @@ -321,11 +323,11 @@ namespace ts.formatting { return false; } - function getListIfStartEndIsInListRange(list: NodeArray, start: number, end: number) { + function getListIfStartEndIsInListRange(list: NodeArray | undefined, start: number, end: number) { return list && rangeContainsStartEnd(list, start, end) ? list : undefined; } - export function getContainingList(node: Node, sourceFile: SourceFile): NodeArray { + export function getContainingList(node: Node, sourceFile: SourceFile): NodeArray | undefined { if (node.parent) { const { end } = node; switch (node.parent.kind) { @@ -467,7 +469,7 @@ namespace ts.formatting { } if (ch === CharacterCodes.tab) { - column += options.tabSize + (column % options.tabSize); + column += options.tabSize! + (column % options.tabSize!); } else { column++; @@ -482,7 +484,7 @@ namespace ts.formatting { return findFirstNonWhitespaceCharacterAndColumn(startPos, endPos, sourceFile, options).column; } - export function nodeWillIndentChild(settings: FormatCodeSettings | undefined, parent: TextRangeWithKind, child: TextRangeWithKind | undefined, sourceFile: SourceFileLike | undefined, indentByDefault: boolean): boolean { + export function nodeWillIndentChild(settings: FormatCodeSettings, parent: TextRangeWithKind, child: TextRangeWithKind | undefined, sourceFile: SourceFileLike | undefined, indentByDefault: boolean): boolean { const childKind = child ? child.kind : SyntaxKind.Unknown; switch (parent.kind) { @@ -533,8 +535,8 @@ namespace ts.formatting { return true; case SyntaxKind.VariableDeclaration: case SyntaxKind.PropertyAssignment: - if (!settings.indentMultiLineObjectLiteralBeginningOnBlankLine && sourceFile && childKind === SyntaxKind.ObjectLiteralExpression) { - return rangeIsOnOneLine(sourceFile, child); + if (!settings.indentMultiLineObjectLiteralBeginningOnBlankLine && sourceFile && childKind === SyntaxKind.ObjectLiteralExpression) { // TODO: GH#18217 + return rangeIsOnOneLine(sourceFile, child!); } return true; case SyntaxKind.DoStatement: @@ -555,7 +557,7 @@ namespace ts.formatting { return childKind !== SyntaxKind.NamedExports; case SyntaxKind.ImportDeclaration: return childKind !== SyntaxKind.ImportClause || - (!!(child).namedBindings && (child).namedBindings.kind !== SyntaxKind.NamedImports); + (!!(child).namedBindings && (child).namedBindings!.kind !== SyntaxKind.NamedImports); case SyntaxKind.JsxElement: return childKind !== SyntaxKind.JsxClosingElement; case SyntaxKind.JsxFragment: @@ -594,7 +596,7 @@ namespace ts.formatting { * True when the parent node should indent the given child by an explicit rule. * @param isNextChild If true, we are judging indent of a hypothetical child *after* this one, not the current child. */ - export function shouldIndentChildNode(settings: FormatCodeSettings | undefined, parent: TextRangeWithKind, child?: Node, sourceFile?: SourceFileLike, isNextChild = false): boolean { + export function shouldIndentChildNode(settings: FormatCodeSettings, parent: TextRangeWithKind, child?: Node, sourceFile?: SourceFileLike, isNextChild = false): boolean { return nodeWillIndentChild(settings, parent, child, sourceFile, /*indentByDefault*/ false) && !(isNextChild && child && isControlFlowEndingStatement(child.kind, parent)); } diff --git a/src/services/getEditsForFileRename.ts b/src/services/getEditsForFileRename.ts index d05d22a98d952..7c71f9a6ed86d 100644 --- a/src/services/getEditsForFileRename.ts +++ b/src/services/getEditsForFileRename.ts @@ -16,6 +16,7 @@ namespace ts { function updateTsconfigFiles(program: Program, changeTracker: textChanges.ChangeTracker, oldFilePath: string, newFilePath: string): void { const configFile = program.getCompilerOptions().configFile; + if (!configFile) return; const oldFile = getTsConfigPropArrayElementValue(configFile, "files", oldFilePath); if (oldFile) { changeTracker.replaceRangeWithText(configFile, createStringRange(oldFile, configFile), newFilePath); diff --git a/src/services/goToDefinition.ts b/src/services/goToDefinition.ts index cda61134b8789..1b9ecf0b5f00d 100644 --- a/src/services/goToDefinition.ts +++ b/src/services/goToDefinition.ts @@ -10,11 +10,12 @@ namespace ts.GoToDefinition { if (node === sourceFile) { return undefined; } + const { parent } = node; // Labels if (isJumpStatementTarget(node)) { const label = getTargetLabel(node.parent, node.text); - return label ? [createDefinitionInfoFromName(label, ScriptElementKind.label, node.text, /*containerName*/ undefined)] : undefined; + return label ? [createDefinitionInfoFromName(label, ScriptElementKind.label, node.text, /*containerName*/ undefined!)] : undefined; // TODO: GH#18217 } const typeChecker = program.getTypeChecker(); @@ -33,9 +34,9 @@ namespace ts.GoToDefinition { // If this is the original constructor definition, parent is the class. return typeChecker.getRootSymbols(symbol).some(s => calledDeclaration.symbol === s || calledDeclaration.symbol.parent === s) || // TODO: GH#23742 Following check shouldn't be necessary if 'require' is an alias - symbol.declarations.some(d => isVariableDeclaration(d) && d.initializer && isRequireCall(d.initializer, /*checkArgumentIsStringLiteralLike*/ false)) + symbol.declarations.some(d => isVariableDeclaration(d) && !!d.initializer && isRequireCall(d.initializer, /*checkArgumentIsStringLiteralLike*/ false)) ? [sigInfo] - : [sigInfo, ...getDefinitionFromSymbol(typeChecker, symbol, node)]; + : [sigInfo, ...getDefinitionFromSymbol(typeChecker, symbol, node)!]; } // Because name in short-hand property assignment has two different meanings: property name and property value, @@ -59,9 +60,9 @@ namespace ts.GoToDefinition { // pr/*destination*/op1: number // } // bar(({pr/*goto*/op1})=>{}); - if (isPropertyName(node) && isBindingElement(node.parent) && isObjectBindingPattern(node.parent.parent) && - (node === (node.parent.propertyName || node.parent.name))) { - const type = typeChecker.getTypeAtLocation(node.parent.parent); + if (isPropertyName(node) && isBindingElement(parent) && isObjectBindingPattern(parent.parent) && + (node === (parent.propertyName || parent.name))) { + const type = typeChecker.getTypeAtLocation(parent.parent); if (type) { const propSymbols = getPropertySymbolsFromType(type, node); if (propSymbols) { @@ -97,7 +98,7 @@ namespace ts.GoToDefinition { const typeReferenceDirective = findReferenceInPosition(sourceFile.typeReferenceDirectives, position); if (typeReferenceDirective) { const reference = program.getResolvedTypeReferenceDirectives().get(typeReferenceDirective.fileName); - const file = reference && program.getSourceFile(reference.resolvedFileName); + const file = reference && program.getSourceFile(reference.resolvedFileName!); // TODO:GH#18217 return file && { fileName: typeReferenceDirective.fileName, file }; } @@ -105,7 +106,7 @@ namespace ts.GoToDefinition { } /// Goto type - export function getTypeDefinitionAtPosition(typeChecker: TypeChecker, sourceFile: SourceFile, position: number): DefinitionInfo[] { + export function getTypeDefinitionAtPosition(typeChecker: TypeChecker, sourceFile: SourceFile, position: number): DefinitionInfo[] | undefined { const node = getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true); if (node === sourceFile) { return undefined; @@ -124,7 +125,7 @@ namespace ts.GoToDefinition { return type.symbol && getDefinitionFromSymbol(typeChecker, type.symbol, node); } - export function getDefinitionAndBoundSpan(program: Program, sourceFile: SourceFile, position: number): DefinitionInfoAndBoundSpan { + export function getDefinitionAndBoundSpan(program: Program, sourceFile: SourceFile, position: number): DefinitionInfoAndBoundSpan | undefined { const definitions = getDefinitionAtPosition(program, sourceFile, position); if (!definitions || definitions.length === 0) { @@ -146,7 +147,7 @@ namespace ts.GoToDefinition { // At 'x.foo', see if the type of 'x' has an index signature, and if so find its declarations. function getDefinitionInfoForIndexSignatures(node: Node, checker: TypeChecker): DefinitionInfo[] | undefined { if (!isPropertyAccessExpression(node.parent) || node.parent.name !== node) return; - const type = checker.getTypeAtLocation(node.parent.expression); + const type = checker.getTypeAtLocation(node.parent.expression)!; return mapDefined(type.isUnionOrIntersection() ? type.types : [type], nonUnionType => { const info = checker.getIndexInfoOfType(nonUnionType, IndexKind.String); return info && info.declaration && createDefinitionFromSignatureDeclaration(checker, info.declaration); @@ -191,7 +192,7 @@ namespace ts.GoToDefinition { } } - function getDefinitionFromSymbol(typeChecker: TypeChecker, symbol: Symbol, node: Node): DefinitionInfo[] { + function getDefinitionFromSymbol(typeChecker: TypeChecker, symbol: Symbol, node: Node): DefinitionInfo[] | undefined { return getConstructSignatureDefinition() || getCallSignatureDefinition() || map(symbol.declarations, declaration => createDefinitionInfo(declaration, typeChecker, symbol, node)); function getConstructSignatureDefinition(): DefinitionInfo[] | undefined { @@ -237,7 +238,7 @@ namespace ts.GoToDefinition { textSpan: createTextSpanFromNode(name, sourceFile), kind: symbolKind, name: symbolName, - containerKind: undefined, + containerKind: undefined!, // TODO: GH#18217 containerName }; } @@ -256,8 +257,8 @@ namespace ts.GoToDefinition { textSpan: createTextSpanFromBounds(0, 0), kind: ScriptElementKind.scriptElement, name, - containerName: undefined, - containerKind: undefined + containerName: undefined!, + containerKind: undefined!, // TODO: GH#18217 }; } @@ -265,7 +266,7 @@ namespace ts.GoToDefinition { function getAncestorCallLikeExpression(node: Node): CallLikeExpression | undefined { const target = climbPastManyPropertyAccesses(node); const callLike = target.parent; - return callLike && isCallLikeExpression(callLike) && getInvokedExpression(callLike) === target && callLike; + return callLike && isCallLikeExpression(callLike) && getInvokedExpression(callLike) === target ? callLike : undefined; } function climbPastManyPropertyAccesses(node: Node): Node { diff --git a/src/services/importTracker.ts b/src/services/importTracker.ts index 4f9836dfdf641..75b96c48caf31 100644 --- a/src/services/importTracker.ts +++ b/src/services/importTracker.ts @@ -49,7 +49,7 @@ namespace ts.FindAllReferences { const markSeenIndirectUser = nodeSeenTracker(); const directImports: Importer[] = []; const isAvailableThroughGlobal = !!exportingModuleSymbol.globalExports; - const indirectUserDeclarations: SourceFileLike[] = isAvailableThroughGlobal ? undefined : []; + const indirectUserDeclarations: SourceFileLike[] | undefined = isAvailableThroughGlobal ? undefined : []; handleDirectImports(exportingModuleSymbol); @@ -69,7 +69,7 @@ namespace ts.FindAllReferences { } // This may return duplicates (if there are multiple module declarations in a single source file, all importing the same thing as a namespace), but `State.markSearchedSymbol` will handle that. - return indirectUserDeclarations.map(getSourceFileOfNode); + return indirectUserDeclarations!.map(getSourceFileOfNode); } function handleDirectImports(exportingModuleSymbol: Symbol): void { @@ -85,7 +85,7 @@ namespace ts.FindAllReferences { switch (direct.kind) { case SyntaxKind.CallExpression: if (!isAvailableThroughGlobal) { - const parent = direct.parent!; + const parent = direct.parent; if (exportKind === ExportKind.ExportEquals && parent.kind === SyntaxKind.VariableDeclaration) { const { name } = parent as VariableDeclaration; if (name.kind === SyntaxKind.Identifier) { @@ -166,7 +166,7 @@ namespace ts.FindAllReferences { Debug.assert(!isAvailableThroughGlobal); const isNew = markSeenIndirectUser(sourceFileLike); if (isNew) { - indirectUserDeclarations.push(sourceFileLike); + indirectUserDeclarations!.push(sourceFileLike); // TODO: GH#18217 } return isNew; } @@ -238,7 +238,7 @@ namespace ts.FindAllReferences { } // Ignore if there's a grammar error - if (decl.moduleSpecifier.kind !== SyntaxKind.StringLiteral) { + if (decl.moduleSpecifier!.kind !== SyntaxKind.StringLiteral) { return; } @@ -259,7 +259,7 @@ namespace ts.FindAllReferences { } if (exportKind === ExportKind.Named) { - searchForNamedImport(namedBindings as NamedImports | undefined); + searchForNamedImport(namedBindings as NamedImports | undefined); // tslint:disable-line no-unnecessary-type-assertion (TODO: GH#18217) } else { // `export =` might be imported by a default import if `--allowSyntheticDefaultImports` is on, so this handles both ExportKind.Default and ExportKind.ExportEquals @@ -267,13 +267,13 @@ namespace ts.FindAllReferences { // If a default import has the same name as the default export, allow to rename it. // Given `import f` and `export default function f`, we will rename both, but for `import g` we will rename just that. if (name && (!isForRename || name.escapedText === symbolEscapedNameNoDefault(exportSymbol))) { - const defaultImportAlias = checker.getSymbolAtLocation(name); + const defaultImportAlias = checker.getSymbolAtLocation(name)!; addSearch(name, defaultImportAlias); } // 'default' might be accessed as a named import `{ default as foo }`. if (exportKind === ExportKind.Default) { - searchForNamedImport(namedBindings as NamedImports | undefined); + searchForNamedImport(namedBindings); } } } @@ -286,7 +286,7 @@ namespace ts.FindAllReferences { function handleNamespaceImportLike(importName: Identifier): void { // Don't rename an import that already has a different name than the export. if (exportKind === ExportKind.ExportEquals && (!isForRename || isNameMatch(importName.escapedText))) { - addSearch(importName, checker.getSymbolAtLocation(importName)); + addSearch(importName, checker.getSymbolAtLocation(importName)!); } } @@ -308,13 +308,13 @@ namespace ts.FindAllReferences { // But do rename `foo` in ` { default as foo }` if that's the original export name. if (!isForRename || name.escapedText === exportSymbol.escapedName) { // Search locally for `bar`. - addSearch(name, checker.getSymbolAtLocation(name)); + addSearch(name, checker.getSymbolAtLocation(name)!); } } else { const localSymbol = element.kind === SyntaxKind.ExportSpecifier && element.propertyName - ? checker.getExportSpecifierLocalTargetSymbol(element) // For re-exporting under a different name, we want to get the re-exported symbol. - : checker.getSymbolAtLocation(name); + ? checker.getExportSpecifierLocalTargetSymbol(element)! // For re-exporting under a different name, we want to get the re-exported symbol. + : checker.getSymbolAtLocation(name)!; addSearch(name, localSymbol); } } @@ -330,7 +330,7 @@ namespace ts.FindAllReferences { function findNamespaceReExports(sourceFileLike: SourceFileLike, name: Identifier, checker: TypeChecker): boolean { const namespaceImportSymbol = checker.getSymbolAtLocation(name); - return forEachPossibleImportOrExportStatement(sourceFileLike, statement => { + return !!forEachPossibleImportOrExportStatement(sourceFileLike, statement => { if (!isExportDeclaration(statement)) return; const { exportClause, moduleSpecifier } = statement; return !moduleSpecifier && exportClause && @@ -395,8 +395,8 @@ namespace ts.FindAllReferences { } /** Iterates over all statements at the top level or in module declarations. Returns the first truthy result. */ - function forEachPossibleImportOrExportStatement(sourceFileLike: SourceFileLike, action: (statement: Statement) => T): T { - return forEach(sourceFileLike.kind === SyntaxKind.SourceFile ? sourceFileLike.statements : sourceFileLike.body.statements, statement => + function forEachPossibleImportOrExportStatement(sourceFileLike: SourceFileLike, action: (statement: Statement) => T): T | undefined { + return forEach(sourceFileLike.kind === SyntaxKind.SourceFile ? sourceFileLike.statements : sourceFileLike.body!.statements, statement => // TODO: GH#18217 action(statement) || (isAmbientModuleDeclaration(statement) && forEach(statement.body && statement.body.statements, action))); } @@ -453,13 +453,14 @@ namespace ts.FindAllReferences { return comingFromExport ? getExport() : getExport() || getImport(); function getExport(): ExportedSymbol | ImportedSymbol | undefined { - const parent = node.parent!; + const { parent } = node; + const grandParent = parent.parent; if (symbol.exportSymbol) { if (parent.kind === SyntaxKind.PropertyAccessExpression) { // When accessing an export of a JS module, there's no alias. The symbol will still be flagged as an export even though we're at the use. // So check that we are at the declaration. - return symbol.declarations.some(d => d === parent) && isBinaryExpression(parent.parent) - ? getSpecialPropertyExport(parent.parent, /*useLhsSymbol*/ false) + return symbol.declarations.some(d => d === parent) && isBinaryExpression(grandParent) + ? getSpecialPropertyExport(grandParent, /*useLhsSymbol*/ false) : undefined; } else { @@ -475,7 +476,7 @@ namespace ts.FindAllReferences { return undefined; } - const lhsSymbol = checker.getSymbolAtLocation(exportNode.name); + const lhsSymbol = checker.getSymbolAtLocation(exportNode.name)!; return { kind: ImportExport.Import, symbol: lhsSymbol, isNamedImport: false }; } else { @@ -487,15 +488,15 @@ namespace ts.FindAllReferences { return getExportAssignmentExport(parent); } // If we are in `export = class A {};` (or `export = class A {};`) at `A`, `parent.parent` is the export assignment. - else if (isExportAssignment(parent.parent)) { - return getExportAssignmentExport(parent.parent); + else if (isExportAssignment(grandParent)) { + return getExportAssignmentExport(grandParent); } // Similar for `module.exports =` and `exports.A =`. else if (isBinaryExpression(parent)) { return getSpecialPropertyExport(parent, /*useLhsSymbol*/ true); } - else if (isBinaryExpression(parent.parent)) { - return getSpecialPropertyExport(parent.parent, /*useLhsSymbol*/ true); + else if (isBinaryExpression(grandParent)) { + return getSpecialPropertyExport(grandParent, /*useLhsSymbol*/ true); } else if (isJSDocTypedefTag(parent)) { return exportInfo(symbol, ExportKind.Named); @@ -524,8 +525,8 @@ namespace ts.FindAllReferences { const sym = useLhsSymbol ? checker.getSymbolAtLocation(cast(node.left, isPropertyAccessExpression).name) : symbol; // Better detection for GH#20803 - if (sym && !(checker.getMergedSymbol(sym.parent).flags & SymbolFlags.Module)) { - Debug.fail(`Special property assignment kind does not have a module as its parent. Assignment is ${Debug.showSymbol(sym)}, parent is ${Debug.showSymbol(sym.parent)}`); + if (sym && !(checker.getMergedSymbol(sym.parent!).flags & SymbolFlags.Module)) { + Debug.fail(`Special property assignment kind does not have a module as its parent. Assignment is ${Debug.showSymbol(sym)}, parent is ${Debug.showSymbol(sym.parent!)}`); } return sym && exportInfo(sym, kind); } @@ -555,13 +556,13 @@ namespace ts.FindAllReferences { } } - function exportInfo(symbol: Symbol, kind: ExportKind): ExportedSymbol { + function exportInfo(symbol: Symbol, kind: ExportKind): ExportedSymbol | undefined { const exportInfo = getExportInfo(symbol, kind, checker); return exportInfo && { kind: ImportExport.Export, symbol, exportInfo }; } // Not meant for use with export specifiers or export assignment. - function getExportKindForDeclaration(node: Node): ExportKind | undefined { + function getExportKindForDeclaration(node: Node): ExportKind { return hasModifier(node, ModifierFlags.Default) ? ExportKind.Default : ExportKind.Named; } } @@ -627,7 +628,7 @@ namespace ts.FindAllReferences { if (symbol.declarations) { for (const declaration of symbol.declarations) { if (isExportSpecifier(declaration) && !declaration.propertyName && !declaration.parent.parent.moduleSpecifier) { - return checker.getExportSpecifierLocalTargetSymbol(declaration); + return checker.getExportSpecifierLocalTargetSymbol(declaration)!; } } } @@ -644,7 +645,6 @@ namespace ts.FindAllReferences { } const { parent } = node; - if (parent.kind === SyntaxKind.SourceFile) { return parent as SourceFile; } diff --git a/src/services/jsDoc.ts b/src/services/jsDoc.ts index c8958ad3d2f57..59251fe38b86b 100644 --- a/src/services/jsDoc.ts +++ b/src/services/jsDoc.ts @@ -99,7 +99,7 @@ namespace ts.JsDoc { case SyntaxKind.JSDocTemplateTag: return withList((tag as JSDocTemplateTag).typeParameters); case SyntaxKind.JSDocTypeTag: - return withNode((tag as JSDocTypeTag).typeExpression); + return withNode((tag as JSDocTypeTag).typeExpression!); case SyntaxKind.JSDocTypedefTag: case SyntaxKind.JSDocCallbackTag: case SyntaxKind.JSDocPropertyTag: @@ -128,7 +128,7 @@ namespace ts.JsDoc { * returns a truthy value, then returns that value. * If no such value is found, the callback is applied to each element of array and undefined is returned. */ - function forEachUnique(array: ReadonlyArray, callback: (element: T, index: number) => U): U { + function forEachUnique(array: ReadonlyArray | undefined, callback: (element: T, index: number) => U): U | undefined { if (array) { for (let i = 0; i < array.length; i++) { if (array.indexOf(array[i]) === i) { @@ -191,7 +191,7 @@ namespace ts.JsDoc { if (!isIdentifier(param.name)) return undefined; const name = param.name.text; - if (jsdoc.tags.some(t => t !== tag && isJSDocParameterTag(t) && isIdentifier(t.name) && t.name.escapedText === name) + if (jsdoc.tags!.some(t => t !== tag && isJSDocParameterTag(t) && isIdentifier(t.name) && t.name.escapedText === name) // TODO: GH#18217 || nameThusFar !== undefined && !startsWith(name, nameThusFar)) { return undefined; } @@ -326,7 +326,7 @@ namespace ts.JsDoc { const varStatement = commentOwner; const varDeclarations = varStatement.declarationList.declarations; const parameters = varDeclarations.length === 1 && varDeclarations[0].initializer - ? getParametersFromRightHandSideOfAssignment(varDeclarations[0].initializer) + ? getParametersFromRightHandSideOfAssignment(varDeclarations[0].initializer!) : undefined; return { commentOwner, parameters }; } @@ -371,7 +371,7 @@ namespace ts.JsDoc { return (rightHandSide).parameters; case SyntaxKind.ClassExpression: { const ctr = find((rightHandSide as ClassExpression).members, isConstructorDeclaration); - return ctr && ctr.parameters; + return ctr ? ctr.parameters : emptyArray; } } diff --git a/src/services/jsTyping.ts b/src/services/jsTyping.ts index c6f97ec2a1acb..539099510f137 100644 --- a/src/services/jsTyping.ts +++ b/src/services/jsTyping.ts @@ -5,7 +5,7 @@ namespace ts.JsTyping { directoryExists(path: string): boolean; fileExists(fileName: string): boolean; readFile(path: string, encoding?: string): string | undefined; - readDirectory(rootDir: string, extensions: ReadonlyArray, excludes: ReadonlyArray, includes: ReadonlyArray, depth?: number): string[]; + readDirectory(rootDir: string, extensions: ReadonlyArray, excludes: ReadonlyArray | undefined, includes: ReadonlyArray | undefined, depth?: number): string[]; } interface PackageJson { @@ -26,7 +26,7 @@ namespace ts.JsTyping { /* @internal */ export function isTypingUpToDate(cachedTyping: CachedTyping, availableTypingVersions: MapLike) { - const availableVersion = Semver.parse(getProperty(availableTypingVersions, `ts${versionMajorMinor}`) || getProperty(availableTypingVersions, "latest")); + const availableVersion = Semver.parse(getProperty(availableTypingVersions, `ts${versionMajorMinor}`) || getProperty(availableTypingVersions, "latest")!); return !availableVersion.greaterThan(cachedTyping.version); } @@ -152,7 +152,7 @@ namespace ts.JsTyping { // add typings for unresolved imports if (unresolvedImports) { - const module = deduplicate( + const module = deduplicate( unresolvedImports.map(moduleId => nodeCoreModules.has(moduleId) ? "node" : moduleId), equateStringsCaseSensitive, compareStringsCaseSensitive); @@ -160,7 +160,7 @@ namespace ts.JsTyping { } // Add the cached typing locations for inferred typings that are already installed packageNameToTypingLocation.forEach((typing, name) => { - if (inferredTypings.has(name) && inferredTypings.get(name) === undefined && isTypingUpToDate(typing, typesRegistry.get(name))) { + if (inferredTypings.has(name) && inferredTypings.get(name) === undefined && isTypingUpToDate(typing, typesRegistry.get(name)!)) { inferredTypings.set(name, typing.typingLocation); } }); @@ -187,7 +187,7 @@ namespace ts.JsTyping { function addInferredTyping(typingName: string) { if (!inferredTypings.has(typingName)) { - inferredTypings.set(typingName, undefined); + inferredTypings.set(typingName, undefined!); // TODO: GH#18217 } } function addInferredTypings(typingNames: ReadonlyArray, message: string) { @@ -344,7 +344,7 @@ namespace ts.JsTyping { case PackageNameValidationResult.Ok: return Debug.fail(); // Shouldn't have called this. default: - Debug.assertNever(result); + throw Debug.assertNever(result); } } } diff --git a/src/services/navigateTo.ts b/src/services/navigateTo.ts index 84c299abf6135..723d7f59b3aab 100644 --- a/src/services/navigateTo.ts +++ b/src/services/navigateTo.ts @@ -8,7 +8,7 @@ namespace ts.NavigateTo { declaration: Declaration; } - export function getNavigateToItems(sourceFiles: ReadonlyArray, checker: TypeChecker, cancellationToken: CancellationToken, searchValue: string, maxResultCount: number, excludeDtsFiles: boolean): NavigateToItem[] { + export function getNavigateToItems(sourceFiles: ReadonlyArray, checker: TypeChecker, cancellationToken: CancellationToken, searchValue: string, maxResultCount: number | undefined, excludeDtsFiles: boolean): NavigateToItem[] { const patternMatcher = createPatternMatcher(searchValue); if (!patternMatcher) return emptyArray; let rawItems: RawNavigateToItem[] = []; @@ -45,7 +45,7 @@ namespace ts.NavigateTo { if (!shouldKeepItem(declaration, checker)) continue; if (patternMatcher.patternContainsDots) { - const fullMatch = patternMatcher.getFullMatch(getContainers(declaration), name); + const fullMatch = patternMatcher.getFullMatch(getContainers(declaration)!, name); // TODO: GH#18217 if (fullMatch) { rawItems.push({ name, fileName, matchKind: fullMatch.kind, isCaseSensitive: fullMatch.isCaseSensitive, declaration }); } @@ -62,7 +62,7 @@ namespace ts.NavigateTo { case SyntaxKind.ImportClause: case SyntaxKind.ImportSpecifier: case SyntaxKind.ImportEqualsDeclaration: - const importer = checker.getSymbolAtLocation((declaration as ImportClause | ImportSpecifier | ImportEqualsDeclaration).name); + const importer = checker.getSymbolAtLocation((declaration as ImportClause | ImportSpecifier | ImportEqualsDeclaration).name!)!; const imported = checker.getAliasedSymbol(importer); return importer.escapedName !== imported.escapedName; default: @@ -118,14 +118,14 @@ namespace ts.NavigateTo { } // Now, walk up our containers, adding all their names to the container array. - declaration = getContainerNode(declaration); + let container = getContainerNode(declaration); - while (declaration) { - if (!tryAddSingleDeclarationName(declaration, containers)) { + while (container) { + if (!tryAddSingleDeclarationName(container, containers)) { return undefined; } - declaration = getContainerNode(declaration); + container = getContainerNode(container); } return containers; @@ -151,7 +151,7 @@ namespace ts.NavigateTo { textSpan: createTextSpanFromNode(declaration), // TODO(jfreeman): What should be the containerName when the container has a computed name? containerName: containerName ? (containerName).text : "", - containerKind: containerName ? getNodeKind(container) : ScriptElementKind.unknown + containerKind: containerName ? getNodeKind(container!) : ScriptElementKind.unknown // TODO: GH#18217 Just use `container ? ...` }; } } diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index 3ce18b9100256..0ce64d786e14f 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -65,10 +65,10 @@ namespace ts.NavigationBar { } function reset() { - curSourceFile = undefined; - curCancellationToken = undefined; + curSourceFile = undefined!; + curCancellationToken = undefined!; parentsStack = []; - parent = undefined; + parent = undefined!; emptyChildItemArray = []; } @@ -134,17 +134,17 @@ namespace ts.NavigationBar { mergeChildren(parent.children); sortChildren(parent.children); } - parent = parentsStack.pop(); + parent = parentsStack.pop()!; } - function addNodeWithRecursiveChild(node: Node, child: Node): void { + function addNodeWithRecursiveChild(node: Node, child: Node | undefined): void { startNode(node); addChildrenRecursively(child); endNode(); } /** Look for navigation bar items in node's subtree, adding them to the current `parent`. */ - function addChildrenRecursively(node: Node): void { + function addChildrenRecursively(node: Node | undefined): void { curCancellationToken.throwIfCancellationRequested(); if (!node || isToken(node)) { @@ -367,7 +367,8 @@ namespace ts.NavigationBar { // We use 1 NavNode to represent 'A.B.C', but there are multiple source nodes. // Only merge module nodes that have the same chain. Don't merge 'A.B.C' with 'A'! function areSameModule(a: ModuleDeclaration, b: ModuleDeclaration): boolean { - return a.body.kind === b.body.kind && (a.body.kind !== SyntaxKind.ModuleDeclaration || areSameModule(a.body, b.body)); + // TODO: GH#18217 + return a.body!.kind === b.body!.kind && (a.body!.kind !== SyntaxKind.ModuleDeclaration || areSameModule(a.body, b.body)); } /** Merge source into target. Source should be thrown away after this is called. */ @@ -391,7 +392,7 @@ namespace ts.NavigationBar { } function compareChildren(child1: NavigationBarNode, child2: NavigationBarNode) { - return compareStringsCaseSensitiveUI(tryGetName(child1.node), tryGetName(child2.node)) + return compareStringsCaseSensitiveUI(tryGetName(child1.node)!, tryGetName(child2.node)!) // TODO: GH#18217 || compareValues(navigationBarNodeKind(child1), navigationBarNodeKind(child2)); } @@ -407,7 +408,7 @@ namespace ts.NavigationBar { const declName = getNameOfDeclaration(node); if (declName) { - return unescapeLeadingUnderscores(getPropertyNameForPropertyNameNode(declName)); + return unescapeLeadingUnderscores(getPropertyNameForPropertyNameNode(declName)!); // TODO: GH#18217 } switch (node.kind) { case SyntaxKind.FunctionExpression: @@ -512,7 +513,7 @@ namespace ts.NavigationBar { return false; } - switch (navigationBarNodeKind(item.parent)) { + switch (navigationBarNodeKind(item.parent!)) { case SyntaxKind.ModuleBlock: case SyntaxKind.SourceFile: case SyntaxKind.MethodDeclaration: @@ -522,8 +523,8 @@ namespace ts.NavigationBar { return hasSomeImportantChild(item); } } - function hasSomeImportantChild(item: NavigationBarNode) { - return forEach(item.children, child => { + function hasSomeImportantChild(item: NavigationBarNode): boolean { + return some(item.children, child => { const childKind = navigationBarNodeKind(child); return childKind !== SyntaxKind.VariableDeclaration && childKind !== SyntaxKind.BindingElement; }); @@ -602,7 +603,7 @@ namespace ts.NavigationBar { * We store 'A' as associated with a NavNode, and use getModuleName to traverse down again. */ function getInteriorModule(decl: ModuleDeclaration): ModuleDeclaration { - return decl.body.kind === SyntaxKind.ModuleDeclaration ? getInteriorModule(decl.body) : decl; + return decl.body!.kind === SyntaxKind.ModuleDeclaration ? getInteriorModule(decl.body) : decl; // TODO: GH#18217 } function isComputedProperty(member: EnumMember): boolean { diff --git a/src/services/organizeImports.ts b/src/services/organizeImports.ts index 225e9fae57d76..7e4affb14aa6b 100644 --- a/src/services/organizeImports.ts +++ b/src/services/organizeImports.ts @@ -28,7 +28,7 @@ namespace ts.OrganizeImports { organizeImportsWorker(topLevelExportDecls, coalesceExports); for (const ambientModule of sourceFile.statements.filter(isAmbientModule)) { - const ambientModuleBody = getModuleBlock(ambientModule as ModuleDeclaration); + const ambientModuleBody = getModuleBlock(ambientModule as ModuleDeclaration)!; // TODO: GH#18217 const ambientModuleImportDecls = ambientModuleBody.statements.filter(isImportDeclaration); organizeImportsWorker(ambientModuleImportDecls, coalesceAndOrganizeImports); @@ -54,10 +54,10 @@ namespace ts.OrganizeImports { // but the consequences of being wrong are very minor. suppressLeadingTrivia(oldImportDecls[0]); - const oldImportGroups = group(oldImportDecls, importDecl => getExternalModuleName(importDecl.moduleSpecifier)); - const sortedImportGroups = stableSort(oldImportGroups, (group1, group2) => compareModuleSpecifiers(group1[0].moduleSpecifier, group2[0].moduleSpecifier)); + const oldImportGroups = group(oldImportDecls, importDecl => getExternalModuleName(importDecl.moduleSpecifier!)!); + const sortedImportGroups = stableSort(oldImportGroups, (group1, group2) => compareModuleSpecifiers(group1[0].moduleSpecifier!, group2[0].moduleSpecifier!)); const newImportDecls = flatMap(sortedImportGroups, importGroup => - getExternalModuleName(importGroup[0].moduleSpecifier) + getExternalModuleName(importGroup[0].moduleSpecifier!) ? coalesce(importGroup) : importGroup); @@ -86,7 +86,7 @@ namespace ts.OrganizeImports { function getModuleBlock(moduleDecl: ModuleDeclaration): ModuleBlock | undefined { const body = moduleDecl.body; - return body && !isIdentifier(body) && (isModuleBlock(body) ? body : getModuleBlock(body)); + return body && !isIdentifier(body) ? (isModuleBlock(body) ? body : getModuleBlock(body)) : undefined; } function removeUnusedImports(oldImports: ReadonlyArray, sourceFile: SourceFile, program: Program) { @@ -172,18 +172,18 @@ namespace ts.OrganizeImports { // Add the namespace import to the existing default ImportDeclaration. const defaultImport = defaultImports[0]; coalescedImports.push( - updateImportDeclarationAndClause(defaultImport, defaultImport.importClause.name, namespaceImports[0].importClause.namedBindings)); + updateImportDeclarationAndClause(defaultImport, defaultImport.importClause!.name, namespaceImports[0].importClause!.namedBindings)); // TODO: GH#18217 return coalescedImports; } const sortedNamespaceImports = stableSort(namespaceImports, (i1, i2) => - compareIdentifiers((i1.importClause.namedBindings as NamespaceImport).name, (i2.importClause.namedBindings as NamespaceImport).name)); + compareIdentifiers((i1.importClause!.namedBindings as NamespaceImport).name, (i2.importClause!.namedBindings as NamespaceImport).name)); // TODO: GH#18217 for (const namespaceImport of sortedNamespaceImports) { // Drop the name, if any coalescedImports.push( - updateImportDeclarationAndClause(namespaceImport, /*name*/ undefined, namespaceImport.importClause.namedBindings)); + updateImportDeclarationAndClause(namespaceImport, /*name*/ undefined, namespaceImport.importClause!.namedBindings)); // TODO: GH#18217 } if (defaultImports.length === 0 && namedImports.length === 0) { @@ -193,16 +193,16 @@ namespace ts.OrganizeImports { let newDefaultImport: Identifier | undefined; const newImportSpecifiers: ImportSpecifier[] = []; if (defaultImports.length === 1) { - newDefaultImport = defaultImports[0].importClause.name; + newDefaultImport = defaultImports[0].importClause!.name; } else { for (const defaultImport of defaultImports) { newImportSpecifiers.push( - createImportSpecifier(createIdentifier("default"), defaultImport.importClause.name)); + createImportSpecifier(createIdentifier("default"), defaultImport.importClause!.name!)); // TODO: GH#18217 } } - newImportSpecifiers.push(...flatMap(namedImports, i => (i.importClause.namedBindings as NamedImports).elements)); + newImportSpecifiers.push(...flatMap(namedImports, i => (i.importClause!.namedBindings as NamedImports).elements)); // TODO: GH#18217 const sortedImportSpecifiers = sortSpecifiers(newImportSpecifiers); @@ -216,7 +216,7 @@ namespace ts.OrganizeImports { : createNamedImports(emptyArray) : namedImports.length === 0 ? createNamedImports(sortedImportSpecifiers) - : updateNamedImports(namedImports[0].importClause.namedBindings as NamedImports, sortedImportSpecifiers); + : updateNamedImports(namedImports[0].importClause!.namedBindings as NamedImports, sortedImportSpecifiers); // TODO: GH#18217 coalescedImports.push( updateImportDeclarationAndClause(importDecl, newDefaultImport, newNamedImports)); @@ -291,7 +291,7 @@ namespace ts.OrganizeImports { } const newExportSpecifiers: ExportSpecifier[] = []; - newExportSpecifiers.push(...flatMap(namedExports, i => (i.exportClause).elements)); + newExportSpecifiers.push(...flatMap(namedExports, i => (i.exportClause!).elements)); const sortedExportSpecifiers = sortSpecifiers(newExportSpecifiers); @@ -301,7 +301,7 @@ namespace ts.OrganizeImports { exportDecl, exportDecl.decorators, exportDecl.modifiers, - updateNamedExports(exportDecl.exportClause, sortedExportSpecifiers), + updateNamedExports(exportDecl.exportClause!, sortedExportSpecifiers), exportDecl.moduleSpecifier)); return coalescedExports; @@ -342,7 +342,7 @@ namespace ts.OrganizeImports { importDeclaration, importDeclaration.decorators, importDeclaration.modifiers, - updateImportClause(importDeclaration.importClause, name, namedBindings), + updateImportClause(importDeclaration.importClause!, name, namedBindings), // TODO: GH#18217 importDeclaration.moduleSpecifier); } @@ -357,8 +357,8 @@ namespace ts.OrganizeImports { const name1 = getExternalModuleName(m1); const name2 = getExternalModuleName(m2); return compareBooleans(name1 === undefined, name2 === undefined) || - compareBooleans(isExternalModuleNameRelative(name1), isExternalModuleNameRelative(name2)) || - compareStringsCaseInsensitive(name1, name2); + compareBooleans(isExternalModuleNameRelative(name1!), isExternalModuleNameRelative(name2!)) || + compareStringsCaseInsensitive(name1!, name2!); } function compareIdentifiers(s1: Identifier, s2: Identifier) { diff --git a/src/services/pathCompletions.ts b/src/services/pathCompletions.ts index f42d70a0c5240..afa1d76bbacb3 100644 --- a/src/services/pathCompletions.ts +++ b/src/services/pathCompletions.ts @@ -59,10 +59,10 @@ namespace ts.Completions.PathCompletions { // Determine the path to the directory containing the script relative to the root directory it is contained within const relativeDirectory = firstDefined(rootDirs, rootDirectory => - containsPath(rootDirectory, scriptPath, basePath, ignoreCase) ? scriptPath.substr(rootDirectory.length) : undefined); + containsPath(rootDirectory, scriptPath, basePath, ignoreCase) ? scriptPath.substr(rootDirectory.length) : undefined)!; // TODO: GH#18217 // Now find a path for each potential directory that is to be merged with the one containing the script - return deduplicate( + return deduplicate( rootDirs.map(rootDirectory => combinePaths(rootDirectory, relativeDirectory)), equateStringsCaseSensitive, compareStringsCaseSensitive); @@ -175,9 +175,9 @@ namespace ts.Completions.PathCompletions { const absolute = isRootedDiskPath(baseUrl) ? baseUrl : combinePaths(projectDir, baseUrl); getCompletionEntriesForDirectoryFragment(fragment, normalizePath(absolute), fileExtensions, /*includeExtensions*/ false, host, /*exclude*/ undefined, result); - for (const path in paths) { - const patterns = paths[path]; - if (paths.hasOwnProperty(path) && patterns) { + for (const path in paths!) { + const patterns = paths![path]; + if (paths!.hasOwnProperty(path) && patterns) { for (const { name, kind } of getCompletionsForPathMapping(path, patterns, fragment, baseUrl, fileExtensions, host)) { // Path mappings may provide a duplicate way to get to something we've already added, so don't add again. if (!result.some(entry => entry.name === name)) { @@ -334,7 +334,7 @@ namespace ts.Completions.PathCompletions { } } else if (host.getDirectories) { - let typeRoots: ReadonlyArray; + let typeRoots: ReadonlyArray | undefined; try { typeRoots = getEffectiveTypeRoots(options, host); } @@ -462,10 +462,10 @@ namespace ts.Completions.PathCompletions { return directoryProbablyExists(path, host); } catch { /*ignore*/ } - return undefined; + return false; } - function tryIOAndConsumeErrors(host: LanguageServiceHost, toApply: (...a: any[]) => T, ...args: any[]) { + function tryIOAndConsumeErrors(host: LanguageServiceHost, toApply: ((...a: any[]) => T) | undefined, ...args: any[]) { try { return toApply && toApply.apply(host, args); } diff --git a/src/services/patternMatcher.ts b/src/services/patternMatcher.ts index 2d26d059021d7..1b71eee0eaf25 100644 --- a/src/services/patternMatcher.ts +++ b/src/services/patternMatcher.ts @@ -119,7 +119,7 @@ namespace ts { // First, check that the last part of the dot separated pattern matches the name of the // candidate. If not, then there's no point in proceeding and doing the more // expensive work. - const candidateMatch = matchSegment(candidate, lastOrUndefined(dotSeparatedSegments), stringToWordSpans); + const candidateMatch = matchSegment(candidate, last(dotSeparatedSegments), stringToWordSpans); if (!candidateMatch) { return undefined; } @@ -203,7 +203,7 @@ namespace ts { } } - function matchSegment(candidate: string, segment: Segment, stringToWordSpans: Map): PatternMatch { + function matchSegment(candidate: string, segment: Segment, stringToWordSpans: Map): PatternMatch | undefined { // First check if the segment matches as is. This is also useful if the segment contains // characters we would normally strip when splitting into parts that we also may want to // match in the candidate. For example if the segment is "@int" and the candidate is @@ -260,7 +260,7 @@ namespace ts { return bestMatch; } - function betterMatch(a: PatternMatch | undefined, b: PatternMatch | undefined): PatternMatch { + function betterMatch(a: PatternMatch | undefined, b: PatternMatch | undefined): PatternMatch | undefined { return min(a, b, compareMatches); } function compareMatches(a: PatternMatch | undefined, b: PatternMatch | undefined): Comparison { @@ -287,8 +287,8 @@ namespace ts { let currentCandidate = 0; let currentChunkSpan = 0; - let firstMatch: number; - let contiguous: boolean; + let firstMatch: number | undefined; + let contiguous: boolean | undefined; while (true) { // Let's consider our termination cases diff --git a/src/services/preProcess.ts b/src/services/preProcess.ts index 5f1378ddbb7fa..be44d7ca2201f 100644 --- a/src/services/preProcess.ts +++ b/src/services/preProcess.ts @@ -11,7 +11,7 @@ namespace ts { moduleName: undefined }; const importedFiles: FileReference[] = []; - let ambientExternalModules: { ref: FileReference, depth: number }[]; + let ambientExternalModules: { ref: FileReference, depth: number }[] | undefined; let lastToken: SyntaxKind; let currentToken: SyntaxKind; let braceNesting = 0; @@ -336,11 +336,11 @@ namespace ts { importedFiles.push(decl.ref); } } - return { referencedFiles: pragmaContext.referencedFiles, typeReferenceDirectives: pragmaContext.typeReferenceDirectives, importedFiles, isLibFile: pragmaContext.hasNoDefaultLib, ambientExternalModules: undefined }; + return { referencedFiles: pragmaContext.referencedFiles, typeReferenceDirectives: pragmaContext.typeReferenceDirectives, importedFiles, isLibFile: !!pragmaContext.hasNoDefaultLib, ambientExternalModules: undefined }; } else { // for global scripts ambient modules still can have augmentations - look for ambient modules with depth > 0 - let ambientModuleNames: string[]; + let ambientModuleNames: string[] | undefined; if (ambientExternalModules) { for (const decl of ambientExternalModules) { if (decl.depth === 0) { @@ -354,7 +354,7 @@ namespace ts { } } } - return { referencedFiles: pragmaContext.referencedFiles, typeReferenceDirectives: pragmaContext.typeReferenceDirectives, importedFiles, isLibFile: pragmaContext.hasNoDefaultLib, ambientExternalModules: ambientModuleNames }; + return { referencedFiles: pragmaContext.referencedFiles, typeReferenceDirectives: pragmaContext.typeReferenceDirectives, importedFiles, isLibFile: !!pragmaContext.hasNoDefaultLib, ambientExternalModules: ambientModuleNames }; } } } diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index 32a39c8f9ad86..073f3badcd265 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -10,7 +10,7 @@ namespace ts.refactor.extractSymbol { export function getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] | undefined { const rangeToExtract = getRangeToExtract(context.file, getRefactorContextSpan(context)); - const targetRange: TargetRange = rangeToExtract.targetRange; + const targetRange = rangeToExtract.targetRange; if (targetRange === undefined) { return undefined; } @@ -88,7 +88,7 @@ namespace ts.refactor.extractSymbol { /* Exported for tests */ export function getEditsForAction(context: RefactorContext, actionName: string): RefactorEditInfo | undefined { const rangeToExtract = getRangeToExtract(context.file, getRefactorContextSpan(context)); - const targetRange: TargetRange = rangeToExtract.targetRange; + const targetRange = rangeToExtract.targetRange!; // TODO:GH#18217 const parsedFunctionIndexMatch = /^function_scope_(\d+)$/.exec(actionName); if (parsedFunctionIndexMatch) { @@ -220,7 +220,8 @@ namespace ts.refactor.extractSymbol { return { errors: [createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] }; } const statements: Statement[] = []; - for (const statement of start.parent.statements) { + const start2 = start; // TODO: GH#18217 Need to alias `start` to get this to compile. See https://github.com/Microsoft/TypeScript/issues/19955#issuecomment-344118248 + for (const statement of (start2.parent as BlockLike).statements) { if (statement === start || statements.length) { const errors = checkNode(statement); if (errors) { @@ -257,13 +258,13 @@ namespace ts.refactor.extractSymbol { if (errors) { return { errors }; } - return { targetRange: { range: getStatementOrExpressionRange(node), facts: rangeFacts, declarations } }; + return { targetRange: { range: getStatementOrExpressionRange(node)!, facts: rangeFacts, declarations } }; // TODO: GH#18217 /** * Attempt to refine the extraction node (generally, by shrinking it) to produce better results. * @param node The unrefined extraction node. */ - function refineNode(node: Node) { + function refineNode(node: Node): Node { if (isReturnStatement(node)) { if (node.expression) { return node.expression; @@ -279,7 +280,7 @@ namespace ts.refactor.extractSymbol { } } if (numInitializers === 1) { - return lastInitializer; + return lastInitializer!; } // No special handling if there are multiple initializers. } @@ -309,7 +310,7 @@ namespace ts.refactor.extractSymbol { break; } else if (current.kind === SyntaxKind.Parameter) { - const ctorOrMethod = getContainingFunction(current); + const ctorOrMethod = getContainingFunction(current)!; if (ctorOrMethod.kind === SyntaxKind.Constructor) { rangeFacts |= RangeFacts.InStaticRegion; } @@ -348,12 +349,12 @@ namespace ts.refactor.extractSymbol { } // If we're in a class, see whether we're in a static region (static property initializer, static method, class constructor parameter default) - const containingClass: Node = getContainingClass(nodeToCheck); + const containingClass = getContainingClass(nodeToCheck); if (containingClass) { checkForStaticContext(nodeToCheck, containingClass); } - let errors: Diagnostic[]; + let errors: Diagnostic[] | undefined; let permittedJumps = PermittedJumps.Return; let seenLabels: __String[]; @@ -370,7 +371,10 @@ namespace ts.refactor.extractSymbol { if (isDeclaration(node)) { const declaringNode = (node.kind === SyntaxKind.VariableDeclaration) ? node.parent.parent : node; if (hasModifier(declaringNode, ModifierFlags.Export)) { - (errors || (errors = [])).push(createDiagnosticForNode(node, Messages.cannotExtractExportedEntity)); + // TODO: GH#18217 Silly to use `errors ||` since it's definitely not defined (see top of `visit`) + // Also, if we're only pushing one error, just use `let error: Diagnostic | undefined`! + // Also TODO: GH#19956 + (errors || (errors = [] as Diagnostic[])).push(createDiagnosticForNode(node, Messages.cannotExtractExportedEntity)); return true; } declarations.push(node.symbol); @@ -379,16 +383,16 @@ namespace ts.refactor.extractSymbol { // Some things can't be extracted in certain situations switch (node.kind) { case SyntaxKind.ImportDeclaration: - (errors || (errors = [])).push(createDiagnosticForNode(node, Messages.cannotExtractImport)); + (errors || (errors = [] as Diagnostic[])).push(createDiagnosticForNode(node, Messages.cannotExtractImport)); return true; case SyntaxKind.SuperKeyword: // For a super *constructor call*, we have to be extracting the entire class, // but a super *method call* simply implies a 'this' reference if (node.parent.kind === SyntaxKind.CallExpression) { // Super constructor call - const containingClass = getContainingClass(node); + const containingClass = getContainingClass(node)!; // TODO:GH#18217 if (containingClass.pos < span.start || containingClass.end >= (span.start + span.length)) { - (errors || (errors = [])).push(createDiagnosticForNode(node, Messages.cannotExtractSuper)); + (errors || (errors = [] as Diagnostic[])).push(createDiagnosticForNode(node, Messages.cannotExtractSuper)); return true; } } @@ -398,13 +402,13 @@ namespace ts.refactor.extractSymbol { break; } - if (!node || isFunctionLikeDeclaration(node) || isClassLike(node)) { + if (isFunctionLikeDeclaration(node) || isClassLike(node)) { switch (node.kind) { case SyntaxKind.FunctionDeclaration: case SyntaxKind.ClassDeclaration: if (isSourceFile(node.parent) && node.parent.externalModuleIndicator === undefined) { // You cannot extract global declarations - (errors || (errors = [])).push(createDiagnosticForNode(node, Messages.functionWillNotBeVisibleInTheNewScope)); + (errors || (errors = [] as Diagnostic[])).push(createDiagnosticForNode(node, Messages.functionWillNotBeVisibleInTheNewScope)); } break; } @@ -460,13 +464,13 @@ namespace ts.refactor.extractSymbol { if (label) { if (!contains(seenLabels, label.escapedText)) { // attempts to jump to label that is not in range to be extracted - (errors || (errors = [])).push(createDiagnosticForNode(node, Messages.cannotExtractRangeContainingLabeledBreakOrContinueStatementWithTargetOutsideOfTheRange)); + (errors || (errors = [] as Diagnostic[])).push(createDiagnosticForNode(node, Messages.cannotExtractRangeContainingLabeledBreakOrContinueStatementWithTargetOutsideOfTheRange)); } } else { if (!(permittedJumps & (node.kind === SyntaxKind.BreakStatement ? PermittedJumps.Break : PermittedJumps.Continue))) { // attempt to break or continue in a forbidden context - (errors || (errors = [])).push(createDiagnosticForNode(node, Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements)); + (errors || (errors = [] as Diagnostic[])).push(createDiagnosticForNode(node, Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements)); } } break; @@ -482,7 +486,7 @@ namespace ts.refactor.extractSymbol { rangeFacts |= RangeFacts.HasReturn; } else { - (errors || (errors = [])).push(createDiagnosticForNode(node, Messages.cannotExtractRangeContainingConditionalReturnStatement)); + (errors || (errors = [] as Diagnostic[])).push(createDiagnosticForNode(node, Messages.cannotExtractRangeContainingConditionalReturnStatement)); } break; default: @@ -495,7 +499,7 @@ namespace ts.refactor.extractSymbol { } } - function getStatementOrExpressionRange(node: Node): Statement[] | Expression { + function getStatementOrExpressionRange(node: Node): Statement[] | Expression | undefined { if (isStatement(node)) { return [node]; } @@ -537,7 +541,7 @@ namespace ts.refactor.extractSymbol { // A function parameter's initializer is actually in the outer scope, not the function declaration if (current.kind === SyntaxKind.Parameter) { // Skip all the way to the outer scope of the function that declared this parameter - current = findAncestor(current, parent => isFunctionLikeDeclaration(parent)).parent; + current = findAncestor(current, parent => isFunctionLikeDeclaration(parent))!.parent; } // We want to find the nearest parent where we can place an "equivalent" sibling to the node we're extracting out of. @@ -557,7 +561,7 @@ namespace ts.refactor.extractSymbol { function getFunctionExtractionAtIndex(targetRange: TargetRange, context: RefactorContext, requestedChangesIndex: number): RefactorEditInfo { const { scopes, readsAndWrites: { target, usagesPerScope, functionErrorsPerScope, exposedVariableDeclarations } } = getPossibleExtractionsWorker(targetRange, context); Debug.assert(!functionErrorsPerScope[requestedChangesIndex].length, "The extraction went missing? How?"); - context.cancellationToken.throwIfCancellationRequested(); + context.cancellationToken!.throwIfCancellationRequested(); // TODO: GH#18217 return extractFunctionInScope(target, scopes[requestedChangesIndex], usagesPerScope[requestedChangesIndex], exposedVariableDeclarations, targetRange, context); } @@ -565,7 +569,7 @@ namespace ts.refactor.extractSymbol { const { scopes, readsAndWrites: { target, usagesPerScope, constantErrorsPerScope, exposedVariableDeclarations } } = getPossibleExtractionsWorker(targetRange, context); Debug.assert(!constantErrorsPerScope[requestedChangesIndex].length, "The extraction went missing? How?"); Debug.assert(exposedVariableDeclarations.length === 0, "Extract constant accepted a range containing a variable declaration?"); - context.cancellationToken.throwIfCancellationRequested(); + context.cancellationToken!.throwIfCancellationRequested(); const expression = isExpression(target) ? target : (target.statements[0] as ExpressionStatement).expression; @@ -645,7 +649,7 @@ namespace ts.refactor.extractSymbol { enclosingTextRange, sourceFile, context.program.getTypeChecker(), - context.cancellationToken); + context.cancellationToken!); return { scopes, readsAndWrites }; } @@ -679,7 +683,7 @@ namespace ts.refactor.extractSymbol { case SyntaxKind.SetAccessor: return `'set ${scope.name.getText()}'`; default: - Debug.assertNever(scope); + throw Debug.assertNever(scope); } } function getDescriptionForClassLikeDeclaration(scope: ClassLikeDeclaration): string { @@ -719,12 +723,12 @@ namespace ts.refactor.extractSymbol { const functionName = createIdentifier(functionNameText); - let returnType: TypeNode; + let returnType: TypeNode | undefined; const parameters: ParameterDeclaration[] = []; const callArguments: Identifier[] = []; - let writes: UsageEntry[]; + let writes: UsageEntry[] | undefined; usagesInScope.forEach((usage, name) => { - let typeNode: TypeNode; + let typeNode: TypeNode | undefined; if (!isJS) { let type = checker.getTypeOfSymbolAtLocation(usage.symbol, usage.node); // Widen the type so we don't emit nonsense annotations like "function fn(x: 3) {" @@ -764,7 +768,7 @@ namespace ts.refactor.extractSymbol { // to avoid problems when there are literal types present if (isExpression(node) && !isJS) { const contextualType = checker.getContextualType(node); - returnType = checker.typeToTypeNode(contextualType, scope, NodeBuilderFlags.NoTruncation); + returnType = checker.typeToTypeNode(contextualType!, scope, NodeBuilderFlags.NoTruncation); // TODO: GH#18217 } const { body, returnValueProperty } = transformFunctionBody(node, exposedVariableDeclarations, writes, substitutions, !!(range.facts & RangeFacts.HasReturn)); @@ -861,8 +865,8 @@ namespace ts.refactor.extractSymbol { /*name*/ getSynthesizedDeepClone(variableDeclaration.name))); // Being returned through an object literal will have widened the type. - const variableType: TypeNode = checker.typeToTypeNode( - checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(variableDeclaration)), + const variableType: TypeNode | undefined = checker.typeToTypeNode( + checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(variableDeclaration)!), // TODO: GH#18217 scope, NodeBuilderFlags.NoTruncation); @@ -1006,7 +1010,7 @@ namespace ts.refactor.extractSymbol { const variableType = isJS || !checker.isContextSensitive(node) ? undefined - : checker.typeToTypeNode(checker.getContextualType(node), scope, NodeBuilderFlags.NoTruncation); + : checker.typeToTypeNode(checker.getContextualType(node)!, scope, NodeBuilderFlags.NoTruncation); // TODO: GH#18217 const initializer = transformConstantInitializer(node, substitutions); suppressLeadingAndTrailingTrivia(initializer); @@ -1032,7 +1036,7 @@ namespace ts.refactor.extractSymbol { const localReference = createPropertyAccess( rangeFacts & RangeFacts.InStaticRegion - ? createIdentifier(scope.name.getText()) + ? createIdentifier(scope.name!.getText()) // TODO: GH#18217 : createThis(), createIdentifier(localNameText)); @@ -1147,7 +1151,7 @@ namespace ts.refactor.extractSymbol { function getCalledExpression(scope: Node, range: TargetRange, functionNameText: string): Expression { const functionReference = createIdentifier(functionNameText); if (isClassLike(scope)) { - const lhs = range.facts & RangeFacts.InStaticRegion ? createIdentifier(scope.name.text) : createThis(); + const lhs = range.facts & RangeFacts.InStaticRegion ? createIdentifier(scope.name!.text) : createThis(); // TODO: GH#18217 return createPropertyAccess(lhs, functionReference); } else { @@ -1155,13 +1159,13 @@ namespace ts.refactor.extractSymbol { } } - function transformFunctionBody(body: Node, exposedVariableDeclarations: ReadonlyArray, writes: ReadonlyArray, substitutions: ReadonlyMap, hasReturn: boolean): { body: Block, returnValueProperty: string } { + function transformFunctionBody(body: Node, exposedVariableDeclarations: ReadonlyArray, writes: ReadonlyArray | undefined, substitutions: ReadonlyMap, hasReturn: boolean): { body: Block, returnValueProperty: string | undefined } { const hasWritesOrVariableDeclarations = writes !== undefined || exposedVariableDeclarations.length > 0; if (isBlock(body) && !hasWritesOrVariableDeclarations && substitutions.size === 0) { // already block, no declarations or writes to propagate back, no substitutions - can use node as is return { body: createBlock(body.statements, /*multLine*/ true), returnValueProperty: undefined }; } - let returnValueProperty: string; + let returnValueProperty: string | undefined; let ignoreReturns = false; const statements = createNodeArray(isBlock(body) ? body.statements.slice(0) : [isStatement(body) ? body : createReturn(body)]); // rewrite body if either there are writes that should be propagated back via return statements or there are substitutions @@ -1191,7 +1195,7 @@ namespace ts.refactor.extractSymbol { if (!returnValueProperty) { returnValueProperty = "__return"; } - assignments.unshift(createPropertyAssignment(returnValueProperty, visitNode((node).expression, visitor))); + assignments.unshift(createPropertyAssignment(returnValueProperty, visitNode((node).expression!, visitor))); } if (assignments.length === 1) { return createReturn(assignments[0].name as Expression); @@ -1224,7 +1228,7 @@ namespace ts.refactor.extractSymbol { function getStatementsOrClassElements(scope: Scope): ReadonlyArray | ReadonlyArray { if (isFunctionLikeDeclaration(scope)) { - const body = scope.body; + const body = scope.body!; // TODO: GH#18217 if (isBlock(body)) { return body.statements; } @@ -1273,7 +1277,7 @@ namespace ts.refactor.extractSymbol { prevMember = member; } - Debug.assert(prevMember !== undefined); // If the loop didn't return, then it did set prevMember. + if (prevMember === undefined) return Debug.fail(); // If the loop didn't return, then it did set prevMember. return prevMember; } @@ -1289,7 +1293,7 @@ namespace ts.refactor.extractSymbol { for (let curr = (prevScope || node).parent; ; curr = curr.parent) { if (isBlockLike(curr)) { - let prevStatement; + let prevStatement: Statement | undefined; for (const statement of curr.statements) { if (statement.pos > node.pos) { break; @@ -1304,26 +1308,23 @@ namespace ts.refactor.extractSymbol { } // There must be at least one statement since we started in one. - Debug.assert(prevStatement !== undefined); - return prevStatement; + return Debug.assertDefined(prevStatement); } - if (curr === scope) { - Debug.fail("Didn't encounter a block-like before encountering scope"); - break; - } + Debug.assert(curr !== scope, "Didn't encounter a block-like before encountering scope"); } } function getPropertyAssignmentsForWritesAndVariableDeclarations( exposedVariableDeclarations: ReadonlyArray, - writes: ReadonlyArray) { - + writes: ReadonlyArray | undefined + ): ShorthandPropertyAssignment[] { const variableAssignments = map(exposedVariableDeclarations, v => createShorthandPropertyAssignment(v.symbol.name)); const writeAssignments = map(writes, w => createShorthandPropertyAssignment(w.symbol.name)); + // TODO: GH#18217 `variableAssignments` not possibly undefined! return variableAssignments === undefined - ? writeAssignments + ? writeAssignments! : writeAssignments === undefined ? variableAssignments : variableAssignments.concat(writeAssignments); @@ -1405,7 +1406,7 @@ namespace ts.refactor.extractSymbol { const end = last(statements).end; expressionDiagnostic = createFileDiagnostic(sourceFile, start, end - start, Messages.expressionExpected); } - else if (checker.getTypeAtLocation(expression).flags & (TypeFlags.Void | TypeFlags.Never)) { + else if (checker.getTypeAtLocation(expression)!.flags & (TypeFlags.Void | TypeFlags.Never)) { // TODO: GH#18217 expressionDiagnostic = createDiagnosticForNode(expression, Messages.uselessConstantType); } @@ -1445,7 +1446,7 @@ namespace ts.refactor.extractSymbol { // will use the contextual type of an expression as the return type of the extracted // method (and will therefore "use" all the types involved). if (inGenericContext && !isReadonlyArray(targetRange.range)) { - const contextualType = checker.getContextualType(targetRange.range); + const contextualType = checker.getContextualType(targetRange.range)!; // TODO: GH#18217 recordTypeParameterUsages(contextualType); } @@ -1554,7 +1555,7 @@ namespace ts.refactor.extractSymbol { function collectUsages(node: Node, valueUsage = Usage.Read) { if (inGenericContext) { - const type = checker.getTypeAtLocation(node); + const type = checker.getTypeAtLocation(node)!; // TODO: GH#18217 recordTypeParameterUsages(type); } @@ -1697,7 +1698,7 @@ namespace ts.refactor.extractSymbol { const decl = find(visibleDeclarationsInExtractedRange, d => d.symbol === sym); if (decl) { if (isVariableDeclaration(decl)) { - const idString = decl.symbol.id.toString(); + const idString = decl.symbol.id!.toString(); if (!exposedVariableSymbolSet.has(idString)) { exposedVariableDeclarations.push(decl); exposedVariableSymbolSet.set(idString, true); @@ -1725,7 +1726,7 @@ namespace ts.refactor.extractSymbol { : checker.getSymbolAtLocation(identifier); } - function tryReplaceWithQualifiedNameOrPropertyAccess(symbol: Symbol, scopeDecl: Node, isTypeNode: boolean): PropertyAccessExpression | EntityName { + function tryReplaceWithQualifiedNameOrPropertyAccess(symbol: Symbol | undefined, scopeDecl: Node, isTypeNode: boolean): PropertyAccessExpression | EntityName | undefined { if (!symbol) { return undefined; } @@ -1743,7 +1744,7 @@ namespace ts.refactor.extractSymbol { } } - function getParentNodeInSpan(node: Node, file: SourceFile, span: TextSpan): Node { + function getParentNodeInSpan(node: Node | undefined, file: SourceFile, span: TextSpan): Node | undefined { if (!node) return undefined; while (node.parent) { @@ -1768,15 +1769,16 @@ namespace ts.refactor.extractSymbol { * in the sense of something that you could extract on */ function isExtractableExpression(node: Node): boolean { - switch (node.parent.kind) { + const { parent } = node; + switch (parent.kind) { case SyntaxKind.EnumMember: return false; } switch (node.kind) { case SyntaxKind.StringLiteral: - return node.parent.kind !== SyntaxKind.ImportDeclaration && - node.parent.kind !== SyntaxKind.ImportSpecifier; + return parent.kind !== SyntaxKind.ImportDeclaration && + parent.kind !== SyntaxKind.ImportSpecifier; case SyntaxKind.SpreadElement: case SyntaxKind.ObjectBindingPattern: @@ -1784,9 +1786,9 @@ namespace ts.refactor.extractSymbol { return false; case SyntaxKind.Identifier: - return node.parent.kind !== SyntaxKind.BindingElement && - node.parent.kind !== SyntaxKind.ImportSpecifier && - node.parent.kind !== SyntaxKind.ExportSpecifier; + return parent.kind !== SyntaxKind.BindingElement && + parent.kind !== SyntaxKind.ImportSpecifier && + parent.kind !== SyntaxKind.ExportSpecifier; } return true; } diff --git a/src/services/refactors/generateGetAccessorAndSetAccessor.ts b/src/services/refactors/generateGetAccessorAndSetAccessor.ts index 92d87b1fcd0e4..6b49b84d4de3d 100644 --- a/src/services/refactors/generateGetAccessorAndSetAccessor.ts +++ b/src/services/refactors/generateGetAccessorAndSetAccessor.ts @@ -101,11 +101,11 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor { } function createAccessorAccessExpression (fieldName: AcceptedNameType, isStatic: boolean, container: ContainerDeclaration) { - const leftHead = isStatic ? (container).name : createThis(); + const leftHead = isStatic ? (container).name! : createThis(); // TODO: GH#18217 return isIdentifier(fieldName) ? createPropertyAccess(leftHead, fieldName) : createElementAccess(leftHead, createLiteral(fieldName)); } - function getModifiers(isJS: boolean, isStatic: boolean, accessModifier: SyntaxKind.PublicKeyword | SyntaxKind.PrivateKeyword): NodeArray { + function getModifiers(isJS: boolean, isStatic: boolean, accessModifier: SyntaxKind.PublicKeyword | SyntaxKind.PrivateKeyword): NodeArray | undefined { const modifiers = append( !isJS ? [createToken(accessModifier) as Token | Token] : undefined, isStatic ? createToken(SyntaxKind.StaticKeyword) : undefined @@ -124,7 +124,7 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor { const declaration = findAncestor(node.parent, isAcceptedDeclaration); // make sure declaration have AccessibilityModifier or Static Modifier or Readonly Modifier const meaning = ModifierFlags.AccessibilityModifier | ModifierFlags.Static | ModifierFlags.Readonly; - if (!declaration || !rangeOverlapsWithStartEnd(declaration.name, startPosition, endPosition) + if (!declaration || !rangeOverlapsWithStartEnd(declaration.name, startPosition, endPosition!) // TODO: GH#18217 || !isConvertableName(declaration.name) || (getModifierFlags(declaration) | meaning) !== meaning) return undefined; const name = declaration.name.text; @@ -144,12 +144,12 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor { }; } - function generateGetAccessor(fieldName: AcceptedNameType, accessorName: AcceptedNameType, type: TypeNode, modifiers: ModifiersArray | undefined, isStatic: boolean, container: ContainerDeclaration) { + function generateGetAccessor(fieldName: AcceptedNameType, accessorName: AcceptedNameType, type: TypeNode | undefined, modifiers: ModifiersArray | undefined, isStatic: boolean, container: ContainerDeclaration) { return createGetAccessor( /*decorators*/ undefined, modifiers, accessorName, - /*parameters*/ undefined, + /*parameters*/ undefined!, // TODO: GH#18217 type, createBlock([ createReturn( @@ -159,7 +159,7 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor { ); } - function generateSetAccessor(fieldName: AcceptedNameType, accessorName: AcceptedNameType, type: TypeNode, modifiers: ModifiersArray | undefined, isStatic: boolean, container: ContainerDeclaration) { + function generateSetAccessor(fieldName: AcceptedNameType, accessorName: AcceptedNameType, type: TypeNode | undefined, modifiers: ModifiersArray | undefined, isStatic: boolean, container: ContainerDeclaration) { return createSetAccessor( /*decorators*/ undefined, modifiers, @@ -226,9 +226,8 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor { if (!constructor.body) return; const { file, program, cancellationToken } = context; - const referenceEntries = mapDefined(FindAllReferences.getReferenceEntriesForNode(originalName.parent.pos, originalName, program, [file], cancellationToken), entry => ( - (entry.type === "node" && rangeContainsRange(constructor, entry.node) && isIdentifier(entry.node) && isWriteAccess(entry.node)) ? entry.node : undefined - )); + const referenceEntries = mapDefined(FindAllReferences.getReferenceEntriesForNode(originalName.parent.pos, originalName, program, [file], cancellationToken!), entry => // TODO: GH#18217 + (entry.type === "node" && rangeContainsRange(constructor, entry.node) && isIdentifier(entry.node) && isWriteAccess(entry.node)) ? entry.node : undefined); forEach(referenceEntries, entry => { const parent = entry.parent; diff --git a/src/services/refactors/moveToNewFile.ts b/src/services/refactors/moveToNewFile.ts index f7ef622b6d47e..ddccee1acba58 100644 --- a/src/services/refactors/moveToNewFile.ts +++ b/src/services/refactors/moveToNewFile.ts @@ -2,7 +2,7 @@ namespace ts.refactor { const refactorName = "Move to a new file"; registerRefactor(refactorName, { - getAvailableActions(context): ApplicableRefactorInfo[] { + getAvailableActions(context): ApplicableRefactorInfo[] | undefined { if (!context.preferences.allowTextChangesInNewFiles || getFirstAndLastStatementToMove(context) === undefined) return undefined; const description = getLocaleSpecificMessage(Diagnostics.Move_to_a_new_file); return [{ name: refactorName, description, actions: [{ name: refactorName, description }] }]; @@ -82,7 +82,7 @@ namespace ts.refactor { case SyntaxKind.ImportEqualsDeclaration: return !hasModifier(node, ModifierFlags.Export); case SyntaxKind.VariableStatement: - return (node as VariableStatement).declarationList.declarations.every(d => d.initializer && isRequireCall(d.initializer, /*checkArgumentIsStringLiteralLike*/ true)); + return (node as VariableStatement).declarationList.declarations.every(d => !!d.initializer && isRequireCall(d.initializer, /*checkArgumentIsStringLiteralLike*/ true)); default: return false; } @@ -139,7 +139,7 @@ namespace ts.refactor { function deleteUnusedOldImports(oldFile: SourceFile, toMove: ReadonlyArray, changes: textChanges.ChangeTracker, toDelete: ReadonlySymbolSet, checker: TypeChecker) { for (const statement of oldFile.statements) { if (contains(toMove, statement)) continue; - forEachImportInStatement(statement, i => deleteUnusedImports(oldFile, i, changes, name => toDelete.has(checker.getSymbolAtLocation(name)))); + forEachImportInStatement(statement, i => deleteUnusedImports(oldFile, i, changes, name => toDelete.has(checker.getSymbolAtLocation(name)!))); } } @@ -152,7 +152,7 @@ namespace ts.refactor { const shouldMove = (name: Identifier): boolean => { const symbol = isBindingElement(name.parent) ? getPropertySymbolFromBindingElement(checker, name.parent as BindingElement & { name: Identifier }) - : skipAlias(checker.getSymbolAtLocation(name), checker); + : skipAlias(checker.getSymbolAtLocation(name)!, checker); // TODO: GH#18217 return !!symbol && movedSymbols.has(symbol); }; deleteUnusedImports(sourceFile, importNode, changes, shouldMove); // These will be changed to imports from the new file @@ -202,7 +202,7 @@ namespace ts.refactor { const imports: string[] = []; newFileNeedExport.forEach(symbol => { if (symbol.escapedName === InternalSymbolName.Default) { - defaultImport = createIdentifier(symbolNameNoDefault(symbol)); + defaultImport = createIdentifier(symbolNameNoDefault(symbol)!); // TODO: GH#18217 } else { imports.push(symbol.name); @@ -325,7 +325,7 @@ namespace ts.refactor { const copiedOldImports: SupportedImportStatement[] = []; for (const oldStatement of oldFile.statements) { forEachImportInStatement(oldStatement, i => { - append(copiedOldImports, filterImport(i, moduleSpecifierFromImport(i), name => importsToCopy.has(checker.getSymbolAtLocation(name)))); + append(copiedOldImports, filterImport(i, moduleSpecifierFromImport(i), name => importsToCopy.has(checker.getSymbolAtLocation(name)!))); }); } @@ -360,7 +360,7 @@ namespace ts.refactor { let newModuleName = moduleName; for (let i = 1; ; i++) { const name = combinePaths(inDirectory, newModuleName + extension); - if (!host.fileExists(name)) return newModuleName; + if (!host.fileExists!(name)) return newModuleName; // TODO: GH#18217 newModuleName = `${moduleName}.${i}`; } } @@ -564,7 +564,7 @@ namespace ts.refactor { } } - function forEachTopLevelDeclaration(statement: Statement, cb: (node: TopLevelDeclaration) => T): T { + function forEachTopLevelDeclaration(statement: Statement, cb: (node: TopLevelDeclaration) => T): T | undefined { switch (statement.kind) { case SyntaxKind.FunctionDeclaration: case SyntaxKind.ClassDeclaration: @@ -611,7 +611,7 @@ namespace ts.refactor { return !isExpressionStatement(decl) && hasModifier(decl, ModifierFlags.Export); } else { - return getNamesToExportInCommonJS(decl).some(name => sourceFile.symbol.exports.has(escapeLeadingUnderscores(name))); + return getNamesToExportInCommonJS(decl).some(name => sourceFile.symbol.exports!.has(escapeLeadingUnderscores(name))); } } @@ -650,7 +650,7 @@ namespace ts.refactor { switch (decl.kind) { case SyntaxKind.FunctionDeclaration: case SyntaxKind.ClassDeclaration: - return [decl.name.text]; + return [decl.name!.text]; // TODO: GH#18217 case SyntaxKind.VariableStatement: return mapDefined(decl.declarationList.declarations, d => isIdentifier(d.name) ? d.name.text : undefined); case SyntaxKind.ModuleDeclaration: @@ -658,11 +658,11 @@ namespace ts.refactor { case SyntaxKind.TypeAliasDeclaration: case SyntaxKind.InterfaceDeclaration: case SyntaxKind.ImportEqualsDeclaration: - return undefined; + return emptyArray; case SyntaxKind.ExpressionStatement: return Debug.fail(); // Shouldn't try to add 'export' keyword to `exports.x = ...` default: - Debug.assertNever(decl); + return Debug.assertNever(decl); } } diff --git a/src/services/rename.ts b/src/services/rename.ts index 0fd7ce5e7b5cc..efebe72d50f6b 100644 --- a/src/services/rename.ts +++ b/src/services/rename.ts @@ -32,7 +32,7 @@ namespace ts.Rename { } // Cannot rename `default` as in `import { default as foo } from "./someModule"; - if (isIdentifier(node) && node.originalKeywordKind === SyntaxKind.DefaultKeyword && symbol.parent.flags & SymbolFlags.Module) { + if (isIdentifier(node) && node.originalKeywordKind === SyntaxKind.DefaultKeyword && symbol.parent!.flags & SymbolFlags.Module) { return undefined; } @@ -69,14 +69,15 @@ namespace ts.Rename { } function getRenameInfoError(diagnostic: DiagnosticMessage): RenameInfo { + // TODO: GH#18217 return { canRename: false, localizedErrorMessage: getLocaleSpecificMessage(diagnostic), - displayName: undefined, - fullDisplayName: undefined, - kind: undefined, - kindModifiers: undefined, - triggerSpan: undefined + displayName: undefined!, + fullDisplayName: undefined!, + kind: undefined!, + kindModifiers: undefined!, + triggerSpan: undefined! }; } diff --git a/src/services/services.ts b/src/services/services.ts index 0375f6fcf38f7..dcea57b71591c 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2,7 +2,7 @@ namespace ts { /** The version of the language service API */ export const servicesVersion = "0.8"; - function createNode(kind: TKind, pos: number, end: number, parent?: Node): NodeObject | TokenObject | IdentifierObject { + function createNode(kind: TKind, pos: number, end: number, parent: Node): NodeObject | TokenObject | IdentifierObject { const node = isNodeKind(kind) ? new NodeObject(kind, pos, end) : kind === SyntaxKind.Identifier ? new IdentifierObject(SyntaxKind.Identifier, pos, end) : new TokenObject(kind, pos, end); @@ -17,6 +17,7 @@ namespace ts { public end: number; public flags: NodeFlags; public parent: Node; + public symbol: Symbol; public jsDoc: JSDoc[]; public original: Node; public transformFlags: TransformFlags; @@ -26,8 +27,8 @@ namespace ts { this.pos = pos; this.end = end; this.flags = NodeFlags.None; - this.transformFlags = undefined; - this.parent = undefined; + this.transformFlags = undefined!; // TODO: GH#18217 + this.parent = undefined!; this.kind = kind; } @@ -96,20 +97,20 @@ namespace ts { return this._children || (this._children = createChildren(this, sourceFile)); } - public getFirstToken(sourceFile?: SourceFile): Node { + public getFirstToken(sourceFile?: SourceFile): Node | undefined { this.assertHasRealPosition(); const children = this.getChildren(sourceFile); if (!children.length) { return undefined; } - const child = find(children, kid => kid.kind < SyntaxKind.FirstJSDocNode || kid.kind > SyntaxKind.LastJSDocNode); + const child = find(children, kid => kid.kind < SyntaxKind.FirstJSDocNode || kid.kind > SyntaxKind.LastJSDocNode)!; return child.kind < SyntaxKind.FirstNode ? child : child.getFirstToken(sourceFile); } - public getLastToken(sourceFile?: SourceFile): Node { + public getLastToken(sourceFile?: SourceFile): Node | undefined { this.assertHasRealPosition(); const children = this.getChildren(sourceFile); @@ -121,7 +122,7 @@ namespace ts { return child.kind < SyntaxKind.FirstNode ? child : child.getLastToken(sourceFile); } - public forEachChild(cbNode: (node: Node) => T, cbNodeArray?: (nodes: NodeArray) => T): T { + public forEachChild(cbNode: (node: Node) => T, cbNodeArray?: (nodes: NodeArray) => T): T | undefined { return forEachChild(this, cbNode, cbNodeArray); } } @@ -200,14 +201,16 @@ namespace ts { public end: number; public flags: NodeFlags; public parent: Node; + public symbol: Symbol; public jsDocComments: JSDoc[]; + public transformFlags: TransformFlags; constructor(pos: number, end: number) { // Set properties in same order as NodeObject this.pos = pos; this.end = end; this.flags = NodeFlags.None; - this.parent = undefined; + this.parent = undefined!; } public getSourceFile(): SourceFile { @@ -254,22 +257,22 @@ namespace ts { } public getChildAt(): Node { - return undefined; + return undefined!; // TODO: GH#18217 } public getChildren(): Node[] { return emptyArray; } - public getFirstToken(): Node { + public getFirstToken(): Node | undefined { return undefined; } - public getLastToken(): Node { + public getLastToken(): Node | undefined { return undefined; } - public forEachChild(): T { + public forEachChild(): T | undefined { return undefined; } } @@ -277,7 +280,8 @@ namespace ts { class SymbolObject implements Symbol { flags: SymbolFlags; escapedName: __String; - declarations?: Declaration[]; + declarations: Declaration[]; + valueDeclaration: Declaration; // Undefined is used to indicate the value has not been computed. If, after computing, the // symbol has no doc comment, then the empty array will be returned. @@ -330,6 +334,7 @@ namespace ts { } class TokenObject extends TokenOrIdentifierObject implements Token { + public symbol: Symbol; public kind: TKind; constructor(kind: TKind, pos: number, end: number) { @@ -341,6 +346,8 @@ namespace ts { class IdentifierObject extends TokenOrIdentifierObject implements Identifier { public kind: SyntaxKind.Identifier; public escapedText: __String; + public symbol: Symbol; + public autoGenerateFlags: GeneratedIdentifierFlags; _primaryExpressionBrand: any; _memberExpressionBrand: any; _leftHandSideExpressionBrand: any; @@ -364,7 +371,7 @@ namespace ts { flags: TypeFlags; objectFlags?: ObjectFlags; id: number; - symbol?: Symbol; + symbol: Symbol; constructor(checker: TypeChecker, flags: TypeFlags) { this.checker = checker; this.flags = flags; @@ -503,7 +510,7 @@ namespace ts { let doc = JsDoc.getJsDocCommentsFromDeclarations(declarations); if (doc.length === 0 || declarations.some(hasJSDocInheritDocTag)) { for (const declaration of declarations) { - const inheritedDocs = findInheritedJSDocComments(declaration, declaration.symbol.name, checker); + const inheritedDocs = findInheritedJSDocComments(declaration, declaration.symbol.name, checker!); // TODO: GH#18217 // TODO: GH#16312 Return a ReadonlyArray, avoid copying inheritedDocs if (inheritedDocs) doc = doc.length === 0 ? inheritedDocs.slice() : inheritedDocs.concat(lineBreakPart(), doc); } @@ -600,7 +607,7 @@ namespace ts { const { line } = this.getLineAndCharacterOfPosition(pos); const lineStarts = this.getLineStarts(); - let lastCharPos: number; + let lastCharPos: number | undefined; if (line + 1 >= lineStarts.length) { lastCharPos = this.getEnd(); } @@ -723,7 +730,7 @@ namespace ts { // Handle named exports case e.g.: // export {a, b as B} from "mod"; if ((node).exportClause) { - forEach((node).exportClause.elements, visit); + forEach((node).exportClause!.elements, visit); } break; @@ -829,7 +836,7 @@ namespace ts { return !s.length || s.charAt(0) === s.charAt(0).toLowerCase(); } - export function displayPartsToString(displayParts: SymbolDisplayPart[]) { + export function displayPartsToString(displayParts: SymbolDisplayPart[] | undefined) { if (displayParts) { return map(displayParts, displayPart => displayPart.text).join(""); } @@ -913,7 +920,7 @@ namespace ts { public getOrCreateEntryByPath(fileName: string, path: Path): HostFileInformation { const info = this.getEntryByPath(path) || this.createEntry(fileName, path); - return isString(info) ? undefined : info; + return isString(info) ? undefined! : info; // TODO: GH#18217 } public getRootFileNames(): string[] { @@ -933,12 +940,12 @@ namespace ts { public getVersion(path: Path): string { const file = this.getHostFileInformation(path); - return file && file.version; + return (file && file.version)!; // TODO: GH#18217 } public getScriptSnapshot(path: Path): IScriptSnapshot { const file = this.getHostFileInformation(path); - return file && file.scriptSnapshot; + return (file && file.scriptSnapshot)!; // TODO: GH#18217 } } @@ -962,7 +969,7 @@ namespace ts { const scriptKind = getScriptKind(fileName, this.host); const version = this.host.getScriptVersion(fileName); - let sourceFile: SourceFile; + let sourceFile: SourceFile | undefined; if (this.currentFileName !== fileName) { // This is a new file, just parse it @@ -999,7 +1006,7 @@ namespace ts { export let disableIncrementalParsing = false; - export function updateLanguageServiceSourceFile(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile { + export function updateLanguageServiceSourceFile(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string, textChangeRange: TextChangeRange | undefined, aggressiveChecks?: boolean): SourceFile { // If we were given a text change range, and our version or open-ness changed, then // incrementally parse this file. if (textChangeRange) { @@ -1058,11 +1065,11 @@ namespace ts { } class CancellationTokenObject implements CancellationToken { - constructor(private cancellationToken: HostCancellationToken) { + constructor(private cancellationToken: HostCancellationToken | undefined) { } - public isCancellationRequested() { - return this.cancellationToken && this.cancellationToken.isCancellationRequested(); + public isCancellationRequested(): boolean { + return !!this.cancellationToken && this.cancellationToken.isCancellationRequested(); } public throwIfCancellationRequested(): void { @@ -1108,7 +1115,7 @@ namespace ts { } /* @internal */ - export function createSourceFileLikeCache(host: { readFile?: (path: string) => string, fileExists?: (path: string) => boolean }): SourceFileLikeCache { + export function createSourceFileLikeCache(host: { readFile?: (path: string) => string | undefined, fileExists?: (path: string) => boolean }): SourceFileLikeCache { const cached = createMap(); return { get(path: Path) { @@ -1117,7 +1124,7 @@ namespace ts { } if (!host.fileExists || !host.readFile || !host.fileExists(path)) return; // And failing that, check the disk - const text = host.readFile(path); + const text = host.readFile(path)!; // TODO: GH#18217 const file: SourceFileLike = { text, lineMap: undefined, @@ -1186,7 +1193,7 @@ namespace ts { const typeRootsVersion = host.getTypeRootsVersion ? host.getTypeRootsVersion() : 0; if (lastTypesRootVersion !== typeRootsVersion) { log("TypeRoots version has changed; provide new program"); - program = undefined; + program = undefined!; // TODO: GH#18217 lastTypesRootVersion = typeRootsVersion; } @@ -1197,7 +1204,7 @@ namespace ts { const hasInvalidatedResolution: HasInvalidatedResolution = host.hasInvalidatedResolution || returnFalse; // If the program is already up-to-date, we can reuse it - if (isProgramUptoDate(program, rootFileNames, hostCache.compilationSettings(), path => hostCache.getVersion(path), fileExists, hasInvalidatedResolution, host.hasChangedAutomaticTypeDirectiveNames)) { + if (isProgramUptoDate(program, rootFileNames, hostCache.compilationSettings(), path => hostCache.getVersion(path), fileExists, hasInvalidatedResolution, !!host.hasChangedAutomaticTypeDirectiveNames)) { return; } @@ -1230,7 +1237,7 @@ namespace ts { } return host.readFile && host.readFile(fileName); }, - realpath: host.realpath && (path => host.realpath(path)), + realpath: host.realpath && (path => host.realpath!(path)), directoryExists: directoryName => { return directoryProbablyExists(directoryName, host); }, @@ -1242,15 +1249,15 @@ namespace ts { hasChangedAutomaticTypeDirectiveNames: host.hasChangedAutomaticTypeDirectiveNames }; if (host.trace) { - compilerHost.trace = message => host.trace(message); + compilerHost.trace = message => host.trace!(message); } if (host.resolveModuleNames) { - compilerHost.resolveModuleNames = (moduleNames, containingFile, reusedNames) => host.resolveModuleNames(moduleNames, containingFile, reusedNames); + compilerHost.resolveModuleNames = (moduleNames, containingFile, reusedNames) => host.resolveModuleNames!(moduleNames, containingFile, reusedNames); } if (host.resolveTypeReferenceDirectives) { compilerHost.resolveTypeReferenceDirectives = (typeReferenceDirectiveNames, containingFile) => { - return host.resolveTypeReferenceDirectives(typeReferenceDirectiveNames, containingFile); + return host.resolveTypeReferenceDirectives!(typeReferenceDirectiveNames, containingFile); }; } @@ -1266,7 +1273,7 @@ namespace ts { // hostCache is captured in the closure for 'getOrCreateSourceFile' but it should not be used past this point. // It needs to be cleared to allow all collected snapshots to be released - hostCache = undefined; + hostCache = undefined!; // We reset this cache on structure invalidation so we don't hold on to outdated files for long; however we can't use the `compilerHost` above, // Because it only functions until `hostCache` is cleared, while we'll potentially need the functionality to lazily read sourcemap files during @@ -1278,12 +1285,12 @@ namespace ts { program.getTypeChecker(); return; - function fileExists(fileName: string) { + function fileExists(fileName: string): boolean { const path = toPath(fileName, currentDirectory, getCanonicalFileName); const entry = hostCache.getEntryByPath(path); return entry ? !isString(entry) : - (host.fileExists && host.fileExists(fileName)); + (!!host.fileExists && host.fileExists(fileName)); } // Release any files we have acquired in the old program but are @@ -1293,11 +1300,11 @@ namespace ts { documentRegistry.releaseDocumentWithKey(oldSourceFile.path, oldSettingsKey); } - function getOrCreateSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile { + function getOrCreateSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined { return getOrCreateSourceFileByPath(fileName, toPath(fileName, currentDirectory, getCanonicalFileName), languageVersion, onError, shouldCreateNewSourceFile); } - function getOrCreateSourceFileByPath(fileName: string, path: Path, _languageVersion: ScriptTarget, _onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile { + function getOrCreateSourceFileByPath(fileName: string, path: Path, _languageVersion: ScriptTarget, _onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined { Debug.assert(hostCache !== undefined); // The program is asking for this file, check first if the host can locate it. // If the host can not locate the file, then it does not exist. return undefined @@ -1352,7 +1359,8 @@ namespace ts { } } - function getProgram(): Program { + // TODO: GH#18217 frequently asserted as defined + function getProgram(): Program | undefined { if (syntaxOnly) { Debug.assert(program === undefined); return undefined; @@ -1364,16 +1372,16 @@ namespace ts { } function cleanupSemanticCache(): void { - program = undefined; + program = undefined!; // TODO: GH#18217 } function dispose(): void { if (program) { forEach(program.getSourceFiles(), f => documentRegistry.releaseDocument(f.fileName, program.getCompilerOptions())); - program = undefined; + program = undefined!; // TODO: GH#18217 } - host = undefined; + host = undefined!; } /// Diagnostics @@ -1415,7 +1423,7 @@ namespace ts { return [...program.getOptionsDiagnostics(cancellationToken), ...program.getGlobalDiagnostics(cancellationToken)]; } - function getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions = defaultPreferences): CompletionInfo { + function getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions = defaultPreferences): CompletionInfo | undefined { // Convert from deprecated options names to new names const fullPreferences: UserPreferences = { ...identity(options), // avoid excess property check @@ -1433,7 +1441,7 @@ namespace ts { options.triggerCharacter); } - function getCompletionEntryDetails(fileName: string, position: number, name: string, formattingOptions: FormatCodeSettings | undefined, source: string | undefined, preferences: UserPreferences = defaultPreferences): CompletionEntryDetails { + function getCompletionEntryDetails(fileName: string, position: number, name: string, formattingOptions: FormatCodeSettings | undefined, source: string | undefined, preferences: UserPreferences = defaultPreferences): CompletionEntryDetails | undefined { synchronizeHostData(); return Completions.getCompletionEntryDetails( program, @@ -1442,19 +1450,19 @@ namespace ts { position, { name, source }, host, - formattingOptions && formatting.getFormatContext(formattingOptions), + (formattingOptions && formatting.getFormatContext(formattingOptions))!, // TODO: GH#18217 getCanonicalFileName, preferences, cancellationToken, ); } - function getCompletionEntrySymbol(fileName: string, position: number, name: string, source?: string): Symbol { + function getCompletionEntrySymbol(fileName: string, position: number, name: string, source?: string): Symbol | undefined { synchronizeHostData(); return Completions.getCompletionEntrySymbol(program, log, getValidSourceFile(fileName), position, { name, source }); } - function getQuickInfoAtPosition(fileName: string, position: number): QuickInfo { + function getQuickInfoAtPosition(fileName: string, position: number): QuickInfo | undefined { synchronizeHostData(); const sourceFile = getValidSourceFile(fileName); @@ -1524,7 +1532,7 @@ namespace ts { function toLineColumnOffset(fileName: string, position: number) { const path = toPath(fileName, currentDirectory, getCanonicalFileName); - const file = program.getSourceFile(path) || sourcemappedFileCache.get(path); + const file = program.getSourceFile(path) || sourcemappedFileCache.get(path)!; // TODO: GH#18217 return file.getLineAndCharacterOfPosition(position); } @@ -1547,7 +1555,7 @@ namespace ts { } function convertDocumentToSourceMapper(file: { sourceMapper?: sourcemaps.SourceMapper }, contents: string, mapFileName: string) { - let maps: sourcemaps.SourceMapData; + let maps: sourcemaps.SourceMapData | undefined; try { maps = JSON.parse(contents); } @@ -1559,8 +1567,8 @@ namespace ts { return file.sourceMapper = sourcemaps.identitySourceMapper; } return file.sourceMapper = sourcemaps.decode({ - readFile: s => host.readFile(s), - fileExists: s => host.fileExists(s), + readFile: s => host.readFile!(s), // TODO: GH#18217 + fileExists: s => host.fileExists!(s), // TODO: GH#18217 getCanonicalFileName, log, }, mapFileName, maps, program, sourcemappedFileCache); @@ -1593,7 +1601,7 @@ namespace ts { for (const location of possibleMapLocations) { const mapPath = toPath(location, getDirectoryPath(fileName), getCanonicalFileName); if (host.fileExists(mapPath)) { - return convertDocumentToSourceMapper(file, host.readFile(mapPath), mapPath); + return convertDocumentToSourceMapper(file, host.readFile(mapPath)!, mapPath); // TODO: GH#18217 } } return file.sourceMapper = sourcemaps.identitySourceMapper; @@ -1607,7 +1615,7 @@ namespace ts { function getTargetOfMappedPosition(input: TIn, original = input): TIn { const info = extract(input); if (endsWith(info.fileName, Extension.Dts)) { - let file: SourceFileLike = program.getSourceFile(info.fileName); + let file: SourceFileLike | undefined = program.getSourceFile(info.fileName); if (!file) { const path = toPath(info.fileName, currentDirectory, getCanonicalFileName); file = sourcemappedFileCache.get(path); @@ -1641,17 +1649,17 @@ namespace ts { }) ); - function getTargetOfMappedDeclarationFiles(infos: ReadonlyArray): DefinitionInfo[] { + function getTargetOfMappedDeclarationFiles(infos: ReadonlyArray | undefined): DefinitionInfo[] | undefined { return map(infos, d => getTargetOfMappedDeclarationInfo(d)); } /// Goto definition - function getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] { + function getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] | undefined { synchronizeHostData(); return getTargetOfMappedDeclarationFiles(GoToDefinition.getDefinitionAtPosition(program, getValidSourceFile(fileName), position)); } - function getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan { + function getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan | undefined { synchronizeHostData(); const result = GoToDefinition.getDefinitionAndBoundSpan(program, getValidSourceFile(fileName), position); if (!result) return result; @@ -1665,7 +1673,7 @@ namespace ts { }; } - function getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] { + function getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] | undefined { synchronizeHostData(); return getTargetOfMappedDeclarationFiles(GoToDefinition.getTypeDefinitionAtPosition(program.getTypeChecker(), getValidSourceFile(fileName), position)); } @@ -1687,17 +1695,17 @@ namespace ts { }) ); - function getTargetOfMappedImplementationLocations(infos: ReadonlyArray): ImplementationLocation[] { + function getTargetOfMappedImplementationLocations(infos: ReadonlyArray | undefined): ImplementationLocation[] | undefined { return map(infos, d => getTargetOfMappedImplementationLocation(d)); } - function getImplementationAtPosition(fileName: string, position: number): ImplementationLocation[] { + function getImplementationAtPosition(fileName: string, position: number): ImplementationLocation[] | undefined { synchronizeHostData(); return getTargetOfMappedImplementationLocations(FindAllReferences.getImplementationsAtPosition(program, cancellationToken, program.getSourceFiles(), getValidSourceFile(fileName), position)); } /// References and Occurrences - function getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[] { + function getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[] | undefined { return flatMap(getDocumentHighlights(fileName, position, [fileName]), entry => entry.highlightSpans.map(highlightSpan => ({ fileName: entry.fileName, textSpan: highlightSpan.textSpan, @@ -1707,7 +1715,7 @@ namespace ts { }))); } - function getDocumentHighlights(fileName: string, position: number, filesToSearch: ReadonlyArray): DocumentHighlights[] { + function getDocumentHighlights(fileName: string, position: number, filesToSearch: ReadonlyArray): DocumentHighlights[] | undefined { Debug.assert(filesToSearch.some(f => normalizePath(f) === fileName)); synchronizeHostData(); const sourceFilesToSearch = map(filesToSearch, f => Debug.assertDefined(program.getSourceFile(f))); @@ -1715,15 +1723,15 @@ namespace ts { return DocumentHighlights.getDocumentHighlights(program, cancellationToken, sourceFile, position, sourceFilesToSearch); } - function findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[] { + function findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[] | undefined { return getReferences(fileName, position, { findInStrings, findInComments, isForRename: true }); } - function getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] { - return getReferences(fileName, position); + function getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] | undefined { + return getReferences(fileName, position)!; } - function getReferences(fileName: string, position: number, options?: FindAllReferences.Options) { + function getReferences(fileName: string, position: number, options?: FindAllReferences.Options): ReferenceEntry[] | undefined { synchronizeHostData(); // Exclude default library when renaming as commonly user don't want to change that file. @@ -1742,20 +1750,20 @@ namespace ts { return FindAllReferences.findReferencedEntries(program, cancellationToken, sourceFiles, getValidSourceFile(fileName), position, options); } - function findReferences(fileName: string, position: number): ReferencedSymbol[] { + function findReferences(fileName: string, position: number): ReferencedSymbol[] | undefined { synchronizeHostData(); return FindAllReferences.findReferencedSymbols(program, cancellationToken, program.getSourceFiles(), getValidSourceFile(fileName), position); } /// NavigateTo - function getNavigateToItems(searchValue: string, maxResultCount?: number, fileName?: string, excludeDtsFiles?: boolean): NavigateToItem[] { + function getNavigateToItems(searchValue: string, maxResultCount?: number, fileName?: string, excludeDtsFiles = false): NavigateToItem[] { synchronizeHostData(); const sourceFiles = fileName ? [getValidSourceFile(fileName)] : program.getSourceFiles(); return NavigateTo.getNavigateToItems(sourceFiles, program.getTypeChecker(), cancellationToken, searchValue, maxResultCount, excludeDtsFiles); } - function getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean) { + function getEmitOutput(fileName: string, emitOnlyDtsFiles = false) { synchronizeHostData(); const sourceFile = getValidSourceFile(fileName); @@ -1767,7 +1775,7 @@ namespace ts { /** * This is a semantic operation. */ - function getSignatureHelpItems(fileName: string, position: number): SignatureHelpItems { + function getSignatureHelpItems(fileName: string, position: number): SignatureHelpItems | undefined { synchronizeHostData(); const sourceFile = getValidSourceFile(fileName); @@ -1784,14 +1792,14 @@ namespace ts { return getNonBoundSourceFile(fileName); } - function getNameOrDottedNameSpan(fileName: string, startPos: number, _endPos: number): TextSpan { + function getNameOrDottedNameSpan(fileName: string, startPos: number, _endPos: number): TextSpan | undefined { const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); // Get node at the location const node = getTouchingPropertyName(sourceFile, startPos, /*includeJsDocComment*/ false); if (node === sourceFile) { - return; + return undefined; } switch (node.kind) { @@ -1809,7 +1817,7 @@ namespace ts { // Cant create the text span default: - return; + return undefined; } let nodeForStartPos = node; @@ -1841,7 +1849,7 @@ namespace ts { return createTextSpanFromBounds(nodeForStartPos.getStart(), node.getEnd()); } - function getBreakpointStatementAtPosition(fileName: string, position: number) { + function getBreakpointStatementAtPosition(fileName: string, position: number): TextSpan | undefined { // doesn't use compiler - no need to synchronize with host const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); @@ -1986,7 +1994,7 @@ namespace ts { } function getEditsForFileRename(oldFilePath: string, newFilePath: string, formatOptions: FormatCodeSettings): ReadonlyArray { - return ts.getEditsForFileRename(getProgram(), oldFilePath, newFilePath, host, formatting.getFormatContext(formatOptions)); + return ts.getEditsForFileRename(getProgram()!, oldFilePath, newFilePath, host, formatting.getFormatContext(formatOptions)); } function applyCodeActionCommand(action: CodeActionCommand): Promise; @@ -2006,7 +2014,7 @@ namespace ts { ? host.installPackage({ fileName: toPath(action.file, currentDirectory, getCanonicalFileName), packageName: action.packageName }) : Promise.reject("Host does not implement `installPackage`"); default: - Debug.fail(); + return Debug.fail(); // TODO: Debug.assertNever(action); will only work if there is more than one type. } } @@ -2051,7 +2059,7 @@ namespace ts { return true; } - function getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean) { + function getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan | undefined { const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); const range = formatting.getRangeOfEnclosingComment(sourceFile, position, onlyMultiLine); return range && createTextSpanFromRange(range); @@ -2077,7 +2085,7 @@ namespace ts { if (descriptors.length > 0 && !isNodeModulesFile(sourceFile.fileName)) { const regExp = getTodoCommentsRegExp(); - let matchArray: RegExpExecArray; + let matchArray: RegExpExecArray | null; while (matchArray = regExp.exec(fileContents)) { cancellationToken.throwIfCancellationRequested(); @@ -2110,13 +2118,13 @@ namespace ts { continue; } - let descriptor: TodoCommentDescriptor; + let descriptor: TodoCommentDescriptor | undefined; for (let i = 0; i < descriptors.length; i++) { if (matchArray[i + firstDescriptorCaptureIndex]) { descriptor = descriptors[i]; } } - Debug.assert(descriptor !== undefined); + if (descriptor === undefined) return Debug.fail(); // We don't want to match something like 'TODOBY', so we make sure a non // letter/digit follows the match. @@ -2216,9 +2224,9 @@ namespace ts { file, startPosition, endPosition, - program: getProgram(), + program: getProgram()!, host, - formatContext: formatting.getFormatContext(formatOptions), + formatContext: formatting.getFormatContext(formatOptions!), // TODO: GH#18217 cancellationToken, preferences, }; @@ -2237,8 +2245,7 @@ namespace ts { refactorName: string, actionName: string, preferences: UserPreferences = defaultPreferences, - ): RefactorEditInfo { - + ): RefactorEditInfo | undefined { synchronizeHostData(); const file = getValidSourceFile(fileName); return refactor.getEditsForRefactor(getRefactorContext(file, positionOrRange, preferences, formatOptions), refactorName, actionName); @@ -2307,7 +2314,7 @@ namespace ts { initializeNameTable(sourceFile); } - return sourceFile.nameTable; + return sourceFile.nameTable!; // TODO: GH#18217 } function initializeNameTable(sourceFile: SourceFile): void { @@ -2320,7 +2327,7 @@ namespace ts { forEachChild(node, walk); if (hasJSDocNodes(node)) { - for (const jsDoc of node.jsDoc) { + for (const jsDoc of node.jsDoc!) { forEachChild(jsDoc, walk); } } @@ -2344,7 +2351,7 @@ namespace ts { * Returns the containing object literal property declaration given a possible name node, e.g. "a" in x = { "a": 1 } */ /* @internal */ - export function getContainingObjectLiteralElement(node: Node): ObjectLiteralElement { + export function getContainingObjectLiteralElement(node: Node): ObjectLiteralElement | undefined { switch (node.kind) { case SyntaxKind.StringLiteral: case SyntaxKind.NumericLiteral: @@ -2363,8 +2370,8 @@ namespace ts { /* @internal */ export function getPropertySymbolsFromContextualType(typeChecker: TypeChecker, node: ObjectLiteralElement): Symbol[] { const objectLiteral = node.parent; - const contextualType = typeChecker.getContextualType(objectLiteral); - return getPropertySymbolsFromType(contextualType, node.name); + const contextualType = typeChecker.getContextualType(objectLiteral)!; // TODO: GH#18217 + return getPropertySymbolsFromType(contextualType, node.name!)!; // TODO: GH#18217 } /* @internal */ diff --git a/src/services/shims.ts b/src/services/shims.ts index 808da2eb1ec9c..5a744ff47f539 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -306,14 +306,14 @@ namespace ts { return this.scriptSnapshotShim.getLength(); } - public getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange { + public getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange | undefined { const oldSnapshotShim = oldSnapshot; const encoded = this.scriptSnapshotShim.getChangeRange(oldSnapshotShim.scriptSnapshotShim); if (encoded === null) { - return null; + return null!; // TODO: GH#18217 } - const decoded: { span: { start: number; length: number; }; newLength: number; } = JSON.parse(encoded); + const decoded: { span: { start: number; length: number; }; newLength: number; } = JSON.parse(encoded!); // TODO: GH#18217 return createTextChangeRange( createTextSpan(decoded.span.start, decoded.span.length), decoded.newLength); } @@ -322,7 +322,7 @@ namespace ts { // if scriptSnapshotShim is a COM object then property check becomes method call with no arguments // 'in' does not have this effect if ("dispose" in this.scriptSnapshotShim) { - this.scriptSnapshotShim.dispose(); + this.scriptSnapshotShim.dispose!(); // TODO: GH#18217 Can we just use `if (this.scriptSnapshotShim.dispose)`? } } } @@ -341,10 +341,10 @@ namespace ts { // 'in' does not have this effect. if ("getModuleResolutionsForFile" in this.shimHost) { this.resolveModuleNames = (moduleNames: string[], containingFile: string): ResolvedModuleFull[] => { - const resolutionsInFile = >JSON.parse(this.shimHost.getModuleResolutionsForFile(containingFile)); + const resolutionsInFile = >JSON.parse(this.shimHost.getModuleResolutionsForFile!(containingFile)); // TODO: GH#18217 return map(moduleNames, name => { const result = getProperty(resolutionsInFile, name); - return result ? { resolvedFileName: result, extension: extensionFromPath(result), isExternalLibraryImport: false } : undefined; + return result ? { resolvedFileName: result, extension: extensionFromPath(result), isExternalLibraryImport: false } : undefined!; // TODO: GH#18217 }); }; } @@ -353,8 +353,8 @@ namespace ts { } if ("getTypeReferenceDirectiveResolutionsForFile" in this.shimHost) { this.resolveTypeReferenceDirectives = (typeDirectiveNames: string[], containingFile: string) => { - const typeDirectivesForFile = >JSON.parse(this.shimHost.getTypeReferenceDirectiveResolutionsForFile(containingFile)); - return map(typeDirectiveNames, name => getProperty(typeDirectivesForFile, name)); + const typeDirectivesForFile = >JSON.parse(this.shimHost.getTypeReferenceDirectiveResolutionsForFile!(containingFile)); // TODO: GH#18217 + return map(typeDirectiveNames, name => getProperty(typeDirectivesForFile, name)!); // TODO: GH#18217 }; } } @@ -378,7 +378,7 @@ namespace ts { public getProjectVersion(): string { if (!this.shimHost.getProjectVersion) { // shimmed host does not support getProjectVersion - return undefined; + return undefined!; // TODO: GH#18217 } return this.shimHost.getProjectVersion(); @@ -411,14 +411,14 @@ namespace ts { return this.files = JSON.parse(encoded); } - public getScriptSnapshot(fileName: string): IScriptSnapshot { + public getScriptSnapshot(fileName: string): IScriptSnapshot | undefined { const scriptSnapshot = this.shimHost.getScriptSnapshot(fileName); return scriptSnapshot && new ScriptSnapshotShimAdapter(scriptSnapshot); } public getScriptKind(fileName: string): ScriptKind { if ("getScriptKind" in this.shimHost) { - return this.shimHost.getScriptKind(fileName); + return this.shimHost.getScriptKind!(fileName); // TODO: GH#18217 } else { return ScriptKind.Unknown; @@ -463,7 +463,7 @@ namespace ts { public readDirectory(path: string, extensions?: ReadonlyArray, exclude?: string[], include?: string[], depth?: number): string[] { const pattern = getFileMatcherPatterns(path, exclude, include, - this.shimHost.useCaseSensitiveFileNames(), this.shimHost.getCurrentDirectory()); + this.shimHost.useCaseSensitiveFileNames!(), this.shimHost.getCurrentDirectory()); // TODO: GH#18217 return JSON.parse(this.shimHost.readDirectory( path, JSON.stringify(extensions), @@ -496,13 +496,13 @@ namespace ts { this.directoryExists = directoryName => this.shimHost.directoryExists(directoryName); } if ("realpath" in this.shimHost) { - this.realpath = path => this.shimHost.realpath(path); + this.realpath = path => this.shimHost.realpath!(path); // TODO: GH#18217 } } public readDirectory(rootDir: string, extensions: ReadonlyArray, exclude: ReadonlyArray, include: ReadonlyArray, depth?: number): string[] { const pattern = getFileMatcherPatterns(rootDir, exclude, include, - this.shimHost.useCaseSensitiveFileNames(), this.shimHost.getCurrentDirectory()); + this.shimHost.useCaseSensitiveFileNames!(), this.shimHost.getCurrentDirectory()); // TODO: GH#18217 return JSON.parse(this.shimHost.readDirectory( rootDir, JSON.stringify(extensions), @@ -528,7 +528,7 @@ namespace ts { } function simpleForwardCall(logger: Logger, actionDescription: string, action: () => {}, logPerformance: boolean): {} { - let start: number; + let start: number | undefined; if (logPerformance) { logger.log(actionDescription); start = timestamp(); @@ -538,7 +538,7 @@ namespace ts { if (logPerformance) { const end = timestamp(); - logger.log(`${actionDescription} completed in ${end - start} msec`); + logger.log(`${actionDescription} completed in ${end - start!} msec`); if (isString(result)) { let str = result; if (str.length > 128) { @@ -551,7 +551,7 @@ namespace ts { return result; } - function forwardJSONCall(logger: Logger, actionDescription: string, action: () => {}, logPerformance: boolean): string { + function forwardJSONCall(logger: Logger, actionDescription: string, action: () => {} | null | undefined, logPerformance: boolean): string { return forwardCall(logger, actionDescription, /*returnJson*/ true, action, logPerformance); } @@ -595,8 +595,8 @@ namespace ts { function realizeDiagnostic(diagnostic: Diagnostic, newLine: string): RealizedDiagnostic { return { message: flattenDiagnosticMessageText(diagnostic.messageText, newLine), - start: diagnostic.start, - length: diagnostic.length, + start: diagnostic.start!, // TODO: GH#18217 + length: diagnostic.length!, // TODO: GH#18217 category: diagnosticCategoryName(diagnostic), code: diagnostic.code, reportsUnnecessary: diagnostic.reportsUnnecessary, @@ -614,7 +614,7 @@ namespace ts { this.logger = this.host; } - public forwardJSONCall(actionDescription: string, action: () => {}): string { + public forwardJSONCall(actionDescription: string, action: () => {} | null | undefined): string { return forwardJSONCall(this.logger, actionDescription, action, this.logPerformance); } @@ -627,7 +627,7 @@ namespace ts { public dispose(dummy: {}): void { this.logger.log("dispose()"); this.languageService.dispose(); - this.languageService = null; + this.languageService = null!; // force a GC if (debugObjectHost && debugObjectHost.CollectGarbage) { @@ -635,7 +635,7 @@ namespace ts { this.logger.log("CollectGarbage()"); } - this.logger = null; + this.logger = null!; super.dispose(dummy); } @@ -1034,14 +1034,14 @@ namespace ts { this.classifier = createClassifier(); } - public getEncodedLexicalClassifications(text: string, lexState: EndOfLineState, syntacticClassifierAbsent?: boolean): string { + public getEncodedLexicalClassifications(text: string, lexState: EndOfLineState, syntacticClassifierAbsent = false): string { return forwardJSONCall(this.logger, "getEncodedLexicalClassifications", () => convertClassifications(this.classifier.getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent)), this.logPerformance); } /// COLORIZATION - public getClassificationsForLine(text: string, lexState: EndOfLineState, classifyKeywordsInGenerics?: boolean): string { + public getClassificationsForLine(text: string, lexState: EndOfLineState, classifyKeywordsInGenerics = false): string { const classification = this.classifier.getClassificationsForLine(text, lexState, classifyKeywordsInGenerics); let result = ""; for (const item of classification.entries) { @@ -1119,7 +1119,7 @@ namespace ts { ); } - private convertFileReferences(refs: FileReference[]): ShimsFileReference[] { + private convertFileReferences(refs: FileReference[]): ShimsFileReference[] | undefined { if (!refs) { return undefined; } @@ -1230,7 +1230,7 @@ namespace ts { public close(): void { // Forget all the registered shims clear(this._shims); - this.documentRegistry = undefined; + this.documentRegistry = undefined!; } public registerShim(shim: Shim): void { diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts index 45cd828f5d7e7..61330757f0836 100644 --- a/src/services/signatureHelp.ts +++ b/src/services/signatureHelp.ts @@ -16,7 +16,7 @@ namespace ts.SignatureHelp { argumentCount: number; } - export function getSignatureHelpItems(program: Program, sourceFile: SourceFile, position: number, cancellationToken: CancellationToken): SignatureHelpItems { + export function getSignatureHelpItems(program: Program, sourceFile: SourceFile, position: number, cancellationToken: CancellationToken): SignatureHelpItems | undefined { const typeChecker = program.getTypeChecker(); // Decide whether to show signature help @@ -47,10 +47,10 @@ namespace ts.SignatureHelp { return undefined; } - return typeChecker.runWithCancellationToken(cancellationToken, typeChecker => createSignatureHelpItems(candidates, resolvedSignature, argumentInfo, typeChecker)); + return typeChecker.runWithCancellationToken(cancellationToken, typeChecker => createSignatureHelpItems(candidates, resolvedSignature!, argumentInfo, typeChecker)); } - function createJavaScriptSignatureHelpItems(argumentInfo: ArgumentListInfo, program: Program, cancellationToken: CancellationToken): SignatureHelpItems { + function createJavaScriptSignatureHelpItems(argumentInfo: ArgumentListInfo, program: Program, cancellationToken: CancellationToken): SignatureHelpItems | undefined { if (argumentInfo.invocation.kind !== SyntaxKind.CallExpression) { return undefined; } @@ -90,9 +90,9 @@ namespace ts.SignatureHelp { * in the argument of an invocation; returns undefined otherwise. */ export function getImmediatelyContainingArgumentInfo(node: Node, position: number, sourceFile: SourceFile): ArgumentListInfo | undefined { - if (isCallOrNewExpression(node.parent)) { - const invocation = node.parent; - let list: Node; + const { parent } = node; + if (isCallOrNewExpression(parent)) { + let list: Node | undefined; let argumentIndex: number; // There are 3 cases to handle: @@ -112,7 +112,7 @@ namespace ts.SignatureHelp { if (node.kind === SyntaxKind.LessThanToken || node.kind === SyntaxKind.OpenParenToken) { // Find the list that starts right *after* the < or ( token. // If the user has just opened a list, consider this item 0. - list = getChildListThatStartsWithOpenerToken(invocation, node, sourceFile); + list = getChildListThatStartsWithOpenerToken(parent, node, sourceFile); Debug.assert(list !== undefined); argumentIndex = 0; } @@ -128,22 +128,22 @@ namespace ts.SignatureHelp { argumentIndex = getArgumentIndex(list, node); } - const kind = invocation.typeArguments && invocation.typeArguments.pos === list.pos ? ArgumentListKind.TypeArguments : ArgumentListKind.CallArguments; + const kind = parent.typeArguments && parent.typeArguments.pos === list.pos ? ArgumentListKind.TypeArguments : ArgumentListKind.CallArguments; const argumentCount = getArgumentCount(list); if (argumentIndex !== 0) { Debug.assertLessThan(argumentIndex, argumentCount); } const argumentsSpan = getApplicableSpanForArguments(list, sourceFile); - return { kind, invocation, argumentsSpan, argumentIndex, argumentCount }; + return { kind, invocation: parent, argumentsSpan, argumentIndex, argumentCount }; } - else if (node.kind === SyntaxKind.NoSubstitutionTemplateLiteral && node.parent.kind === SyntaxKind.TaggedTemplateExpression) { + else if (node.kind === SyntaxKind.NoSubstitutionTemplateLiteral && parent.kind === SyntaxKind.TaggedTemplateExpression) { // Check if we're actually inside the template; // otherwise we'll fall out and return undefined. if (isInsideTemplateLiteral(node, position)) { return getArgumentListInfoForTemplate(node.parent, /*argumentIndex*/ 0, sourceFile); } } - else if (node.kind === SyntaxKind.TemplateHead && node.parent.parent.kind === SyntaxKind.TaggedTemplateExpression) { + else if (node.kind === SyntaxKind.TemplateHead && parent.parent.kind === SyntaxKind.TaggedTemplateExpression) { const templateExpression = node.parent; const tagExpression = templateExpression.parent; Debug.assert(templateExpression.kind === SyntaxKind.TemplateExpression); @@ -152,7 +152,7 @@ namespace ts.SignatureHelp { return getArgumentListInfoForTemplate(tagExpression, argumentIndex, sourceFile); } - else if (node.parent.kind === SyntaxKind.TemplateSpan && node.parent.parent.parent.kind === SyntaxKind.TaggedTemplateExpression) { + else if (parent.kind === SyntaxKind.TemplateSpan && parent.parent.parent.kind === SyntaxKind.TaggedTemplateExpression) { const templateSpan = node.parent; const templateExpression = templateSpan.parent; const tagExpression = templateExpression.parent; @@ -228,7 +228,7 @@ namespace ts.SignatureHelp { const listChildren = argumentsList.getChildren(); let argumentCount = countWhere(listChildren, arg => arg.kind !== SyntaxKind.CommaToken); - if (listChildren.length > 0 && lastOrUndefined(listChildren).kind === SyntaxKind.CommaToken) { + if (listChildren.length > 0 && last(listChildren).kind === SyntaxKind.CommaToken) { argumentCount++; } @@ -304,7 +304,7 @@ namespace ts.SignatureHelp { // This is because a Missing node has no width. However, what we actually want is to include trivia // leading up to the next token in case the user is about to type in a TemplateMiddle or TemplateTail. if (template.kind === SyntaxKind.TemplateExpression) { - const lastSpan = lastOrUndefined(template.templateSpans); + const lastSpan = last(template.templateSpans); if (lastSpan.literal.getFullWidth() === 0) { applicableSpanEnd = skipTrivia(sourceFile.text, applicableSpanEnd, /*stopAfterLineBreak*/ false); } @@ -313,7 +313,7 @@ namespace ts.SignatureHelp { return createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart); } - export function getContainingArgumentInfo(node: Node, position: number, sourceFile: SourceFile): ArgumentListInfo { + export function getContainingArgumentInfo(node: Node, position: number, sourceFile: SourceFile): ArgumentListInfo | undefined { for (let n = node; n.kind !== SyntaxKind.SourceFile; n = n.parent) { if (isFunctionBlock(n)) { return undefined; @@ -369,8 +369,8 @@ namespace ts.SignatureHelp { signatureHelpParameters = typeParameters && typeParameters.length > 0 ? map(typeParameters, createSignatureHelpParameterForTypeParameter) : emptyArray; suffixDisplayParts.push(punctuationPart(SyntaxKind.GreaterThanToken)); const parameterParts = mapToDisplayParts(writer => { - const thisParameter = candidateSignature.thisParameter ? [typeChecker.symbolToParameterDeclaration(candidateSignature.thisParameter, invocation, signatureHelpNodeBuilderFlags)] : []; - const params = createNodeArray([...thisParameter, ...map(candidateSignature.parameters, param => typeChecker.symbolToParameterDeclaration(param, invocation, signatureHelpNodeBuilderFlags))]); + const thisParameter = candidateSignature.thisParameter ? [typeChecker.symbolToParameterDeclaration(candidateSignature.thisParameter, invocation, signatureHelpNodeBuilderFlags)!] : []; + const params = createNodeArray([...thisParameter, ...map(candidateSignature.parameters, param => typeChecker.symbolToParameterDeclaration(param, invocation, signatureHelpNodeBuilderFlags)!)]); printer.writeList(ListFormat.CallExpressionArguments, params, getSourceFileOfNode(getParseTreeNode(invocation)), writer); }); addRange(suffixDisplayParts, parameterParts); @@ -379,7 +379,7 @@ namespace ts.SignatureHelp { isVariadic = candidateSignature.hasRestParameter; const typeParameterParts = mapToDisplayParts(writer => { if (candidateSignature.typeParameters && candidateSignature.typeParameters.length) { - const args = createNodeArray(map(candidateSignature.typeParameters, p => typeChecker.typeParameterToDeclaration(p, invocation))); + const args = createNodeArray(map(candidateSignature.typeParameters, p => typeChecker.typeParameterToDeclaration(p, invocation)!)); printer.writeList(ListFormat.TypeParameters, args, getSourceFileOfNode(getParseTreeNode(invocation)), writer); } }); @@ -415,17 +415,17 @@ namespace ts.SignatureHelp { }); if (argumentIndex !== 0) { - Debug.assertLessThan(argumentIndex, argumentCount); + Debug.assertLessThan(argumentIndex!, argumentCount); // TODO: GH#18217 } const selectedItemIndex = candidates.indexOf(resolvedSignature); Debug.assert(selectedItemIndex !== -1); // If candidates is non-empty it should always include bestSignature. We check for an empty candidates before calling this function. - return { items, applicableSpan, selectedItemIndex, argumentIndex, argumentCount }; + return { items, applicableSpan, selectedItemIndex, argumentIndex: argumentIndex!, argumentCount }; // TODO: GH#18217 function createSignatureHelpParameterForParameter(parameter: Symbol): SignatureHelpParameter { const displayParts = mapToDisplayParts(writer => { - const param = typeChecker.symbolToParameterDeclaration(parameter, invocation, signatureHelpNodeBuilderFlags); + const param = typeChecker.symbolToParameterDeclaration(parameter, invocation, signatureHelpNodeBuilderFlags)!; printer.writeNode(EmitHint.Unspecified, param, getSourceFileOfNode(getParseTreeNode(invocation)), writer); }); @@ -439,7 +439,7 @@ namespace ts.SignatureHelp { function createSignatureHelpParameterForTypeParameter(typeParameter: TypeParameter): SignatureHelpParameter { const displayParts = mapToDisplayParts(writer => { - const param = typeChecker.typeParameterToDeclaration(typeParameter, invocation); + const param = typeChecker.typeParameterToDeclaration(typeParameter, invocation)!; printer.writeNode(EmitHint.Unspecified, param, getSourceFileOfNode(getParseTreeNode(invocation)), writer); }); diff --git a/src/services/sourcemaps.ts b/src/services/sourcemaps.ts index c24ed0f64a8f4..9fa997f7a7fd8 100644 --- a/src/services/sourcemaps.ts +++ b/src/services/sourcemaps.ts @@ -23,7 +23,7 @@ namespace ts.sourcemaps { export const identitySourceMapper = { getOriginalPosition: identity, getGeneratedPosition: identity }; export interface SourceMapDecodeHost { - readFile(path: string): string; + readFile(path: string): string | undefined; fileExists(path: string): boolean; getCanonicalFileName(path: string): string; log(text: string): void; @@ -52,7 +52,7 @@ namespace ts.sourcemaps { if (!maps[targetIndex] || comparePaths(loc.fileName, maps[targetIndex].sourcePath, sourceRoot) !== 0) { return loc; } - return { fileName: toPath(map.file, sourceRoot, host.getCanonicalFileName), position: maps[targetIndex].emittedPosition }; // Closest pos + return { fileName: toPath(map.file!, sourceRoot, host.getCanonicalFileName), position: maps[targetIndex].emittedPosition }; // Closest pos } function getOriginalPosition(loc: SourceMappableLocation): SourceMappableLocation { @@ -68,7 +68,7 @@ namespace ts.sourcemaps { function getSourceFileLike(fileName: string, location: string): SourceFileLike | undefined { // Lookup file in program, if provided - const file: SourceFileLike = program && program.getSourceFile(fileName); + const file = program && program.getSourceFile(fileName); if (!file) { // Otherwise check the cache (which may hit disk) const path = toPath(fileName, location, host.getCanonicalFileName); @@ -133,7 +133,7 @@ namespace ts.sourcemaps { function processPosition(position: RawSourceMapPosition): ProcessedSourceMapPosition { const sourcePath = map.sources[position.sourceIndex]; return { - emittedPosition: getPositionOfLineAndCharacterUsingName(map.file, currentDirectory, position.emittedLine, position.emittedColumn), + emittedPosition: getPositionOfLineAndCharacterUsingName(map.file!, currentDirectory, position.emittedLine, position.emittedColumn), sourcePosition: getPositionOfLineAndCharacterUsingName(sourcePath, sourceRoot, position.sourceLine, position.sourceColumn), sourcePath, // TODO: Consider using `name` field to remap the expected identifier to scan for renames to handle another tool renaming oout output @@ -164,7 +164,7 @@ namespace ts.sourcemaps { currentSourceLine: number; currentSourceColumn: number; currentSourceIndex: number; - currentNameIndex: number; + currentNameIndex: number | undefined; encodedText: string; sourceMapNamesLength?: number; error?: string; @@ -282,14 +282,14 @@ namespace ts.sourcemaps { return condition; } - function base64VLQFormatDecode() { + function base64VLQFormatDecode(): number { let moreDigits = true; let shiftCount = 0; let value = 0; for (; moreDigits; state.decodingIndex++) { if (createErrorIfCondition(state.decodingIndex >= state.encodedText.length, "Error in decoding base64VLQFormatDecode, past the mapping string")) { - return; + return undefined!; // TODO: GH#18217 } // 6 digit number diff --git a/src/services/suggestionDiagnostics.ts b/src/services/suggestionDiagnostics.ts index c59c267d16448..4e09b97fec85e 100644 --- a/src/services/suggestionDiagnostics.ts +++ b/src/services/suggestionDiagnostics.ts @@ -18,8 +18,7 @@ namespace ts { case SyntaxKind.FunctionDeclaration: case SyntaxKind.FunctionExpression: if (isJsFile) { - const symbol = node.symbol; - if (symbol.members && (symbol.members.size > 0)) { + if (node.symbol.members && (node.symbol.members.size > 0)) { diags.push(createDiagnosticForNode(isVariableDeclaration(node.parent) ? node.parent.name : node, Diagnostics.This_constructor_function_may_be_converted_to_a_class_declaration)); } } @@ -70,7 +69,7 @@ namespace ts { switch (statement.kind) { case SyntaxKind.VariableStatement: return (statement as VariableStatement).declarationList.declarations.some(decl => - isRequireCall(propertyAccessLeftHandSide(decl.initializer), /*checkArgumentIsStringLiteralLike*/ true)); + isRequireCall(propertyAccessLeftHandSide(decl.initializer!), /*checkArgumentIsStringLiteralLike*/ true)); // TODO: GH#18217 case SyntaxKind.ExpressionStatement: { const { expression } = statement as ExpressionStatement; if (!isBinaryExpression(expression)) return isRequireCall(expression, /*checkArgumentIsStringLiteralLike*/ true); @@ -91,7 +90,7 @@ namespace ts { switch (node.kind) { case SyntaxKind.ImportDeclaration: const { importClause, moduleSpecifier } = node; - return importClause && !importClause.name && importClause.namedBindings.kind === SyntaxKind.NamespaceImport && isStringLiteral(moduleSpecifier) + return importClause && !importClause.name && importClause.namedBindings && importClause.namedBindings.kind === SyntaxKind.NamespaceImport && isStringLiteral(moduleSpecifier) ? importClause.namedBindings.name : undefined; case SyntaxKind.ImportEqualsDeclaration: diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts index 854f5297d6885..2945d641c0915 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -117,24 +117,24 @@ namespace ts.SymbolDisplay { displayParts: SymbolDisplayPart[]; documentation: SymbolDisplayPart[]; symbolKind: ScriptElementKind; - tags: JSDocTagInfo[]; + tags: JSDocTagInfo[] | undefined; } // TODO(drosen): Currently completion entry details passes the SemanticMeaning.All instead of using semanticMeaning of location - export function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker: TypeChecker, symbol: Symbol, sourceFile: SourceFile, enclosingDeclaration: Node, + export function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker: TypeChecker, symbol: Symbol, sourceFile: SourceFile, enclosingDeclaration: Node | undefined, location: Node, semanticMeaning = getMeaningFromLocation(location), alias?: Symbol): SymbolDisplayPartsDocumentationAndSymbolKind { const displayParts: SymbolDisplayPart[] = []; - let documentation: SymbolDisplayPart[]; - let tags: JSDocTagInfo[]; + let documentation: SymbolDisplayPart[] | undefined; + let tags: JSDocTagInfo[] | undefined; const symbolFlags = getCombinedLocalAndExportSymbolFlags(symbol); let symbolKind = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeChecker, symbol, location); - let hasAddedSymbolInfo: boolean; + let hasAddedSymbolInfo = false; const isThisExpression = location.kind === SyntaxKind.ThisKeyword && isExpression(location); - let type: Type; + let type: Type | undefined; let printer: Printer; - let documentationFromAlias: SymbolDisplayPart[]; - let tagsFromAlias: JSDocTagInfo[]; + let documentationFromAlias: SymbolDisplayPart[] | undefined; + let tagsFromAlias: JSDocTagInfo[] | undefined; // Class at constructor site need to be shown as constructor apart from property,method, vars if (symbolKind !== ScriptElementKind.unknown || symbolFlags & SymbolFlags.Class || symbolFlags & SymbolFlags.Alias) { @@ -143,7 +143,7 @@ namespace ts.SymbolDisplay { symbolKind = ScriptElementKind.memberVariableElement; } - let signature: Signature; + let signature: Signature | undefined; type = isThisExpression ? typeChecker.getTypeAtLocation(location) : typeChecker.getTypeOfSymbolAtLocation(symbol.exportSymbol || symbol, location); if (location.parent && location.parent.kind === SyntaxKind.PropertyAccessExpression) { @@ -155,7 +155,7 @@ namespace ts.SymbolDisplay { } // try get the call/construct signature from the type if it matches - let callExpressionLike: CallExpression | NewExpression | JsxOpeningLikeElement; + let callExpressionLike: CallExpression | NewExpression | JsxOpeningLikeElement | undefined; if (isCallOrNewExpression(location)) { callExpressionLike = location; } @@ -168,11 +168,11 @@ namespace ts.SymbolDisplay { if (callExpressionLike) { const candidateSignatures: Signature[] = []; - signature = typeChecker.getResolvedSignature(callExpressionLike, candidateSignatures); + signature = typeChecker.getResolvedSignature(callExpressionLike, candidateSignatures)!; // TODO: GH#18217 const useConstructSignatures = callExpressionLike.kind === SyntaxKind.NewExpression || (isCallExpression(callExpressionLike) && callExpressionLike.expression.kind === SyntaxKind.SuperKeyword); - const allSignatures = useConstructSignatures ? type.getConstructSignatures() : type.getCallSignatures(); + const allSignatures = useConstructSignatures ? type!.getConstructSignatures() : type!.getCallSignatures(); if (!contains(allSignatures, signature.target) && !contains(allSignatures, signature)) { // Get the first signature if there is one -- allSignatures may contain @@ -184,7 +184,7 @@ namespace ts.SymbolDisplay { if (useConstructSignatures && (symbolFlags & SymbolFlags.Class)) { // Constructor symbolKind = ScriptElementKind.constructorImplementationElement; - addPrefixForAnyFunctionOrVar(type.symbol, symbolKind); + addPrefixForAnyFunctionOrVar(type!.symbol, symbolKind); } else if (symbolFlags & SymbolFlags.Alias) { symbolKind = ScriptElementKind.alias; @@ -211,8 +211,8 @@ namespace ts.SymbolDisplay { // If it is call or construct signature of lambda's write type name displayParts.push(punctuationPart(SyntaxKind.ColonToken)); displayParts.push(spacePart()); - if (!(getObjectFlags(type) & ObjectFlags.Anonymous) && type.symbol) { - addRange(displayParts, symbolToDisplayParts(typeChecker, type.symbol, enclosingDeclaration, /*meaning*/ undefined, SymbolFormatFlags.AllowAnyNodeKind | SymbolFormatFlags.WriteTypeParametersOrArguments)); + if (!(getObjectFlags(type!) & ObjectFlags.Anonymous) && type!.symbol) { + addRange(displayParts, symbolToDisplayParts(typeChecker, type!.symbol, enclosingDeclaration, /*meaning*/ undefined, SymbolFormatFlags.AllowAnyNodeKind | SymbolFormatFlags.WriteTypeParametersOrArguments)); displayParts.push(lineBreakPart()); } if (useConstructSignatures) { @@ -238,9 +238,9 @@ namespace ts.SymbolDisplay { declaration === (location.kind === SyntaxKind.ConstructorKeyword ? functionDeclaration.parent : functionDeclaration)); if (locationIsSymbolDeclaration) { - const allSignatures = functionDeclaration.kind === SyntaxKind.Constructor ? type.getNonNullableType().getConstructSignatures() : type.getNonNullableType().getCallSignatures(); + const allSignatures = functionDeclaration.kind === SyntaxKind.Constructor ? type!.getNonNullableType().getConstructSignatures() : type!.getNonNullableType().getCallSignatures(); if (!typeChecker.isImplementationOfOverload(functionDeclaration)) { - signature = typeChecker.getSignatureFromDeclaration(functionDeclaration); + signature = typeChecker.getSignatureFromDeclaration(functionDeclaration)!; // TODO: GH#18217 } else { signature = allSignatures[0]; @@ -249,12 +249,12 @@ namespace ts.SymbolDisplay { if (functionDeclaration.kind === SyntaxKind.Constructor) { // show (constructor) Type(...) signature symbolKind = ScriptElementKind.constructorImplementationElement; - addPrefixForAnyFunctionOrVar(type.symbol, symbolKind); + addPrefixForAnyFunctionOrVar(type!.symbol, symbolKind); } else { // (function/method) symbol(..signature) addPrefixForAnyFunctionOrVar(functionDeclaration.kind === SyntaxKind.CallSignature && - !(type.symbol.flags & SymbolFlags.TypeLiteral || type.symbol.flags & SymbolFlags.ObjectLiteral) ? type.symbol : symbol, symbolKind); + !(type!.symbol.flags & SymbolFlags.TypeLiteral || type!.symbol.flags & SymbolFlags.ObjectLiteral) ? type!.symbol : symbol, symbolKind); } addSignatureDisplayParts(signature, allSignatures); @@ -330,13 +330,13 @@ namespace ts.SymbolDisplay { else { // Method/function type parameter const decl = getDeclarationOfKind(symbol, SyntaxKind.TypeParameter); - Debug.assert(decl !== undefined); + if (decl === undefined) return Debug.fail(); const declaration = decl.parent; if (declaration) { if (isFunctionLikeKind(declaration.kind)) { addInPrefix(); - const signature = typeChecker.getSignatureFromDeclaration(declaration); + const signature = typeChecker.getSignatureFromDeclaration(declaration)!; // TODO: GH#18217 if (declaration.kind === SyntaxKind.ConstructSignature) { displayParts.push(keywordPart(SyntaxKind.NewKeyword)); displayParts.push(spacePart()); @@ -468,7 +468,7 @@ namespace ts.SymbolDisplay { // If the type is type parameter, format it specially if (type.symbol && type.symbol.flags & SymbolFlags.TypeParameter) { const typeParameterParts = mapToDisplayParts(writer => { - const param = typeChecker.typeParameterToDeclaration(type as TypeParameter, enclosingDeclaration); + const param = typeChecker.typeParameterToDeclaration(type as TypeParameter, enclosingDeclaration)!; getPrinter().writeNode(EmitHint.Unspecified, param, getSourceFileOfNode(getParseTreeNode(enclosingDeclaration)), writer); }); addRange(displayParts, typeParameterParts); @@ -526,11 +526,11 @@ namespace ts.SymbolDisplay { if (documentation.length === 0 && documentationFromAlias) { documentation = documentationFromAlias; } - if (tags.length === 0 && tagsFromAlias) { + if (tags!.length === 0 && tagsFromAlias) { tags = tagsFromAlias; } - return { displayParts, documentation, symbolKind, tags }; + return { displayParts, documentation, symbolKind, tags: tags! }; function getPrinter() { if (!printer) { @@ -600,7 +600,7 @@ namespace ts.SymbolDisplay { } } - function addSignatureDisplayParts(signature: Signature, allSignatures: Signature[], flags?: TypeFormatFlags) { + function addSignatureDisplayParts(signature: Signature, allSignatures: Signature[], flags = TypeFormatFlags.None) { addRange(displayParts, signatureToDisplayParts(typeChecker, signature, enclosingDeclaration, flags | TypeFormatFlags.WriteTypeArgumentsOfSignature)); if (allSignatures.length > 1) { displayParts.push(spacePart()); @@ -615,7 +615,7 @@ namespace ts.SymbolDisplay { tags = signature.getJsDocTags(); } - function writeTypeParametersOfSymbol(symbol: Symbol, enclosingDeclaration: Node) { + function writeTypeParametersOfSymbol(symbol: Symbol, enclosingDeclaration: Node | undefined) { const typeParameterParts = mapToDisplayParts(writer => { const params = typeChecker.symbolToTypeParameterDeclarations(symbol, enclosingDeclaration); getPrinter().writeList(ListFormat.TypeParameters, params, getSourceFileOfNode(getParseTreeNode(enclosingDeclaration)), writer); diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index 6002b79d2c476..b14806c957159 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -190,8 +190,8 @@ namespace ts.textChanges { /** * Checks if 'candidate' argument is a legal separator in the list that contains 'node' as an element */ - function isSeparator(node: Node, candidate: Node): candidate is Token { - return candidate && node.parent && (candidate.kind === SyntaxKind.CommaToken || (candidate.kind === SyntaxKind.SemicolonToken && node.parent.kind === SyntaxKind.ObjectLiteralExpression)); + function isSeparator(node: Node, candidate: Node | undefined): candidate is Token { + return !!candidate && !!node.parent && (candidate.kind === SyntaxKind.CommaToken || (candidate.kind === SyntaxKind.SemicolonToken && node.parent.kind === SyntaxKind.ObjectLiteralExpression)); } function spaces(count: number) { @@ -359,7 +359,7 @@ namespace ts.textChanges { /** Prefer this over replacing a node with another that has a type annotation, as it avoids reformatting the other parts of the node. */ public tryInsertTypeAnnotation(sourceFile: SourceFile, node: TypeAnnotatable, type: TypeNode): void { - let endNode: Node; + let endNode: Node | undefined; if (isFunctionLike(node)) { endNode = findChildOfKind(node, SyntaxKind.CloseParenToken, sourceFile); if (!endNode) { @@ -395,9 +395,9 @@ namespace ts.textChanges { } public insertNodeAtConstructorStart(sourceFile: SourceFile, ctr: ConstructorDeclaration, newStatement: Statement): void { - const firstStatement = firstOrUndefined(ctr.body.statements); - if (!firstStatement || !ctr.body.multiLine) { - this.replaceConstructorBody(sourceFile, ctr, [newStatement, ...ctr.body.statements]); + const firstStatement = firstOrUndefined(ctr.body!.statements); + if (!firstStatement || !ctr.body!.multiLine) { + this.replaceConstructorBody(sourceFile, ctr, [newStatement, ...ctr.body!.statements]); } else { this.insertNodeBefore(sourceFile, firstStatement, newStatement); @@ -405,9 +405,9 @@ namespace ts.textChanges { } public insertNodeAtConstructorEnd(sourceFile: SourceFile, ctr: ConstructorDeclaration, newStatement: Statement): void { - const lastStatement = lastOrUndefined(ctr.body.statements); - if (!lastStatement || !ctr.body.multiLine) { - this.replaceConstructorBody(sourceFile, ctr, [...ctr.body.statements, newStatement]); + const lastStatement = lastOrUndefined(ctr.body!.statements); + if (!lastStatement || !ctr.body!.multiLine) { + this.replaceConstructorBody(sourceFile, ctr, [...ctr.body!.statements, newStatement]); } else { this.insertNodeAfter(sourceFile, lastStatement, newStatement); @@ -415,13 +415,13 @@ namespace ts.textChanges { } private replaceConstructorBody(sourceFile: SourceFile, ctr: ConstructorDeclaration, statements: ReadonlyArray): void { - this.replaceNode(sourceFile, ctr.body, createBlock(statements, /*multiLine*/ true)); + this.replaceNode(sourceFile, ctr.body!, createBlock(statements, /*multiLine*/ true)); } public insertNodeAtEndOfScope(sourceFile: SourceFile, scope: Node, newNode: Node): void { - const pos = getAdjustedStartPosition(sourceFile, scope.getLastToken(), {}, Position.Start); + const pos = getAdjustedStartPosition(sourceFile, scope.getLastToken()!, {}, Position.Start); this.replaceRange(sourceFile, { pos, end: pos }, newNode, { - prefix: isLineBreak(sourceFile.text.charCodeAt(scope.getLastToken().pos)) ? this.newLineCharacter : this.newLineCharacter + this.newLineCharacter, + prefix: isLineBreak(sourceFile.text.charCodeAt(scope.getLastToken()!.pos)) ? this.newLineCharacter : this.newLineCharacter + this.newLineCharacter, suffix: this.newLineCharacter }); } @@ -429,7 +429,7 @@ namespace ts.textChanges { public insertNodeAtClassStart(sourceFile: SourceFile, cls: ClassLikeDeclaration, newElement: ClassElement): void { const clsStart = cls.getStart(sourceFile); const indentation = formatting.SmartIndenter.findFirstNonWhitespaceColumn(getLineStartPositionForPosition(clsStart, sourceFile), clsStart, sourceFile, this.formatContext.options) - + this.formatContext.options.indentSize; + + this.formatContext.options.indentSize!; this.insertNodeAt(sourceFile, cls.members.pos, newElement, { indentation, ...this.getInsertNodeAtClassStartPrefixSuffix(sourceFile, cls) }); } @@ -575,7 +575,7 @@ namespace ts.textChanges { const lineAndCharOfNextElement = getLineAndCharacterOfPosition(sourceFile, skipWhitespacesAndLineBreaks(sourceFile.text, containingList[index + 1].getFullStart())); // find line and character of the token that precedes next element (usually it is separator) const lineAndCharOfNextToken = getLineAndCharacterOfPosition(sourceFile, nextToken.end); - let prefix: string; + let prefix: string | undefined; let startPos: number; if (lineAndCharOfNextToken.line === lineAndCharOfNextElement.line) { // next element is located on the same line with separator: @@ -608,7 +608,7 @@ namespace ts.textChanges { const afterStart = after.getStart(sourceFile); const afterStartLinePosition = getLineStartPositionForPosition(afterStart, sourceFile); - let separator: SyntaxKind.CommaToken | SyntaxKind.SemicolonToken; + let separator: SyntaxKind.CommaToken | SyntaxKind.SemicolonToken | undefined; let multilineList = false; // insert element after the last element in the list that has more than one item @@ -666,7 +666,7 @@ namespace ts.textChanges { private finishTrailingCommaAfterDeletingNodesInList() { this.deletedNodesInLists.forEach(node => { const sourceFile = node.getSourceFile(); - const list = formatting.SmartIndenter.getContainingList(node, sourceFile); + const list = formatting.SmartIndenter.getContainingList(node, sourceFile)!; if (node !== last(list)) return; const lastNonDeletedIndex = findLastIndex(list, n => !this.deletedNodesInLists.has(n), list.length - 2); @@ -703,13 +703,13 @@ namespace ts.textChanges { } function getClassBraceEnds(cls: ClassLikeDeclaration, sourceFile: SourceFile): [number, number] { - return [findChildOfKind(cls, SyntaxKind.OpenBraceToken, sourceFile).end, findChildOfKind(cls, SyntaxKind.CloseBraceToken, sourceFile).end]; + return [findChildOfKind(cls, SyntaxKind.OpenBraceToken, sourceFile)!.end, findChildOfKind(cls, SyntaxKind.CloseBraceToken, sourceFile)!.end]; } export type ValidateNonFormattedText = (node: Node, text: string) => void; namespace changesToText { - export function getTextChangesFromChanges(changes: ReadonlyArray, newLineCharacter: string, formatContext: formatting.FormatContext, validate: ValidateNonFormattedText): FileTextChanges[] { + export function getTextChangesFromChanges(changes: ReadonlyArray, newLineCharacter: string, formatContext: formatting.FormatContext, validate: ValidateNonFormattedText | undefined): FileTextChanges[] { return group(changes, c => c.sourceFile.path).map(changesInFile => { const sourceFile = changesInFile[0].sourceFile; // order changes by start position @@ -731,7 +731,7 @@ namespace ts.textChanges { return { fileName, textChanges: [createTextChange(createTextSpan(0, 0), text)], isNewFile: true }; } - function computeNewText(change: Change, sourceFile: SourceFile, newLineCharacter: string, formatContext: formatting.FormatContext, validate: ValidateNonFormattedText): string { + function computeNewText(change: Change, sourceFile: SourceFile, newLineCharacter: string, formatContext: formatting.FormatContext, validate: ValidateNonFormattedText | undefined): string { if (change.kind === ChangeKind.Remove) { return ""; } @@ -742,7 +742,7 @@ namespace ts.textChanges { const { options = {}, range: { pos } } = change; const format = (n: Node) => getFormattedTextOfNode(n, sourceFile, pos, options, newLineCharacter, formatContext, validate); const text = change.kind === ChangeKind.ReplaceWithMultipleNodes - ? change.nodes.map(n => removeSuffix(format(n), newLineCharacter)).join(change.options.joiner || newLineCharacter) + ? change.nodes.map(n => removeSuffix(format(n), newLineCharacter)).join(change.options!.joiner || newLineCharacter) // TODO: GH#18217 : format(change.node); // strip initial indentation (spaces or tabs) if text will be inserted in the middle of the line const noIndent = (options.preserveLeadingWhitespace || options.indentation !== undefined || getLineStartPositionForPosition(pos, sourceFile) === pos) ? text : text.replace(/^\s+/, ""); @@ -750,7 +750,7 @@ namespace ts.textChanges { } /** Note: this may mutate `nodeIn`. */ - function getFormattedTextOfNode(nodeIn: Node, sourceFile: SourceFile, pos: number, { indentation, prefix, delta }: InsertNodeOptions, newLineCharacter: string, formatContext: formatting.FormatContext, validate: ValidateNonFormattedText): string { + function getFormattedTextOfNode(nodeIn: Node, sourceFile: SourceFile, pos: number, { indentation, prefix, delta }: InsertNodeOptions, newLineCharacter: string, formatContext: formatting.FormatContext, validate: ValidateNonFormattedText | undefined): string { const { node, text } = getNonformattedText(nodeIn, sourceFile, newLineCharacter); if (validate) validate(node, text); const { options: formatOptions } = formatContext; @@ -789,7 +789,7 @@ namespace ts.textChanges { } function assignPositionsToNode(node: Node): Node { - const visited = visitEachChild(node, assignPositionsToNode, nullTransformationContext, assignPositionsToNodeArray, assignPositionsToNode); + const visited = visitEachChild(node, assignPositionsToNode, nullTransformationContext, assignPositionsToNodeArray, assignPositionsToNode)!; // TODO: GH#18217 // create proxy node for non synthesized nodes const newNode = nodeIsSynthesized(visited) ? visited : Object.create(visited) as Node; newNode.pos = getPos(node); @@ -991,7 +991,7 @@ namespace ts.textChanges { } function needSemicolonBetween(a: Node, b: Node): boolean { - return (isPropertySignature(a) || isPropertyDeclaration(a)) && isClassOrTypeElement(b) && b.name.kind === SyntaxKind.ComputedPropertyName + return (isPropertySignature(a) || isPropertyDeclaration(a)) && isClassOrTypeElement(b) && b.name!.kind === SyntaxKind.ComputedPropertyName || isStatementButNotDeclaration(a) && isStatementButNotDeclaration(b); // TODO: only if b would start with a `(` or `[` } } diff --git a/src/services/transform.ts b/src/services/transform.ts index b6b2a35708104..a3d0d7b10c3f0 100644 --- a/src/services/transform.ts +++ b/src/services/transform.ts @@ -7,7 +7,7 @@ namespace ts { */ export function transform(source: T | T[], transformers: TransformerFactory[], compilerOptions?: CompilerOptions) { const diagnostics: DiagnosticWithLocation[] = []; - compilerOptions = fixupCompilerOptions(compilerOptions, diagnostics); + compilerOptions = fixupCompilerOptions(compilerOptions!, diagnostics); // TODO: GH#18217 const nodes = isArray(source) ? source : [source]; const result = transformNodes(/*resolver*/ undefined, /*emitHost*/ undefined, compilerOptions, nodes, transformers, /*allowDtsFiles*/ true); result.diagnostics = concatenate(result.diagnostics, diagnostics); diff --git a/src/services/transpile.ts b/src/services/transpile.ts index 000bd124fa753..70ca5b6431438 100644 --- a/src/services/transpile.ts +++ b/src/services/transpile.ts @@ -58,7 +58,7 @@ namespace ts { // if jsx is specified then treat file as .tsx const inputFileName = transpileOptions.fileName || (options.jsx ? "module.tsx" : "module.ts"); - const sourceFile = createSourceFile(inputFileName, input, options.target); + const sourceFile = createSourceFile(inputFileName, input, options.target!); // TODO: GH#18217 if (transpileOptions.moduleName) { sourceFile.moduleName = transpileOptions.moduleName; } @@ -70,8 +70,8 @@ namespace ts { const newLine = getNewLineCharacter(options); // Output - let outputText: string; - let sourceMapText: string; + let outputText: string | undefined; + let sourceMapText: string | undefined; // Create a compilerHost object to allow the compiler to read and write files const compilerHost: CompilerHost = { @@ -106,7 +106,7 @@ namespace ts { // Emit program.emit(/*targetSourceFile*/ undefined, /*writeFile*/ undefined, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ undefined, transpileOptions.transformers); - Debug.assert(outputText !== undefined, "Output generation failed"); + if (outputText === undefined) return Debug.fail("Output generation failed"); return { outputText, diagnostics, sourceMapText }; } diff --git a/src/services/types.ts b/src/services/types.ts index b1b0ccd6de885..4dcd59d22b554 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -18,8 +18,8 @@ namespace ts { getLeadingTriviaWidth(sourceFile?: SourceFile): number; getFullText(sourceFile?: SourceFile): string; getText(sourceFile?: SourceFile): string; - getFirstToken(sourceFile?: SourceFile): Node; - getLastToken(sourceFile?: SourceFile): Node; + getFirstToken(sourceFile?: SourceFile): Node | undefined; + getLastToken(sourceFile?: SourceFile): Node | undefined; // See ts.forEachChild for documentation. forEachChild(cbNode: (node: Node) => T | undefined, cbNodeArray?: (nodes: NodeArray) => T | undefined): T | undefined; } @@ -75,8 +75,8 @@ namespace ts { export interface SourceFile { /* @internal */ version: string; - /* @internal */ scriptSnapshot: IScriptSnapshot; - /* @internal */ nameTable: UnderscoreEscapedMap; + /* @internal */ scriptSnapshot: IScriptSnapshot | undefined; + /* @internal */ nameTable: UnderscoreEscapedMap | undefined; /* @internal */ getNamedDeclarations(): Map; @@ -140,7 +140,7 @@ namespace ts { return this.text.length; } - public getChangeRange(): TextChangeRange { + public getChangeRange(): TextChangeRange | undefined { // Text-based snapshots do not support incremental parsing. Return undefined // to signal that to the caller. return undefined; @@ -155,7 +155,7 @@ namespace ts { referencedFiles: FileReference[]; typeReferenceDirectives: FileReference[]; importedFiles: FileReference[]; - ambientExternalModules: string[]; + ambientExternalModules?: string[]; isLibFile: boolean; } @@ -211,7 +211,7 @@ namespace ts { * If this is implemented, `getResolvedModuleWithFailedLookupLocationsFromCache` should be too. */ resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[]): ResolvedModule[]; - getResolvedModuleWithFailedLookupLocationsFromCache?(modulename: string, containingFile: string): ResolvedModuleWithFailedLookupLocations; + getResolvedModuleWithFailedLookupLocationsFromCache?(modulename: string, containingFile: string): ResolvedModuleWithFailedLookupLocations | undefined; resolveTypeReferenceDirectives?(typeDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[]; /* @internal */ hasInvalidatedResolution?: HasInvalidatedResolution; /* @internal */ hasChangedAutomaticTypeDirectiveNames?: boolean; @@ -272,7 +272,7 @@ namespace ts { getEncodedSyntacticClassifications(fileName: string, span: TextSpan): Classifications; getEncodedSemanticClassifications(fileName: string, span: TextSpan): Classifications; - getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions | undefined): CompletionInfo; + getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions | undefined): CompletionInfo | undefined; // "options" and "source" are optional only for backwards-compatibility getCompletionEntryDetails( fileName: string, @@ -281,31 +281,31 @@ namespace ts { formatOptions: FormatCodeOptions | FormatCodeSettings | undefined, source: string | undefined, preferences: UserPreferences | undefined, - ): CompletionEntryDetails; - getCompletionEntrySymbol(fileName: string, position: number, name: string, source: string | undefined): Symbol; + ): CompletionEntryDetails | undefined; + getCompletionEntrySymbol(fileName: string, position: number, name: string, source: string | undefined): Symbol | undefined; - getQuickInfoAtPosition(fileName: string, position: number): QuickInfo; + getQuickInfoAtPosition(fileName: string, position: number): QuickInfo | undefined; - getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan; + getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan | undefined; - getBreakpointStatementAtPosition(fileName: string, position: number): TextSpan; + getBreakpointStatementAtPosition(fileName: string, position: number): TextSpan | undefined; - getSignatureHelpItems(fileName: string, position: number): SignatureHelpItems; + getSignatureHelpItems(fileName: string, position: number): SignatureHelpItems | undefined; getRenameInfo(fileName: string, position: number): RenameInfo; - findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[]; + findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[] | undefined; - getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[]; - getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan; - getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[]; - getImplementationAtPosition(fileName: string, position: number): ImplementationLocation[]; + getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] | undefined; + getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan | undefined; + getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] | undefined; + getImplementationAtPosition(fileName: string, position: number): ImplementationLocation[] | undefined; - getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[]; - findReferences(fileName: string, position: number): ReferencedSymbol[]; - getDocumentHighlights(fileName: string, position: number, filesToSearch: string[]): DocumentHighlights[]; + getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] | undefined; + findReferences(fileName: string, position: number): ReferencedSymbol[] | undefined; + getDocumentHighlights(fileName: string, position: number, filesToSearch: string[]): DocumentHighlights[] | undefined; /** @deprecated */ - getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[]; + getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[] | undefined; getNavigateToItems(searchValue: string, maxResultCount?: number, fileName?: string, excludeDtsFiles?: boolean): NavigateToItem[]; getNavigationBarItems(fileName: string): NavigationBarItem[]; @@ -320,11 +320,11 @@ namespace ts { getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[]; getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[]; - getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion; + getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion | undefined; isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean; - getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan; + getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan | undefined; toLineColumnOffset?(fileName: string, position: number): LineAndCharacter; @@ -346,7 +346,7 @@ namespace ts { getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean): EmitOutput; - getProgram(): Program; + getProgram(): Program | undefined; /* @internal */ getNonBoundSourceFile(fileName: string): SourceFile; @@ -471,7 +471,7 @@ namespace ts { export interface CombinedCodeActions { changes: ReadonlyArray; - commands: ReadonlyArray | undefined; + commands?: ReadonlyArray; } // Publicly, this type is just `{}`. Internally it is a union of all the actions we use. @@ -533,8 +533,8 @@ namespace ts { */ export interface RefactorEditInfo { edits: FileTextChanges[]; - renameFilename: string | undefined; - renameLocation: number | undefined; + renameFilename?: string ; + renameLocation?: number; commands?: CodeActionCommand[]; } @@ -617,6 +617,7 @@ namespace ts { IndentStyle: IndentStyle; } + // TODO: GH#18217 These are frequently asserted as defined export interface EditorSettings { baseIndentSize?: number; indentSize?: number; @@ -674,7 +675,7 @@ namespace ts { } export interface DefinitionInfoAndBoundSpan { - definitions: ReadonlyArray; + definitions?: ReadonlyArray; textSpan: TextSpan; } @@ -726,14 +727,14 @@ namespace ts { kind: ScriptElementKind; kindModifiers: string; textSpan: TextSpan; - displayParts: SymbolDisplayPart[]; - documentation: SymbolDisplayPart[]; - tags: JSDocTagInfo[]; + displayParts?: SymbolDisplayPart[]; + documentation?: SymbolDisplayPart[]; + tags?: JSDocTagInfo[]; } export interface RenameInfo { canRename: boolean; - localizedErrorMessage: string; + localizedErrorMessage?: string; displayName: string; fullDisplayName: string; kind: ScriptElementKind; @@ -792,7 +793,7 @@ namespace ts { export interface CompletionEntry { name: string; kind: ScriptElementKind; - kindModifiers: string; // see ScriptElementKindModifier, comma separated + kindModifiers?: string; // see ScriptElementKindModifier, comma separated sortText: string; insertText?: string; /** @@ -811,8 +812,8 @@ namespace ts { kind: ScriptElementKind; kindModifiers: string; // see ScriptElementKindModifier, comma separated displayParts: SymbolDisplayPart[]; - documentation: SymbolDisplayPart[]; - tags: JSDocTagInfo[]; + documentation?: SymbolDisplayPart[]; + tags?: JSDocTagInfo[]; codeActions?: CodeAction[]; source?: SymbolDisplayPart[]; } diff --git a/src/services/utilities.ts b/src/services/utilities.ts index b389b956eac34..54f88646071dc 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -201,16 +201,16 @@ namespace ts { return isCallOrNewExpressionTarget(node, SyntaxKind.NewExpression); } - function isCallOrNewExpressionTarget(node: Node, kind: SyntaxKind) { + function isCallOrNewExpressionTarget(node: Node, kind: SyntaxKind): boolean { const target = climbPastPropertyAccess(node); - return target && target.parent && target.parent.kind === kind && (target.parent).expression === target; + return !!target && !!target.parent && target.parent.kind === kind && (target.parent).expression === target; } export function climbPastPropertyAccess(node: Node) { return isRightSideOfPropertyAccess(node) ? node.parent : node; } - export function getTargetLabel(referenceNode: Node, labelName: string): Identifier { + export function getTargetLabel(referenceNode: Node, labelName: string): Identifier | undefined { while (referenceNode) { if (referenceNode.kind === SyntaxKind.LabeledStatement && (referenceNode).label.escapedText === labelName) { return (referenceNode).label; @@ -267,6 +267,8 @@ namespace ts { return true; case SyntaxKind.LiteralType: return node.parent.parent.kind === SyntaxKind.IndexedAccessType; + default: + return false; } } @@ -275,7 +277,7 @@ namespace ts { getExternalModuleImportEqualsDeclarationExpression(node.parent.parent) === node; } - export function getContainerNode(node: Node): Declaration { + export function getContainerNode(node: Node): Declaration | undefined { if (isJSDocTypeAlias(node)) { // This doesn't just apply to the node immediately under the comment, but to everything in its parent's scope. // node.parent = the JSDoc comment, node.parent.parent = the node having the comment. @@ -447,8 +449,8 @@ namespace ts { return position < candidate.end || !isCompletedNode(candidate, sourceFile); } - function isCompletedNode(n: Node, sourceFile: SourceFile): boolean { - if (nodeIsMissing(n)) { + function isCompletedNode(n: Node | undefined, sourceFile: SourceFile): boolean { + if (n === undefined || nodeIsMissing(n)) { return false; } @@ -504,7 +506,7 @@ namespace ts { return hasChildOfKind(n, SyntaxKind.CloseParenToken, sourceFile); case SyntaxKind.ModuleDeclaration: - return (n).body && isCompletedNode((n).body, sourceFile); + return !!(n).body && isCompletedNode((n).body, sourceFile); case SyntaxKind.IfStatement: if ((n).elseStatement) { @@ -588,18 +590,18 @@ namespace ts { function nodeEndsWith(n: Node, expectedLastToken: SyntaxKind, sourceFile: SourceFile): boolean { const children = n.getChildren(sourceFile); if (children.length) { - const last = lastOrUndefined(children); - if (last.kind === expectedLastToken) { + const lastChild = last(children); + if (lastChild.kind === expectedLastToken) { return true; } - else if (last.kind === SyntaxKind.SemicolonToken && children.length !== 1) { + else if (lastChild.kind === SyntaxKind.SemicolonToken && children.length !== 1) { return children[children.length - 2].kind === expectedLastToken; } } return false; } - export function findListItemInfo(node: Node): ListItemInfo { + export function findListItemInfo(node: Node): ListItemInfo | undefined { const list = findContainingList(node); // It is possible at this point for syntaxList to be undefined, either if @@ -655,12 +657,12 @@ namespace ts { } /** Returns a token if position is in [start-of-leading-trivia, end) */ - export function getTokenAtPosition(sourceFile: SourceFile, position: number, includeJsDocComment: boolean, includeEndPosition?: boolean): Node { + export function getTokenAtPosition(sourceFile: SourceFile, position: number, includeJsDocComment: boolean, includeEndPosition = false): Node { return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ true, /*includePrecedingTokenAtEndPosition*/ undefined, includeEndPosition, includeJsDocComment); } /** Get the token whose text contains the position */ - function getTokenAtPositionWorker(sourceFile: SourceFile, position: number, allowPositionInLeadingTrivia: boolean, includePrecedingTokenAtEndPosition: (n: Node) => boolean, includeEndPosition: boolean, includeJsDocComment: boolean): Node { + function getTokenAtPositionWorker(sourceFile: SourceFile, position: number, allowPositionInLeadingTrivia: boolean, includePrecedingTokenAtEndPosition: ((n: Node) => boolean) | undefined, includeEndPosition: boolean, includeJsDocComment: boolean): Node { let current: Node = sourceFile; outer: while (true) { if (isToken(current)) { @@ -705,7 +707,7 @@ namespace ts { * foo |bar -> will return foo * */ - export function findTokenOnLeftOfPosition(file: SourceFile, position: number): Node { + export function findTokenOnLeftOfPosition(file: SourceFile, position: number): Node | undefined { // Ideally, getTokenAtPosition should return a token. However, it is currently // broken, so we do a check to make sure the result was indeed a token. const tokenAtPosition = getTokenAtPosition(file, position, /*includeJsDocComment*/ false); @@ -716,10 +718,10 @@ namespace ts { return findPrecedingToken(position, file); } - export function findNextToken(previousToken: Node, parent: Node, sourceFile: SourceFile): Node { + export function findNextToken(previousToken: Node, parent: Node, sourceFile: SourceFile): Node | undefined { return find(parent); - function find(n: Node): Node { + function find(n: Node): Node | undefined { if (isToken(n) && n.pos === previousToken.end) { // this is token that starts at the end of previous token - return it return n; @@ -899,10 +901,11 @@ namespace ts { const tokenKind = token.kind; let remainingMatchingTokens = 0; while (true) { - token = findPrecedingToken(token.getFullStart(), sourceFile); - if (!token) { + const preceding = findPrecedingToken(token.getFullStart(), sourceFile); + if (!preceding) { return undefined; } + token = preceding; if (token.kind === matchingTokenKind) { if (remainingMatchingTokens === 0) { @@ -917,7 +920,8 @@ namespace ts { } } - export function isPossiblyTypeArgumentPosition(token: Node, sourceFile: SourceFile) { + export function isPossiblyTypeArgumentPosition(tokenIn: Node, sourceFile: SourceFile): boolean { + let token: Node | undefined = tokenIn; // This function determines if the node could be type argument position // Since during editing, when type argument list is not complete, // the tree could be of any shape depending on the tokens parsed before current node, @@ -929,7 +933,8 @@ namespace ts { case SyntaxKind.LessThanToken: // Found the beginning of the generic argument expression token = findPrecedingToken(token.getFullStart(), sourceFile); - const tokenIsIdentifier = token && isIdentifier(token); + if (!token) return false; + const tokenIsIdentifier = isIdentifier(token); if (!remainingLessThanTokens || !tokenIsIdentifier) { return tokenIsIdentifier; } @@ -1052,7 +1057,7 @@ namespace ts { return result.length > 0 ? result.join(",") : ScriptElementKindModifier.none; } - export function getTypeArgumentOrTypeParameterList(node: Node): NodeArray { + export function getTypeArgumentOrTypeParameterList(node: Node): NodeArray | undefined { if (node.kind === SyntaxKind.TypeReference || node.kind === SyntaxKind.CallExpression) { return (node).typeArguments; } @@ -1215,7 +1220,7 @@ namespace ts { } export function skipConstraint(type: Type): Type { - return type.isTypeParameter() ? type.getConstraint() : type; + return type.isTypeParameter() ? type.getConstraint()! : type; // TODO: GH#18217 } export function getNameFromPropertyName(name: PropertyName): string | undefined { @@ -1229,7 +1234,7 @@ namespace ts { return program.getSourceFiles().some(s => !s.isDeclarationFile && !program.isSourceFileFromExternalLibrary(s) && !!s.externalModuleIndicator); } export function compilerOptionsIndicateEs6Modules(compilerOptions: CompilerOptions): boolean { - return !!compilerOptions.module || compilerOptions.target >= ScriptTarget.ES2015 || !!compilerOptions.noEmit; + return !!compilerOptions.module || compilerOptions.target! >= ScriptTarget.ES2015 || !!compilerOptions.noEmit; } export function hostUsesCaseSensitiveFileNames(host: LanguageServiceHost): boolean { @@ -1412,15 +1417,15 @@ namespace ts { } export function keywordPart(kind: SyntaxKind) { - return displayPart(tokenToString(kind), SymbolDisplayPartKind.keyword); + return displayPart(tokenToString(kind)!, SymbolDisplayPartKind.keyword); } export function punctuationPart(kind: SyntaxKind) { - return displayPart(tokenToString(kind), SymbolDisplayPartKind.punctuation); + return displayPart(tokenToString(kind)!, SymbolDisplayPartKind.punctuation); } export function operatorPart(kind: SyntaxKind) { - return displayPart(tokenToString(kind), SymbolDisplayPartKind.operator); + return displayPart(tokenToString(kind)!, SymbolDisplayPartKind.operator); } export function textOrKeywordPart(text: string) { @@ -1459,19 +1464,19 @@ namespace ts { } } - export function typeToDisplayParts(typechecker: TypeChecker, type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): SymbolDisplayPart[] { + export function typeToDisplayParts(typechecker: TypeChecker, type: Type, enclosingDeclaration?: Node, flags: TypeFormatFlags = TypeFormatFlags.None): SymbolDisplayPart[] { return mapToDisplayParts(writer => { typechecker.writeType(type, enclosingDeclaration, flags | TypeFormatFlags.MultilineObjectLiterals, writer); }); } - export function symbolToDisplayParts(typeChecker: TypeChecker, symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): SymbolDisplayPart[] { + export function symbolToDisplayParts(typeChecker: TypeChecker, symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags: SymbolFormatFlags = SymbolFormatFlags.None): SymbolDisplayPart[] { return mapToDisplayParts(writer => { typeChecker.writeSymbol(symbol, enclosingDeclaration, meaning, flags | SymbolFormatFlags.UseAliasDefinedOutsideCurrentScope, writer); }); } - export function signatureToDisplayParts(typechecker: TypeChecker, signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags): SymbolDisplayPart[] { + export function signatureToDisplayParts(typechecker: TypeChecker, signature: Signature, enclosingDeclaration?: Node, flags: TypeFormatFlags = TypeFormatFlags.None): SymbolDisplayPart[] { flags |= TypeFormatFlags.UseAliasDefinedOutsideCurrentScope | TypeFormatFlags.MultilineObjectLiterals | TypeFormatFlags.WriteTypeArgumentsOfSignature | TypeFormatFlags.OmitParameterModifiers; return mapToDisplayParts(writer => { typechecker.writeSignature(signature, enclosingDeclaration, flags, /*signatureKind*/ undefined, writer); @@ -1479,7 +1484,7 @@ namespace ts { } export function isImportOrExportSpecifierName(location: Node): location is Identifier { - return location.parent && + return !!location.parent && (location.parent.kind === SyntaxKind.ImportSpecifier || location.parent.kind === SyntaxKind.ExportSpecifier) && (location.parent).propertyName === location; } @@ -1503,7 +1508,7 @@ namespace ts { export function scriptKindIs(fileName: string, host: LanguageServiceHost, ...scriptKinds: ScriptKind[]): boolean { const scriptKind = getScriptKind(fileName, host); - return forEach(scriptKinds, k => k === scriptKind); + return some(scriptKinds, k => k === scriptKind); } export function getScriptKind(fileName: string, host?: LanguageServiceHost): ScriptKind { @@ -1529,13 +1534,13 @@ namespace ts { * WARNING: This is an expensive operation and is only intended to be used in refactorings * and code fixes (because those are triggered by explicit user actions). */ - export function getSynthesizedDeepClone(node: T | undefined, includeTrivia = true): T | undefined { - const clone = node && getSynthesizedDeepCloneWorker(node); + export function getSynthesizedDeepClone(node: T, includeTrivia = true): T { + const clone = node && getSynthesizedDeepCloneWorker(node as NonNullable); if (clone && !includeTrivia) suppressLeadingAndTrailingTrivia(clone); return clone; } - function getSynthesizedDeepCloneWorker(node: T): T | undefined { + function getSynthesizedDeepCloneWorker(node: T): T { const visited = visitEachChild(node, getSynthesizedDeepClone, nullTransformationContext); if (visited === node) { // This only happens for leaf nodes - internal nodes always see their children change. @@ -1552,10 +1557,12 @@ namespace ts { // PERF: As an optimization, rather than calling getSynthesizedClone, we'll update // the new node created by visitEachChild with the extra changes getSynthesizedClone // would have made. - visited.parent = undefined; + visited.parent = undefined!; return visited; } + export function getSynthesizedDeepClones(nodes: NodeArray, includeTrivia?: boolean): NodeArray; + export function getSynthesizedDeepClones(nodes: NodeArray | undefined, includeTrivia?: boolean): NodeArray | undefined; export function getSynthesizedDeepClones(nodes: NodeArray | undefined, includeTrivia = true): NodeArray | undefined { return nodes && createNodeArray(nodes.map(n => getSynthesizedDeepClone(n, includeTrivia)), nodes.hasTrailingComma); } @@ -1585,7 +1592,7 @@ namespace ts { addEmitFlagsRecursively(node, EmitFlags.NoTrailingComments, getLastChild); } - function addEmitFlagsRecursively(node: Node, flag: EmitFlags, getChild: (n: Node) => Node) { + function addEmitFlagsRecursively(node: Node, flag: EmitFlags, getChild: (n: Node) => Node | undefined) { addEmitFlags(node, flag); const child = getChild(node); if (child) addEmitFlagsRecursively(child, flag, getChild); diff --git a/src/tsconfig-base.json b/src/tsconfig-base.json index 81905b501025e..92c32e73fcc5b 100644 --- a/src/tsconfig-base.json +++ b/src/tsconfig-base.json @@ -2,6 +2,7 @@ "compilerOptions": { "lib": ["es5"], "noEmitOnError": true, + "strictNullChecks": true, "noImplicitAny": true, "noImplicitThis": true, "noUnusedLocals": true, diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 3b36440877811..3adc0f014b696 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -460,7 +460,7 @@ declare namespace ts { flags: NodeFlags; decorators?: NodeArray; modifiers?: ModifiersArray; - parent?: Node; + parent: Node; } interface JSDocContainer { } @@ -525,12 +525,12 @@ declare namespace ts { } interface Decorator extends Node { kind: SyntaxKind.Decorator; - parent?: NamedDeclaration; + parent: NamedDeclaration; expression: LeftHandSideExpression; } interface TypeParameterDeclaration extends NamedDeclaration { kind: SyntaxKind.TypeParameter; - parent?: DeclarationWithTypeParameters | InferTypeNode; + parent: DeclarationWithTypeParameters | InferTypeNode; name: Identifier; constraint?: TypeNode; default?: TypeNode; @@ -541,7 +541,7 @@ declare namespace ts { name?: PropertyName; typeParameters?: NodeArray; parameters: NodeArray; - type: TypeNode | undefined; + type?: TypeNode; } type SignatureDeclaration = CallSignatureDeclaration | ConstructSignatureDeclaration | MethodSignature | IndexSignatureDeclaration | FunctionTypeNode | ConstructorTypeNode | JSDocFunctionType | FunctionDeclaration | MethodDeclaration | ConstructorDeclaration | AccessorDeclaration | FunctionExpression | ArrowFunction; interface CallSignatureDeclaration extends SignatureDeclarationBase, TypeElement { @@ -553,7 +553,7 @@ declare namespace ts { type BindingName = Identifier | BindingPattern; interface VariableDeclaration extends NamedDeclaration { kind: SyntaxKind.VariableDeclaration; - parent?: VariableDeclarationList | CatchClause; + parent: VariableDeclarationList | CatchClause; name: BindingName; exclamationToken?: ExclamationToken; type?: TypeNode; @@ -561,12 +561,12 @@ declare namespace ts { } interface VariableDeclarationList extends Node { kind: SyntaxKind.VariableDeclarationList; - parent?: VariableStatement | ForStatement | ForOfStatement | ForInStatement; + parent: VariableStatement | ForStatement | ForOfStatement | ForInStatement; declarations: NodeArray; } interface ParameterDeclaration extends NamedDeclaration, JSDocContainer { kind: SyntaxKind.Parameter; - parent?: SignatureDeclaration; + parent: SignatureDeclaration; dotDotDotToken?: DotDotDotToken; name: BindingName; questionToken?: QuestionToken; @@ -575,7 +575,7 @@ declare namespace ts { } interface BindingElement extends NamedDeclaration { kind: SyntaxKind.BindingElement; - parent?: BindingPattern; + parent: BindingPattern; propertyName?: PropertyName; dotDotDotToken?: DotDotDotToken; name: BindingName; @@ -628,12 +628,12 @@ declare namespace ts { } interface ObjectBindingPattern extends Node { kind: SyntaxKind.ObjectBindingPattern; - parent?: VariableDeclaration | ParameterDeclaration | BindingElement; + parent: VariableDeclaration | ParameterDeclaration | BindingElement; elements: NodeArray; } interface ArrayBindingPattern extends Node { kind: SyntaxKind.ArrayBindingPattern; - parent?: VariableDeclaration | ParameterDeclaration | BindingElement; + parent: VariableDeclaration | ParameterDeclaration | BindingElement; elements: NodeArray; } type BindingPattern = ObjectBindingPattern | ArrayBindingPattern; @@ -662,41 +662,41 @@ declare namespace ts { } interface MethodSignature extends SignatureDeclarationBase, TypeElement { kind: SyntaxKind.MethodSignature; - parent?: ObjectTypeDeclaration; + parent: ObjectTypeDeclaration; name: PropertyName; } interface MethodDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer { kind: SyntaxKind.MethodDeclaration; - parent?: ClassLikeDeclaration | ObjectLiteralExpression; + parent: ClassLikeDeclaration | ObjectLiteralExpression; name: PropertyName; body?: FunctionBody; } interface ConstructorDeclaration extends FunctionLikeDeclarationBase, ClassElement, JSDocContainer { kind: SyntaxKind.Constructor; - parent?: ClassLikeDeclaration; + parent: ClassLikeDeclaration; body?: FunctionBody; } /** For when we encounter a semicolon in a class declaration. ES6 allows these as class elements. */ interface SemicolonClassElement extends ClassElement { kind: SyntaxKind.SemicolonClassElement; - parent?: ClassLikeDeclaration; + parent: ClassLikeDeclaration; } interface GetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer { kind: SyntaxKind.GetAccessor; - parent?: ClassLikeDeclaration | ObjectLiteralExpression; + parent: ClassLikeDeclaration | ObjectLiteralExpression; name: PropertyName; body?: FunctionBody; } interface SetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer { kind: SyntaxKind.SetAccessor; - parent?: ClassLikeDeclaration | ObjectLiteralExpression; + parent: ClassLikeDeclaration | ObjectLiteralExpression; name: PropertyName; body?: FunctionBody; } type AccessorDeclaration = GetAccessorDeclaration | SetAccessorDeclaration; interface IndexSignatureDeclaration extends SignatureDeclarationBase, ClassElement, TypeElement { kind: SyntaxKind.IndexSignature; - parent?: ObjectTypeDeclaration; + parent: ObjectTypeDeclaration; } interface TypeNode extends Node { _typeNodeBrand: any; @@ -730,7 +730,7 @@ declare namespace ts { } interface TypePredicateNode extends TypeNode { kind: SyntaxKind.TypePredicate; - parent?: SignatureDeclaration; + parent: SignatureDeclaration; parameterName: Identifier | ThisTypeNode; type: TypeNode; } @@ -959,15 +959,15 @@ declare namespace ts { } interface TemplateHead extends LiteralLikeNode { kind: SyntaxKind.TemplateHead; - parent?: TemplateExpression; + parent: TemplateExpression; } interface TemplateMiddle extends LiteralLikeNode { kind: SyntaxKind.TemplateMiddle; - parent?: TemplateSpan; + parent: TemplateSpan; } interface TemplateTail extends LiteralLikeNode { kind: SyntaxKind.TemplateTail; - parent?: TemplateSpan; + parent: TemplateSpan; } type TemplateLiteral = TemplateExpression | NoSubstitutionTemplateLiteral; interface TemplateExpression extends PrimaryExpression { @@ -977,7 +977,7 @@ declare namespace ts { } interface TemplateSpan extends Node { kind: SyntaxKind.TemplateSpan; - parent?: TemplateExpression; + parent: TemplateExpression; expression: Expression; literal: TemplateMiddle | TemplateTail; } @@ -991,7 +991,7 @@ declare namespace ts { } interface SpreadElement extends Expression { kind: SyntaxKind.SpreadElement; - parent?: ArrayLiteralExpression | CallExpression | NewExpression; + parent: ArrayLiteralExpression | CallExpression | NewExpression; expression: Expression; } /** @@ -1044,7 +1044,7 @@ declare namespace ts { } interface ExpressionWithTypeArguments extends NodeWithTypeArguments { kind: SyntaxKind.ExpressionWithTypeArguments; - parent?: HeritageClause; + parent: HeritageClause; expression: LeftHandSideExpression; } interface NewExpression extends PrimaryExpression, Declaration { @@ -1090,11 +1090,11 @@ declare namespace ts { type JsxAttributeLike = JsxAttribute | JsxSpreadAttribute; type JsxTagNameExpression = PrimaryExpression | PropertyAccessExpression; interface JsxAttributes extends ObjectLiteralExpressionBase { - parent?: JsxOpeningLikeElement; + parent: JsxOpeningLikeElement; } interface JsxOpeningElement extends Expression { kind: SyntaxKind.JsxOpeningElement; - parent?: JsxElement; + parent: JsxElement; tagName: JsxTagNameExpression; typeArguments?: NodeArray; attributes: JsxAttributes; @@ -1113,38 +1113,38 @@ declare namespace ts { } interface JsxOpeningFragment extends Expression { kind: SyntaxKind.JsxOpeningFragment; - parent?: JsxFragment; + parent: JsxFragment; } interface JsxClosingFragment extends Expression { kind: SyntaxKind.JsxClosingFragment; - parent?: JsxFragment; + parent: JsxFragment; } interface JsxAttribute extends ObjectLiteralElement { kind: SyntaxKind.JsxAttribute; - parent?: JsxAttributes; + parent: JsxAttributes; name: Identifier; initializer?: StringLiteral | JsxExpression; } interface JsxSpreadAttribute extends ObjectLiteralElement { kind: SyntaxKind.JsxSpreadAttribute; - parent?: JsxAttributes; + parent: JsxAttributes; expression: Expression; } interface JsxClosingElement extends Node { kind: SyntaxKind.JsxClosingElement; - parent?: JsxElement; + parent: JsxElement; tagName: JsxTagNameExpression; } interface JsxExpression extends Expression { kind: SyntaxKind.JsxExpression; - parent?: JsxElement | JsxAttributeLike; + parent: JsxElement | JsxAttributeLike; dotDotDotToken?: Token; expression?: Expression; } interface JsxText extends Node { kind: SyntaxKind.JsxText; containsOnlyWhiteSpaces: boolean; - parent?: JsxElement; + parent: JsxElement; } type JsxChild = JsxText | JsxExpression | JsxElement | JsxSelfClosingElement | JsxFragment; interface Statement extends Node { @@ -1245,18 +1245,18 @@ declare namespace ts { } interface CaseBlock extends Node { kind: SyntaxKind.CaseBlock; - parent?: SwitchStatement; + parent: SwitchStatement; clauses: NodeArray; } interface CaseClause extends Node { kind: SyntaxKind.CaseClause; - parent?: CaseBlock; + parent: CaseBlock; expression: Expression; statements: NodeArray; } interface DefaultClause extends Node { kind: SyntaxKind.DefaultClause; - parent?: CaseBlock; + parent: CaseBlock; statements: NodeArray; } type CaseOrDefaultClause = CaseClause | DefaultClause; @@ -1267,7 +1267,7 @@ declare namespace ts { } interface ThrowStatement extends Statement { kind: SyntaxKind.ThrowStatement; - expression: Expression; + expression?: Expression; } interface TryStatement extends Statement { kind: SyntaxKind.TryStatement; @@ -1277,7 +1277,7 @@ declare namespace ts { } interface CatchClause extends Node { kind: SyntaxKind.CatchClause; - parent?: TryStatement; + parent: TryStatement; variableDeclaration?: VariableDeclaration; block: Block; } @@ -1317,7 +1317,7 @@ declare namespace ts { } interface HeritageClause extends Node { kind: SyntaxKind.HeritageClause; - parent?: InterfaceDeclaration | ClassLikeDeclaration; + parent: InterfaceDeclaration | ClassLikeDeclaration; token: SyntaxKind.ExtendsKeyword | SyntaxKind.ImplementsKeyword; types: NodeArray; } @@ -1329,7 +1329,7 @@ declare namespace ts { } interface EnumMember extends NamedDeclaration, JSDocContainer { kind: SyntaxKind.EnumMember; - parent?: EnumDeclaration; + parent: EnumDeclaration; name: PropertyName; initializer?: Expression; } @@ -1342,7 +1342,7 @@ declare namespace ts { type ModuleBody = NamespaceBody | JSDocNamespaceBody; interface ModuleDeclaration extends DeclarationStatement, JSDocContainer { kind: SyntaxKind.ModuleDeclaration; - parent?: ModuleBody | SourceFile; + parent: ModuleBody | SourceFile; name: ModuleName; body?: ModuleBody | JSDocNamespaceDeclaration; } @@ -1354,11 +1354,11 @@ declare namespace ts { type JSDocNamespaceBody = Identifier | JSDocNamespaceDeclaration; interface JSDocNamespaceDeclaration extends ModuleDeclaration { name: Identifier; - body: JSDocNamespaceBody; + body?: JSDocNamespaceBody; } interface ModuleBlock extends Node, Statement { kind: SyntaxKind.ModuleBlock; - parent?: ModuleDeclaration; + parent: ModuleDeclaration; statements: NodeArray; } type ModuleReference = EntityName | ExternalModuleReference; @@ -1369,18 +1369,18 @@ declare namespace ts { */ interface ImportEqualsDeclaration extends DeclarationStatement, JSDocContainer { kind: SyntaxKind.ImportEqualsDeclaration; - parent?: SourceFile | ModuleBlock; + parent: SourceFile | ModuleBlock; name: Identifier; moduleReference: ModuleReference; } interface ExternalModuleReference extends Node { kind: SyntaxKind.ExternalModuleReference; - parent?: ImportEqualsDeclaration; - expression?: Expression; + parent: ImportEqualsDeclaration; + expression: Expression; } interface ImportDeclaration extends Statement { kind: SyntaxKind.ImportDeclaration; - parent?: SourceFile | ModuleBlock; + parent: SourceFile | ModuleBlock; importClause?: ImportClause; /** If this is not a StringLiteral it will be a grammar error. */ moduleSpecifier: Expression; @@ -1388,13 +1388,13 @@ declare namespace ts { type NamedImportBindings = NamespaceImport | NamedImports; interface ImportClause extends NamedDeclaration { kind: SyntaxKind.ImportClause; - parent?: ImportDeclaration; + parent: ImportDeclaration; name?: Identifier; namedBindings?: NamedImportBindings; } interface NamespaceImport extends NamedDeclaration { kind: SyntaxKind.NamespaceImport; - parent?: ImportClause; + parent: ImportClause; name: Identifier; } interface NamespaceExportDeclaration extends DeclarationStatement { @@ -1403,7 +1403,7 @@ declare namespace ts { } interface ExportDeclaration extends DeclarationStatement { kind: SyntaxKind.ExportDeclaration; - parent?: SourceFile | ModuleBlock; + parent: SourceFile | ModuleBlock; /** Will not be assigned in the case of `export * from "foo";` */ exportClause?: NamedExports; /** If this is not a StringLiteral it will be a grammar error. */ @@ -1411,24 +1411,24 @@ declare namespace ts { } interface NamedImports extends Node { kind: SyntaxKind.NamedImports; - parent?: ImportClause; + parent: ImportClause; elements: NodeArray; } interface NamedExports extends Node { kind: SyntaxKind.NamedExports; - parent?: ExportDeclaration; + parent: ExportDeclaration; elements: NodeArray; } type NamedImportsOrExports = NamedImports | NamedExports; interface ImportSpecifier extends NamedDeclaration { kind: SyntaxKind.ImportSpecifier; - parent?: NamedImports; + parent: NamedImports; propertyName?: Identifier; name: Identifier; } interface ExportSpecifier extends NamedDeclaration { kind: SyntaxKind.ExportSpecifier; - parent?: NamedExports; + parent: NamedExports; propertyName?: Identifier; name: Identifier; } @@ -1439,7 +1439,7 @@ declare namespace ts { */ interface ExportAssignment extends DeclarationStatement { kind: SyntaxKind.ExportAssignment; - parent?: SourceFile; + parent: SourceFile; isExportEquals?: boolean; expression: Expression; } @@ -1494,15 +1494,15 @@ declare namespace ts { type JSDocTypeReferencingNode = JSDocVariadicType | JSDocOptionalType | JSDocNullableType | JSDocNonNullableType; interface JSDoc extends Node { kind: SyntaxKind.JSDocComment; - parent?: HasJSDoc; - tags: NodeArray | undefined; - comment: string | undefined; + parent: HasJSDoc; + tags?: NodeArray; + comment?: string; } interface JSDocTag extends Node { parent: JSDoc | JSDocTypeLiteral; atToken: AtToken; tagName: Identifier; - comment: string | undefined; + comment?: string; } interface JSDocUnknownTag extends JSDocTag { kind: SyntaxKind.JSDocTag; @@ -1526,11 +1526,11 @@ declare namespace ts { } interface JSDocReturnTag extends JSDocTag { kind: SyntaxKind.JSDocReturnTag; - typeExpression: JSDocTypeExpression; + typeExpression?: JSDocTypeExpression; } interface JSDocTypeTag extends JSDocTag { kind: SyntaxKind.JSDocTypeTag; - typeExpression: JSDocTypeExpression; + typeExpression?: JSDocTypeExpression; } interface JSDocTypedefTag extends JSDocTag, NamedDeclaration { parent: JSDoc; @@ -1608,7 +1608,7 @@ declare namespace ts { container?: FunctionExpression | ArrowFunction | MethodDeclaration; } interface FlowLabel extends FlowNodeBase { - antecedents: FlowNode[]; + antecedents: FlowNode[] | undefined; } interface FlowAssignment extends FlowNodeBase { node: Expression | VariableDeclaration | BindingElement; @@ -1635,7 +1635,7 @@ declare namespace ts { } interface AmdDependency { path: string; - name: string; + name?: string; } interface SourceFile extends Declaration { kind: SyntaxKind.SourceFile; @@ -1644,7 +1644,7 @@ declare namespace ts { fileName: string; text: string; amdDependencies: ReadonlyArray; - moduleName: string; + moduleName?: string; referencedFiles: ReadonlyArray; typeReferenceDirectives: ReadonlyArray; languageVariant: LanguageVariant; @@ -1704,7 +1704,7 @@ declare namespace ts { fileExists(path: string): boolean; readFile(path: string): string | undefined; } - type WriteFileCallback = (fileName: string, data: string, writeByteOrderMark: boolean, onError: ((message: string) => void) | undefined, sourceFiles: ReadonlyArray) => void; + type WriteFileCallback = (fileName: string, data: string, writeByteOrderMark: boolean, onError: ((message: string) => void) | undefined, sourceFiles?: ReadonlyArray) => void; class OperationCanceledException { } interface CancellationToken { @@ -1794,7 +1794,7 @@ declare namespace ts { emitSkipped: boolean; /** Contains declaration emit diagnostics */ diagnostics: ReadonlyArray; - emittedFiles: string[]; + emittedFiles?: string[]; } interface TypeChecker { getTypeOfSymbolAtLocation(symbol: Symbol, node: Node): Type; @@ -1811,7 +1811,7 @@ declare namespace ts { getNullableType(type: Type, flags: TypeFlags): Type; getNonNullableType(type: Type): Type; /** Note that the resulting nodes cannot be checked. */ - typeToTypeNode(type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): TypeNode; + typeToTypeNode(type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): TypeNode | undefined; /** Note that the resulting nodes cannot be checked. */ signatureToSignatureDeclaration(signature: Signature, kind: SyntaxKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): (SignatureDeclaration & { typeArguments?: NodeArray; @@ -1847,7 +1847,7 @@ declare namespace ts { */ getExportSymbolOfSymbol(symbol: Symbol): Symbol; getPropertySymbolOfDestructuringAssignment(location: Identifier): Symbol | undefined; - getTypeAtLocation(node: Node): Type; + getTypeAtLocation(node: Node): Type | undefined; getTypeFromTypeNode(node: TypeNode): Type; signatureToString(signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): string; typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string; @@ -1864,9 +1864,10 @@ declare namespace ts { getContextualType(node: Expression): Type | undefined; /** * returns unknownSignature in the case of an error. + * returns undefined if the node is not valid. * @param argumentCount Apparent number of arguments, passed in case of a possibly incomplete call. This should come from an ArgumentListInfo. See `signatureHelp.ts`. */ - getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[], argumentCount?: number): Signature; + getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[], argumentCount?: number): Signature | undefined; getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature | undefined; isImplementationOfOverload(node: SignatureDeclaration): boolean | undefined; isUndefinedSymbol(symbol: Symbol): boolean; @@ -2070,8 +2071,8 @@ declare namespace ts { interface Symbol { flags: SymbolFlags; escapedName: __String; - declarations?: Declaration[]; - valueDeclaration?: Declaration; + declarations: Declaration[]; + valueDeclaration: Declaration; members?: SymbolTable; exports?: SymbolTable; globalExports?: SymbolTable; @@ -2173,15 +2174,15 @@ declare namespace ts { type DestructuringPattern = BindingPattern | ObjectLiteralExpression | ArrayLiteralExpression; interface Type { flags: TypeFlags; - symbol?: Symbol; + symbol: Symbol; pattern?: DestructuringPattern; aliasSymbol?: Symbol; aliasTypeArguments?: Type[]; } interface LiteralType extends Type { value: string | number; - freshType?: LiteralType; - regularType?: LiteralType; + freshType: LiteralType; + regularType: LiteralType; } interface UniqueESSymbolType extends Type { symbol: Symbol; @@ -2216,18 +2217,18 @@ declare namespace ts { } /** Class and interface types (ObjectFlags.Class and ObjectFlags.Interface). */ interface InterfaceType extends ObjectType { - typeParameters: TypeParameter[]; - outerTypeParameters: TypeParameter[]; - localTypeParameters: TypeParameter[]; - thisType: TypeParameter; + typeParameters: TypeParameter[] | undefined; + outerTypeParameters: TypeParameter[] | undefined; + localTypeParameters: TypeParameter[] | undefined; + thisType: TypeParameter | undefined; } type BaseType = ObjectType | IntersectionType; interface InterfaceTypeWithDeclaredMembers extends InterfaceType { declaredProperties: Symbol[]; declaredCallSignatures: Signature[]; declaredConstructSignatures: Signature[]; - declaredStringIndexInfo: IndexInfo; - declaredNumberIndexInfo: IndexInfo; + declaredStringIndexInfo?: IndexInfo; + declaredNumberIndexInfo?: IndexInfo; } /** * Type references (ObjectFlags.Reference). When a class or interface has type parameters or @@ -2278,11 +2279,11 @@ declare namespace ts { trueType: Type; falseType: Type; isDistributive: boolean; - inferTypeParameters: TypeParameter[]; + inferTypeParameters?: TypeParameter[]; outerTypeParameters?: TypeParameter[]; instantiations?: Map; - aliasSymbol: Symbol; - aliasTypeArguments: Type[]; + aliasSymbol?: Symbol; + aliasTypeArguments?: Type[]; } interface ConditionalType extends InstantiableType { root: ConditionalRoot; @@ -2630,7 +2631,7 @@ declare namespace ts { packageId?: PackageId; } interface ResolvedTypeReferenceDirectiveWithFailedLookupLocations { - readonly resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective; + readonly resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective | undefined; readonly failedLookupLocations: ReadonlyArray; } interface CompilerHost extends ModuleResolutionHost { @@ -2650,8 +2651,8 @@ declare namespace ts { /** * This method is a companion for 'resolveModuleNames' and is used to resolve 'types' references to actual type declaration files */ - resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): (ResolvedTypeReferenceDirective | undefined)[]; - getEnvironmentVariable?(name: string): string; + resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[]; + getEnvironmentVariable?(name: string): string | undefined; createHash?(data: string): string; } interface SourceMapRange extends TextRange { @@ -2663,6 +2664,7 @@ declare namespace ts { skipTrivia?: (pos: number) => number; } enum EmitFlags { + None = 0, SingleLine = 1, AdviseOnEmitNode = 2, NoSubstitution = 4, @@ -2716,7 +2718,7 @@ declare namespace ts { /** Resumes a suspended lexical environment, usually before visiting a function body. */ resumeLexicalEnvironment(): void; /** Ends a lexical environment, returning any declarations. */ - endLexicalEnvironment(): Statement[]; + endLexicalEnvironment(): Statement[] | undefined; /** Hoists a function declaration to the containing scope. */ hoistFunctionDeclaration(node: FunctionDeclaration): void; /** Hoists a variable declaration to the containing scope. */ @@ -2847,7 +2849,7 @@ declare namespace ts { * }); * ``` */ - onEmitNode?(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void; + onEmitNode?(hint: EmitHint, node: Node | undefined, emitCallback: (hint: EmitHint, node: Node | undefined) => void): void; /** * A hook used by the Printer to perform just-in-time substitution of a node. This is * primarily used by node transformations that need to substitute one node for another, @@ -3020,7 +3022,7 @@ declare namespace ts { interface FileWatcher { close(): void; } - function getNodeMajorVersion(): number; + function getNodeMajorVersion(): number | undefined; let sys: System; } declare namespace ts { @@ -3047,8 +3049,8 @@ declare namespace ts { scanJSDocToken(): JsDocSyntaxKind; scan(): SyntaxKind; getText(): string; - setText(text: string, start?: number, length?: number): void; - setOnError(onError: ErrorCallback): void; + setText(text: string | undefined, start?: number, length?: number): void; + setOnError(onError: ErrorCallback | undefined): void; setScriptTarget(scriptTarget: ScriptTarget): void; setLanguageVariant(variant: LanguageVariant): void; setTextPos(textPos: number): void; @@ -3068,15 +3070,15 @@ declare namespace ts { function forEachLeadingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state: T): U | undefined; function forEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean) => U): U | undefined; function forEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state: T): U | undefined; - function reduceEachLeadingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T, memo: U) => U, state: T, initial: U): U; - function reduceEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T, memo: U) => U, state: T, initial: U): U; + function reduceEachLeadingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T, memo: U) => U, state: T, initial: U): U | undefined; + function reduceEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T, memo: U) => U, state: T, initial: U): U | undefined; function getLeadingCommentRanges(text: string, pos: number): CommentRange[] | undefined; function getTrailingCommentRanges(text: string, pos: number): CommentRange[] | undefined; /** Optionally, get the shebang */ function getShebang(text: string): string | undefined; - function isIdentifierStart(ch: number, languageVersion: ScriptTarget): boolean; - function isIdentifierPart(ch: number, languageVersion: ScriptTarget): boolean; - function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean, languageVariant?: LanguageVariant, text?: string, onError?: ErrorCallback, start?: number, length?: number): Scanner; + function isIdentifierStart(ch: number, languageVersion: ScriptTarget | undefined): boolean; + function isIdentifierPart(ch: number, languageVersion: ScriptTarget | undefined): boolean; + function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean, languageVariant?: LanguageVariant, textInitial?: string, onError?: ErrorCallback, start?: number, length?: number): Scanner; } declare namespace ts { function getDefaultLibFileName(options: CompilerOptions): string; @@ -3085,12 +3087,12 @@ declare namespace ts { function textSpanContainsPosition(span: TextSpan, position: number): boolean; function textSpanContainsTextSpan(span: TextSpan, other: TextSpan): boolean; function textSpanOverlapsWith(span: TextSpan, other: TextSpan): boolean; - function textSpanOverlap(span1: TextSpan, span2: TextSpan): TextSpan; + function textSpanOverlap(span1: TextSpan, span2: TextSpan): TextSpan | undefined; function textSpanIntersectsWithTextSpan(span: TextSpan, other: TextSpan): boolean; function textSpanIntersectsWith(span: TextSpan, start: number, length: number): boolean; function decodedTextSpanIntersectsWith(start1: number, length1: number, start2: number, length2: number): boolean; function textSpanIntersectsWithPosition(span: TextSpan, position: number): boolean; - function textSpanIntersection(span1: TextSpan, span2: TextSpan): TextSpan; + function textSpanIntersection(span1: TextSpan, span2: TextSpan): TextSpan | undefined; function createTextSpan(start: number, length: number): TextSpan; function createTextSpanFromBounds(start: number, end: number): TextSpan; function textChangeRangeNewSpan(range: TextChangeRange): TextSpan; @@ -3106,7 +3108,7 @@ declare namespace ts { * Vn. */ function collapseTextChangeRangesAcrossMultipleVersions(changes: ReadonlyArray): TextChangeRange; - function getTypeParameterOwner(d: Declaration): Declaration; + function getTypeParameterOwner(d: Declaration): Declaration | undefined; type ParameterPropertyDeclaration = ParameterDeclaration & { parent: ConstructorDeclaration; name: Identifier; @@ -3128,6 +3130,8 @@ declare namespace ts { }, errors?: Push): void; function getOriginalNode(node: Node): Node; function getOriginalNode(node: Node, nodeTest: (node: Node) => node is T): T; + function getOriginalNode(node: Node | undefined): Node | undefined; + function getOriginalNode(node: Node | undefined, nodeTest: (node: Node | undefined) => node is T): T | undefined; /** * Gets a value indicating whether a node originated in the parse tree. * @@ -3148,7 +3152,7 @@ declare namespace ts { * @param nodeTest A callback used to ensure the correct type of parse tree node is returned. * @returns The original parse tree node if found; otherwise, undefined. */ - function getParseTreeNode(node: Node, nodeTest?: (node: Node) => node is T): T; + function getParseTreeNode(node: Node | undefined, nodeTest?: (node: Node) => node is T): T | undefined; /** * Remove extra underscore from escaped identifier text content. * @@ -3166,7 +3170,7 @@ declare namespace ts { */ function unescapeIdentifier(id: string): string; function getNameOfJSDocTypedef(declaration: JSDocTypedefTag): Identifier | undefined; - function getNameOfDeclaration(declaration: Declaration | Expression): DeclarationName | undefined; + function getNameOfDeclaration(declaration: Declaration | Expression): DeclarationName; /** * Gets the JSDoc parameter tags for the node if present. * @@ -3448,7 +3452,7 @@ declare namespace ts { */ function forEachChild(node: Node, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined; function createSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, setParentNodes?: boolean, scriptKind?: ScriptKind): SourceFile; - function parseIsolatedEntityName(text: string, languageVersion: ScriptTarget): EntityName; + function parseIsolatedEntityName(text: string, languageVersion: ScriptTarget): EntityName | undefined; /** * Parse json text into SyntaxTree and return node and parse errors if any * @param fileName @@ -3494,7 +3498,7 @@ declare namespace ts { getOrCreateCacheForModuleName(nonRelativeModuleName: string): PerModuleNameCache; } interface PerModuleNameCache { - get(directory: string): ResolvedModuleWithFailedLookupLocations; + get(directory: string): ResolvedModuleWithFailedLookupLocations | undefined; set(directory: string, result: ResolvedModuleWithFailedLookupLocations): void; } function createModuleResolutionCache(currentDirectory: string, getCanonicalFileName: (s: string) => string): ModuleResolutionCache; @@ -3576,7 +3580,7 @@ declare namespace ts { function updateConstructorTypeNode(node: ConstructorTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): ConstructorTypeNode; function createTypeQueryNode(exprName: EntityName): TypeQueryNode; function updateTypeQueryNode(node: TypeQueryNode, exprName: EntityName): TypeQueryNode; - function createTypeLiteralNode(members: ReadonlyArray): TypeLiteralNode; + function createTypeLiteralNode(members: ReadonlyArray | undefined): TypeLiteralNode; function updateTypeLiteralNode(node: TypeLiteralNode, members: NodeArray): TypeLiteralNode; function createArrayTypeNode(elementType: TypeNode): ArrayTypeNode; function updateArrayTypeNode(node: ArrayTypeNode, elementType: TypeNode): ArrayTypeNode; @@ -3615,23 +3619,23 @@ declare namespace ts { function updateArrayLiteral(node: ArrayLiteralExpression, elements: ReadonlyArray): ArrayLiteralExpression; function createObjectLiteral(properties?: ReadonlyArray, multiLine?: boolean): ObjectLiteralExpression; function updateObjectLiteral(node: ObjectLiteralExpression, properties: ReadonlyArray): ObjectLiteralExpression; - function createPropertyAccess(expression: Expression, name: string | Identifier): PropertyAccessExpression; + function createPropertyAccess(expression: Expression, name: string | Identifier | undefined): PropertyAccessExpression; function updatePropertyAccess(node: PropertyAccessExpression, expression: Expression, name: Identifier): PropertyAccessExpression; function createElementAccess(expression: Expression, index: number | Expression): ElementAccessExpression; function updateElementAccess(node: ElementAccessExpression, expression: Expression, argumentExpression: Expression): ElementAccessExpression; - function createCall(expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray): CallExpression; + function createCall(expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray | undefined): CallExpression; function updateCall(node: CallExpression, expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray): CallExpression; function createNew(expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray | undefined): NewExpression; function updateNew(node: NewExpression, expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray | undefined): NewExpression; function createTaggedTemplate(tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; - function createTaggedTemplate(tag: Expression, typeArguments: ReadonlyArray, template: TemplateLiteral): TaggedTemplateExpression; + function createTaggedTemplate(tag: Expression, typeArguments: ReadonlyArray | undefined, template: TemplateLiteral): TaggedTemplateExpression; function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; - function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: ReadonlyArray, template: TemplateLiteral): TaggedTemplateExpression; + function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: ReadonlyArray | undefined, template: TemplateLiteral): TaggedTemplateExpression; function createTypeAssertion(type: TypeNode, expression: Expression): TypeAssertion; function updateTypeAssertion(node: TypeAssertion, type: TypeNode, expression: Expression): TypeAssertion; function createParen(expression: Expression): ParenthesizedExpression; function updateParen(node: ParenthesizedExpression, expression: Expression): ParenthesizedExpression; - function createFunctionExpression(modifiers: ReadonlyArray | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: ReadonlyArray | undefined, parameters: ReadonlyArray, type: TypeNode | undefined, body: Block): FunctionExpression; + function createFunctionExpression(modifiers: ReadonlyArray | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: ReadonlyArray | undefined, parameters: ReadonlyArray | undefined, type: TypeNode | undefined, body: Block): FunctionExpression; function updateFunctionExpression(node: FunctionExpression, modifiers: ReadonlyArray | undefined, asteriskToken: AsteriskToken | undefined, name: Identifier | undefined, typeParameters: ReadonlyArray | undefined, parameters: ReadonlyArray, type: TypeNode | undefined, body: Block): FunctionExpression; function createArrowFunction(modifiers: ReadonlyArray | undefined, typeParameters: ReadonlyArray | undefined, parameters: ReadonlyArray, type: TypeNode | undefined, equalsGreaterThanToken: EqualsGreaterThanToken | undefined, body: ConciseBody): ArrowFunction; function updateArrowFunction(node: ArrowFunction, modifiers: ReadonlyArray | undefined, typeParameters: ReadonlyArray | undefined, parameters: ReadonlyArray, type: TypeNode | undefined, body: ConciseBody): ArrowFunction; @@ -3661,15 +3665,15 @@ declare namespace ts { function createTemplateTail(text: string): TemplateTail; function createNoSubstitutionTemplateLiteral(text: string): NoSubstitutionTemplateLiteral; function createYield(expression?: Expression): YieldExpression; - function createYield(asteriskToken: AsteriskToken, expression: Expression): YieldExpression; + function createYield(asteriskToken: AsteriskToken | undefined, expression: Expression): YieldExpression; function updateYield(node: YieldExpression, asteriskToken: AsteriskToken | undefined, expression: Expression): YieldExpression; function createSpread(expression: Expression): SpreadElement; function updateSpread(node: SpreadElement, expression: Expression): SpreadElement; - function createClassExpression(modifiers: ReadonlyArray | undefined, name: string | Identifier | undefined, typeParameters: ReadonlyArray | undefined, heritageClauses: ReadonlyArray, members: ReadonlyArray): ClassExpression; - function updateClassExpression(node: ClassExpression, modifiers: ReadonlyArray | undefined, name: Identifier | undefined, typeParameters: ReadonlyArray | undefined, heritageClauses: ReadonlyArray, members: ReadonlyArray): ClassExpression; + function createClassExpression(modifiers: ReadonlyArray | undefined, name: string | Identifier | undefined, typeParameters: ReadonlyArray | undefined, heritageClauses: ReadonlyArray | undefined, members: ReadonlyArray): ClassExpression; + function updateClassExpression(node: ClassExpression, modifiers: ReadonlyArray | undefined, name: Identifier | undefined, typeParameters: ReadonlyArray | undefined, heritageClauses: ReadonlyArray | undefined, members: ReadonlyArray): ClassExpression; function createOmittedExpression(): OmittedExpression; - function createExpressionWithTypeArguments(typeArguments: ReadonlyArray, expression: Expression): ExpressionWithTypeArguments; - function updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, typeArguments: ReadonlyArray, expression: Expression): ExpressionWithTypeArguments; + function createExpressionWithTypeArguments(typeArguments: ReadonlyArray | undefined, expression: Expression): ExpressionWithTypeArguments; + function updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, typeArguments: ReadonlyArray | undefined, expression: Expression): ExpressionWithTypeArguments; function createAsExpression(expression: Expression, type: TypeNode): AsExpression; function updateAsExpression(node: AsExpression, expression: Expression, type: TypeNode): AsExpression; function createNonNullExpression(expression: Expression): NonNullExpression; @@ -3696,8 +3700,8 @@ declare namespace ts { function updateFor(node: ForStatement, initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement): ForStatement; function createForIn(initializer: ForInitializer, expression: Expression, statement: Statement): ForInStatement; function updateForIn(node: ForInStatement, initializer: ForInitializer, expression: Expression, statement: Statement): ForInStatement; - function createForOf(awaitModifier: AwaitKeywordToken, initializer: ForInitializer, expression: Expression, statement: Statement): ForOfStatement; - function updateForOf(node: ForOfStatement, awaitModifier: AwaitKeywordToken, initializer: ForInitializer, expression: Expression, statement: Statement): ForOfStatement; + function createForOf(awaitModifier: AwaitKeywordToken | undefined, initializer: ForInitializer, expression: Expression, statement: Statement): ForOfStatement; + function updateForOf(node: ForOfStatement, awaitModifier: AwaitKeywordToken | undefined, initializer: ForInitializer, expression: Expression, statement: Statement): ForOfStatement; function createContinue(label?: string | Identifier): ContinueStatement; function updateContinue(node: ContinueStatement, label: Identifier | undefined): ContinueStatement; function createBreak(label?: string | Identifier): BreakStatement; @@ -3721,8 +3725,8 @@ declare namespace ts { function updateVariableDeclarationList(node: VariableDeclarationList, declarations: ReadonlyArray): VariableDeclarationList; function createFunctionDeclaration(decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: ReadonlyArray | undefined, parameters: ReadonlyArray, type: TypeNode | undefined, body: Block | undefined): FunctionDeclaration; function updateFunctionDeclaration(node: FunctionDeclaration, decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, asteriskToken: AsteriskToken | undefined, name: Identifier | undefined, typeParameters: ReadonlyArray | undefined, parameters: ReadonlyArray, type: TypeNode | undefined, body: Block | undefined): FunctionDeclaration; - function createClassDeclaration(decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, name: string | Identifier | undefined, typeParameters: ReadonlyArray | undefined, heritageClauses: ReadonlyArray, members: ReadonlyArray): ClassDeclaration; - function updateClassDeclaration(node: ClassDeclaration, decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, name: Identifier | undefined, typeParameters: ReadonlyArray | undefined, heritageClauses: ReadonlyArray, members: ReadonlyArray): ClassDeclaration; + function createClassDeclaration(decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, name: string | Identifier | undefined, typeParameters: ReadonlyArray | undefined, heritageClauses: ReadonlyArray | undefined, members: ReadonlyArray): ClassDeclaration; + function updateClassDeclaration(node: ClassDeclaration, decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, name: Identifier | undefined, typeParameters: ReadonlyArray | undefined, heritageClauses: ReadonlyArray | undefined, members: ReadonlyArray): ClassDeclaration; function createInterfaceDeclaration(decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, name: string | Identifier, typeParameters: ReadonlyArray | undefined, heritageClauses: ReadonlyArray | undefined, members: ReadonlyArray): InterfaceDeclaration; function updateInterfaceDeclaration(node: InterfaceDeclaration, decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, name: Identifier, typeParameters: ReadonlyArray | undefined, heritageClauses: ReadonlyArray | undefined, members: ReadonlyArray): InterfaceDeclaration; function createTypeAliasDeclaration(decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, name: string | Identifier, typeParameters: ReadonlyArray | undefined, type: TypeNode): TypeAliasDeclaration; @@ -3740,7 +3744,7 @@ declare namespace ts { function createImportEqualsDeclaration(decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, name: string | Identifier, moduleReference: ModuleReference): ImportEqualsDeclaration; function updateImportEqualsDeclaration(node: ImportEqualsDeclaration, decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, name: Identifier, moduleReference: ModuleReference): ImportEqualsDeclaration; function createImportDeclaration(decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression): ImportDeclaration; - function updateImportDeclaration(node: ImportDeclaration, decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression | undefined): ImportDeclaration; + function updateImportDeclaration(node: ImportDeclaration, decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression): ImportDeclaration; function createImportClause(name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause; function updateImportClause(node: ImportClause, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause; function createNamespaceImport(name: Identifier): NamespaceImport; @@ -3749,7 +3753,7 @@ declare namespace ts { function updateNamedImports(node: NamedImports, elements: ReadonlyArray): NamedImports; function createImportSpecifier(propertyName: Identifier | undefined, name: Identifier): ImportSpecifier; function updateImportSpecifier(node: ImportSpecifier, propertyName: Identifier | undefined, name: Identifier): ImportSpecifier; - function createExportAssignment(decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, isExportEquals: boolean, expression: Expression): ExportAssignment; + function createExportAssignment(decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, isExportEquals: boolean | undefined, expression: Expression): ExportAssignment; function updateExportAssignment(node: ExportAssignment, decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, expression: Expression): ExportAssignment; function createExportDeclaration(decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, exportClause: NamedExports | undefined, moduleSpecifier?: Expression): ExportDeclaration; function updateExportDeclaration(node: ExportDeclaration, decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, exportClause: NamedExports | undefined, moduleSpecifier: Expression | undefined): ExportDeclaration; @@ -3879,16 +3883,16 @@ declare namespace ts { */ function setCommentRange(node: T, range: TextRange): T; function getSyntheticLeadingComments(node: Node): SynthesizedComment[] | undefined; - function setSyntheticLeadingComments(node: T, comments: SynthesizedComment[]): T; + function setSyntheticLeadingComments(node: T, comments: SynthesizedComment[] | undefined): T; function addSyntheticLeadingComment(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean): T; function getSyntheticTrailingComments(node: Node): SynthesizedComment[] | undefined; - function setSyntheticTrailingComments(node: T, comments: SynthesizedComment[]): T; + function setSyntheticTrailingComments(node: T, comments: SynthesizedComment[] | undefined): T; function addSyntheticTrailingComment(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean): T; function moveSyntheticComments(node: T, original: Node): T; /** * Gets the constant value to emit for an expression. */ - function getConstantValue(node: PropertyAccessExpression | ElementAccessExpression): string | number; + function getConstantValue(node: PropertyAccessExpression | ElementAccessExpression): string | number | undefined; /** * Sets the constant value to emit for an expression. */ @@ -3924,7 +3928,7 @@ declare namespace ts { * @param test A callback to execute to verify the Node is valid. * @param lift An optional callback to execute to lift a NodeArray into a valid Node. */ - function visitNode(node: T, visitor: Visitor, test?: (node: Node) => boolean, lift?: (node: NodeArray) => T): T; + function visitNode(node: T | undefined, visitor: Visitor | undefined, test?: (node: Node) => boolean, lift?: (node: NodeArray) => T): T; /** * Visits a Node using the supplied visitor, possibly returning a new Node in its place. * @@ -3933,7 +3937,7 @@ declare namespace ts { * @param test A callback to execute to verify the Node is valid. * @param lift An optional callback to execute to lift a NodeArray into a valid Node. */ - function visitNode(node: T | undefined, visitor: Visitor, test?: (node: Node) => boolean, lift?: (node: NodeArray) => T): T | undefined; + function visitNode(node: T | undefined, visitor: Visitor | undefined, test?: (node: Node) => boolean, lift?: (node: NodeArray) => T): T | undefined; /** * Visits a NodeArray using the supplied visitor, possibly returning a new NodeArray in its place. * @@ -3943,7 +3947,7 @@ declare namespace ts { * @param start An optional value indicating the starting offset at which to start visiting. * @param count An optional value indicating the maximum number of nodes to visit. */ - function visitNodes(nodes: NodeArray, visitor: Visitor, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray; + function visitNodes(nodes: NodeArray | undefined, visitor: Visitor, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray; /** * Visits a NodeArray using the supplied visitor, possibly returning a new NodeArray in its place. * @@ -3963,7 +3967,7 @@ declare namespace ts { * Starts a new lexical environment and visits a parameter list, suspending the lexical * environment upon completion. */ - function visitParameterList(nodes: NodeArray, visitor: Visitor, context: TransformationContext, nodesVisitor?: typeof visitNodes): NodeArray; + function visitParameterList(nodes: NodeArray | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: typeof visitNodes): NodeArray; /** * Resumes a suspended lexical environment and visits a function body, ending the lexical * environment and merging hoisted declarations upon completion. @@ -4012,7 +4016,7 @@ declare namespace ts { function formatDiagnostics(diagnostics: ReadonlyArray, host: FormatDiagnosticsHost): string; function formatDiagnostic(diagnostic: Diagnostic, host: FormatDiagnosticsHost): string; function formatDiagnosticsWithColorAndContext(diagnostics: ReadonlyArray, host: FormatDiagnosticsHost): string; - function flattenDiagnosticMessageText(messageText: string | DiagnosticMessageChain, newLine: string): string; + function flattenDiagnosticMessageText(messageText: string | DiagnosticMessageChain | undefined, newLine: string): string; function getConfigFileParsingDiagnostics(configFileParseResult: ParsedCommandLine): ReadonlyArray; /** * Create a new 'Program' instance. A Program is an immutable collection of 'SourceFile's and a 'CompilerOptions' @@ -4207,11 +4211,11 @@ declare namespace ts { /** If provided would be used to write log about compilation */ trace?(s: string): void; /** If provided is used to get the environment variable */ - getEnvironmentVariable?(name: string): string; + getEnvironmentVariable?(name: string): string | undefined; /** If provided, used to resolve the module names, otherwise typescript's default module resolution */ resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[]): ResolvedModule[]; /** If provided, used to resolve type reference directives, otherwise typescript's default resolution */ - resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): (ResolvedTypeReferenceDirective | undefined)[]; + resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[]; /** Used to watch changes in source files, missing files needed to update the program or config file */ watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher; /** Used to watch resolved module's failed lookup locations, config file specs, type roots where auto type reference directives are added */ @@ -4361,8 +4365,8 @@ declare namespace ts { getLeadingTriviaWidth(sourceFile?: SourceFile): number; getFullText(sourceFile?: SourceFile): string; getText(sourceFile?: SourceFile): string; - getFirstToken(sourceFile?: SourceFile): Node; - getLastToken(sourceFile?: SourceFile): Node; + getFirstToken(sourceFile?: SourceFile): Node | undefined; + getLastToken(sourceFile?: SourceFile): Node | undefined; forEachChild(cbNode: (node: Node) => T | undefined, cbNodeArray?: (nodes: NodeArray) => T | undefined): T | undefined; } interface Identifier { @@ -4450,7 +4454,7 @@ declare namespace ts { referencedFiles: FileReference[]; typeReferenceDirectives: FileReference[]; importedFiles: FileReference[]; - ambientExternalModules: string[]; + ambientExternalModules?: string[]; isLibFile: boolean; } interface HostCancellationToken { @@ -4483,7 +4487,7 @@ declare namespace ts { fileExists?(path: string): boolean; getTypeRootsVersion?(): number; resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[]): ResolvedModule[]; - getResolvedModuleWithFailedLookupLocationsFromCache?(modulename: string, containingFile: string): ResolvedModuleWithFailedLookupLocations; + getResolvedModuleWithFailedLookupLocationsFromCache?(modulename: string, containingFile: string): ResolvedModuleWithFailedLookupLocations | undefined; resolveTypeReferenceDirectives?(typeDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[]; getDirectories?(directoryName: string): string[]; /** @@ -4518,24 +4522,24 @@ declare namespace ts { getSemanticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[]; getEncodedSyntacticClassifications(fileName: string, span: TextSpan): Classifications; getEncodedSemanticClassifications(fileName: string, span: TextSpan): Classifications; - getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions | undefined): CompletionInfo; - getCompletionEntryDetails(fileName: string, position: number, name: string, formatOptions: FormatCodeOptions | FormatCodeSettings | undefined, source: string | undefined, preferences: UserPreferences | undefined): CompletionEntryDetails; - getCompletionEntrySymbol(fileName: string, position: number, name: string, source: string | undefined): Symbol; - getQuickInfoAtPosition(fileName: string, position: number): QuickInfo; - getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan; - getBreakpointStatementAtPosition(fileName: string, position: number): TextSpan; - getSignatureHelpItems(fileName: string, position: number): SignatureHelpItems; + getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions | undefined): CompletionInfo | undefined; + getCompletionEntryDetails(fileName: string, position: number, name: string, formatOptions: FormatCodeOptions | FormatCodeSettings | undefined, source: string | undefined, preferences: UserPreferences | undefined): CompletionEntryDetails | undefined; + getCompletionEntrySymbol(fileName: string, position: number, name: string, source: string | undefined): Symbol | undefined; + getQuickInfoAtPosition(fileName: string, position: number): QuickInfo | undefined; + getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan | undefined; + getBreakpointStatementAtPosition(fileName: string, position: number): TextSpan | undefined; + getSignatureHelpItems(fileName: string, position: number): SignatureHelpItems | undefined; getRenameInfo(fileName: string, position: number): RenameInfo; - findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[]; - getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[]; - getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan; - getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[]; - getImplementationAtPosition(fileName: string, position: number): ImplementationLocation[]; - getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[]; - findReferences(fileName: string, position: number): ReferencedSymbol[]; - getDocumentHighlights(fileName: string, position: number, filesToSearch: string[]): DocumentHighlights[]; + findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[] | undefined; + getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] | undefined; + getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan | undefined; + getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] | undefined; + getImplementationAtPosition(fileName: string, position: number): ImplementationLocation[] | undefined; + getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] | undefined; + findReferences(fileName: string, position: number): ReferencedSymbol[] | undefined; + getDocumentHighlights(fileName: string, position: number, filesToSearch: string[]): DocumentHighlights[] | undefined; /** @deprecated */ - getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[]; + getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[] | undefined; getNavigateToItems(searchValue: string, maxResultCount?: number, fileName?: string, excludeDtsFiles?: boolean): NavigateToItem[]; getNavigationBarItems(fileName: string): NavigationBarItem[]; getNavigationTree(fileName: string): NavigationTree; @@ -4546,9 +4550,9 @@ declare namespace ts { getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions | FormatCodeSettings): TextChange[]; getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[]; getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[]; - getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion; + getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion | undefined; isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean; - getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan; + getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan | undefined; toLineColumnOffset?(fileName: string, position: number): LineAndCharacter; getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: ReadonlyArray, formatOptions: FormatCodeSettings, preferences: UserPreferences): ReadonlyArray; getCombinedCodeFix(scope: CombinedCodeFixScope, fixId: {}, formatOptions: FormatCodeSettings, preferences: UserPreferences): CombinedCodeActions; @@ -4566,7 +4570,7 @@ declare namespace ts { organizeImports(scope: OrganizeImportsScope, formatOptions: FormatCodeSettings, preferences: UserPreferences | undefined): ReadonlyArray; getEditsForFileRename(oldFilePath: string, newFilePath: string, formatOptions: FormatCodeSettings): ReadonlyArray; getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean): EmitOutput; - getProgram(): Program; + getProgram(): Program | undefined; dispose(): void; } interface CombinedCodeFixScope { @@ -4669,7 +4673,7 @@ declare namespace ts { } interface CombinedCodeActions { changes: ReadonlyArray; - commands: ReadonlyArray | undefined; + commands?: ReadonlyArray; } type CodeActionCommand = InstallPackageAction; interface InstallPackageAction { @@ -4719,8 +4723,8 @@ declare namespace ts { */ interface RefactorEditInfo { edits: FileTextChanges[]; - renameFilename: string | undefined; - renameLocation: number | undefined; + renameFilename?: string; + renameLocation?: number; commands?: CodeActionCommand[]; } interface TextInsertion { @@ -4841,7 +4845,7 @@ declare namespace ts { containerName: string; } interface DefinitionInfoAndBoundSpan { - definitions: ReadonlyArray; + definitions?: ReadonlyArray; textSpan: TextSpan; } interface ReferencedSymbolDefinitionInfo extends DefinitionInfo { @@ -4887,13 +4891,13 @@ declare namespace ts { kind: ScriptElementKind; kindModifiers: string; textSpan: TextSpan; - displayParts: SymbolDisplayPart[]; - documentation: SymbolDisplayPart[]; - tags: JSDocTagInfo[]; + displayParts?: SymbolDisplayPart[]; + documentation?: SymbolDisplayPart[]; + tags?: JSDocTagInfo[]; } interface RenameInfo { canRename: boolean; - localizedErrorMessage: string; + localizedErrorMessage?: string; displayName: string; fullDisplayName: string; kind: ScriptElementKind; @@ -4945,7 +4949,7 @@ declare namespace ts { interface CompletionEntry { name: string; kind: ScriptElementKind; - kindModifiers: string; + kindModifiers?: string; sortText: string; insertText?: string; /** @@ -4963,8 +4967,8 @@ declare namespace ts { kind: ScriptElementKind; kindModifiers: string; displayParts: SymbolDisplayPart[]; - documentation: SymbolDisplayPart[]; - tags: JSDocTagInfo[]; + documentation?: SymbolDisplayPart[]; + tags?: JSDocTagInfo[]; codeActions?: CodeAction[]; source?: SymbolDisplayPart[]; } @@ -5277,12 +5281,12 @@ declare namespace ts { /** The version of the language service API */ const servicesVersion = "0.8"; function toEditorSettings(options: EditorOptions | EditorSettings): EditorSettings; - function displayPartsToString(displayParts: SymbolDisplayPart[]): string; + function displayPartsToString(displayParts: SymbolDisplayPart[] | undefined): string; function getDefaultCompilerOptions(): CompilerOptions; function getSupportedCodeFixes(): string[]; function createLanguageServiceSourceFile(fileName: string, scriptSnapshot: IScriptSnapshot, scriptTarget: ScriptTarget, version: string, setNodeParents: boolean, scriptKind?: ScriptKind): SourceFile; let disableIncrementalParsing: boolean; - function updateLanguageServiceSourceFile(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile; + function updateLanguageServiceSourceFile(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string, textChangeRange: TextChangeRange | undefined, aggressiveChecks?: boolean): SourceFile; function createLanguageService(host: LanguageServiceHost, documentRegistry?: DocumentRegistry, syntaxOnly?: boolean): LanguageService; /** * Get the path of the default library files (lib.d.ts) as distributed with the typescript @@ -5440,7 +5444,7 @@ declare namespace ts.server { startGroup(): void; endGroup(): void; msg(s: string, type?: Msg): void; - getLogFileName(): string; + getLogFileName(): string | undefined; } enum Msg { Err = "Err", @@ -5465,7 +5469,7 @@ declare namespace ts.server { function normalizedPathToPath(normalizedPath: NormalizedPath, currentDirectory: string, getCanonicalFileName: (f: string) => string): Path; function asNormalizedPath(fileName: string): NormalizedPath; interface NormalizedPathMap { - get(path: NormalizedPath): T; + get(path: NormalizedPath): T | undefined; set(path: NormalizedPath, value: T): void; contains(path: NormalizedPath): boolean; remove(path: NormalizedPath): void; @@ -6858,7 +6862,7 @@ declare namespace ts.server.protocol { } interface CompletionEntryIdentifier { name: string; - source: string; + source?: string; } /** * Completion entry details request; value of command field is @@ -6898,7 +6902,7 @@ declare namespace ts.server.protocol { /** * Optional modifiers for the kind (such as 'public'). */ - kindModifiers: string; + kindModifiers?: string; /** * A string that is used for comparing completion items so that they can be ordered. This * is often the same as the name but may be different in certain circumstances. @@ -6955,11 +6959,11 @@ declare namespace ts.server.protocol { /** * Documentation strings for the symbol. */ - documentation: SymbolDisplayPart[]; + documentation?: SymbolDisplayPart[]; /** * JSDoc tags for the symbol. */ - tags: JSDocTagInfo[]; + tags?: JSDocTagInfo[]; /** * The associated code actions for this entry */ @@ -7734,15 +7738,15 @@ declare namespace ts.server { close(fileExists?: boolean): void; getSnapshot(): IScriptSnapshot; private ensureRealPath; - getFormatCodeSettings(): FormatCodeSettings; - getPreferences(): UserPreferences; + getFormatCodeSettings(): FormatCodeSettings | undefined; + getPreferences(): UserPreferences | undefined; attachToProject(project: Project): boolean; isAttached(project: Project): boolean; detachFromProject(project: Project): void; detachAllProjects(): void; getDefaultProject(): Project; registerFileUpdate(): void; - setOptions(formatSettings: FormatCodeSettings, preferences: UserPreferences): void; + setOptions(formatSettings: FormatCodeSettings, preferences: UserPreferences | undefined): void; getLatestVersion(): string; saveTo(fileName: string): void; reloadFromFile(tempFileName?: NormalizedPath): void; @@ -7770,7 +7774,7 @@ declare namespace ts.server { interface ITypingsInstaller { isKnownTypesPackageName(name: string): boolean; installPackage(options: InstallPackageOptionsWithProject): Promise; - enqueueInstallTypingsRequest(p: Project, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray): void; + enqueueInstallTypingsRequest(p: Project, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray | undefined): void; attach(projectService: ProjectService): void; onProjectClosed(p: Project): void; readonly globalTypingsCacheLocation: string | undefined; @@ -7863,7 +7867,7 @@ declare namespace ts.server { private getOrCreateScriptInfoAndAttachToProject; getScriptKind(fileName: string): ScriptKind; getScriptVersion(filename: string): string; - getScriptSnapshot(filename: string): IScriptSnapshot; + getScriptSnapshot(filename: string): IScriptSnapshot | undefined; getCancellationToken(): HostCancellationToken; getCurrentDirectory(): string; getDefaultLibFileName(): string; @@ -7872,7 +7876,7 @@ declare namespace ts.server { readFile(fileName: string): string | undefined; fileExists(file: string): boolean; resolveModuleNames(moduleNames: string[], containingFile: string, reusedNames?: string[]): ResolvedModuleFull[]; - getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string): ResolvedModuleWithFailedLookupLocations; + getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string): ResolvedModuleWithFailedLookupLocations | undefined; resolveTypeReferenceDirectives(typeDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[]; directoryExists(path: string): boolean; getDirectories(path: string): string[]; @@ -7897,7 +7901,7 @@ declare namespace ts.server { abstract getTypeAcquisition(): TypeAcquisition; protected removeLocalTypingsFromTypeAcquisition(newTypeAcquisition: TypeAcquisition): TypeAcquisition; getExternalFiles(): SortedReadonlyArray; - getSourceFile(path: Path): SourceFile; + getSourceFile(path: Path): SourceFile | undefined; close(): void; private detachScriptInfoIfNotRoot; isClosed(): boolean; @@ -7927,7 +7931,7 @@ declare namespace ts.server { private addMissingFileWatcher; private isWatchedMissingFile; getScriptInfoForNormalizedPath(fileName: NormalizedPath): ScriptInfo | undefined; - getScriptInfo(uncheckedFileName: string): ScriptInfo; + getScriptInfo(uncheckedFileName: string): ScriptInfo | undefined; filesToString(writeProjectFileNames: boolean): string; setCompilerOptions(compilerOptions: CompilerOptions): void; protected removeRoot(info: ScriptInfo): void; @@ -8073,7 +8077,7 @@ declare namespace ts.server { readonly info: OpenFileInfo; } interface ProjectInfoTypeAcquisitionData { - readonly enable: boolean; + readonly enable: boolean | undefined; readonly include: boolean; readonly exclude: boolean; } @@ -8158,7 +8162,7 @@ declare namespace ts.server { /** * Open files: with value being project root path, and key being Path of the file that is open */ - readonly openFiles: Map; + readonly openFiles: Map; /** * Map of open files that are opened without complete path but have projectRoot as current directory */ @@ -8210,8 +8214,8 @@ declare namespace ts.server { private delayUpdateProjectGraphs; setCompilerOptionsForInferredProjects(projectCompilerOptions: protocol.ExternalProjectCompilerOptions, projectRootPath?: string): void; findProject(projectName: string): Project | undefined; - getDefaultProjectForFile(fileName: NormalizedPath, ensureProject: boolean): Project; - getScriptInfoEnsuringProjectsUptoDate(uncheckedFileName: string): ScriptInfo; + getDefaultProjectForFile(fileName: NormalizedPath, ensureProject: boolean): Project | undefined; + getScriptInfoEnsuringProjectsUptoDate(uncheckedFileName: string): ScriptInfo | undefined; /** * Ensures the project structures are upto date * This means, @@ -8295,18 +8299,18 @@ declare namespace ts.server { private getOrCreateSingleInferredProjectIfEnabled; private getOrCreateSingleInferredWithoutProjectRoot; private createInferredProject; - getScriptInfo(uncheckedFileName: string): ScriptInfo; + getScriptInfo(uncheckedFileName: string): ScriptInfo | undefined; private watchClosedScriptInfo; private stopWatchingScriptInfo; getOrCreateScriptInfoForNormalizedPath(fileName: NormalizedPath, openedByClient: boolean, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, hostToQueryFileExistsOn?: { fileExists(path: string): boolean; - }): ScriptInfo; + }): ScriptInfo | undefined; private getOrCreateScriptInfoWorker; /** * This gets the script info for the normalized path. If the path is not rooted disk path then the open script info with project root context is preferred */ - getScriptInfoForNormalizedPath(fileName: NormalizedPath): ScriptInfo; - getScriptInfoForPath(fileName: Path): ScriptInfo; + getScriptInfoForNormalizedPath(fileName: NormalizedPath): ScriptInfo | undefined; + getScriptInfoForPath(fileName: Path): ScriptInfo | undefined; setHostConfiguration(args: protocol.ConfigureRequestArguments): void; closeLog(): void; /** diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 71d598ca102e2..70f2e0d0cdbf5 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -460,7 +460,7 @@ declare namespace ts { flags: NodeFlags; decorators?: NodeArray; modifiers?: ModifiersArray; - parent?: Node; + parent: Node; } interface JSDocContainer { } @@ -525,12 +525,12 @@ declare namespace ts { } interface Decorator extends Node { kind: SyntaxKind.Decorator; - parent?: NamedDeclaration; + parent: NamedDeclaration; expression: LeftHandSideExpression; } interface TypeParameterDeclaration extends NamedDeclaration { kind: SyntaxKind.TypeParameter; - parent?: DeclarationWithTypeParameters | InferTypeNode; + parent: DeclarationWithTypeParameters | InferTypeNode; name: Identifier; constraint?: TypeNode; default?: TypeNode; @@ -541,7 +541,7 @@ declare namespace ts { name?: PropertyName; typeParameters?: NodeArray; parameters: NodeArray; - type: TypeNode | undefined; + type?: TypeNode; } type SignatureDeclaration = CallSignatureDeclaration | ConstructSignatureDeclaration | MethodSignature | IndexSignatureDeclaration | FunctionTypeNode | ConstructorTypeNode | JSDocFunctionType | FunctionDeclaration | MethodDeclaration | ConstructorDeclaration | AccessorDeclaration | FunctionExpression | ArrowFunction; interface CallSignatureDeclaration extends SignatureDeclarationBase, TypeElement { @@ -553,7 +553,7 @@ declare namespace ts { type BindingName = Identifier | BindingPattern; interface VariableDeclaration extends NamedDeclaration { kind: SyntaxKind.VariableDeclaration; - parent?: VariableDeclarationList | CatchClause; + parent: VariableDeclarationList | CatchClause; name: BindingName; exclamationToken?: ExclamationToken; type?: TypeNode; @@ -561,12 +561,12 @@ declare namespace ts { } interface VariableDeclarationList extends Node { kind: SyntaxKind.VariableDeclarationList; - parent?: VariableStatement | ForStatement | ForOfStatement | ForInStatement; + parent: VariableStatement | ForStatement | ForOfStatement | ForInStatement; declarations: NodeArray; } interface ParameterDeclaration extends NamedDeclaration, JSDocContainer { kind: SyntaxKind.Parameter; - parent?: SignatureDeclaration; + parent: SignatureDeclaration; dotDotDotToken?: DotDotDotToken; name: BindingName; questionToken?: QuestionToken; @@ -575,7 +575,7 @@ declare namespace ts { } interface BindingElement extends NamedDeclaration { kind: SyntaxKind.BindingElement; - parent?: BindingPattern; + parent: BindingPattern; propertyName?: PropertyName; dotDotDotToken?: DotDotDotToken; name: BindingName; @@ -628,12 +628,12 @@ declare namespace ts { } interface ObjectBindingPattern extends Node { kind: SyntaxKind.ObjectBindingPattern; - parent?: VariableDeclaration | ParameterDeclaration | BindingElement; + parent: VariableDeclaration | ParameterDeclaration | BindingElement; elements: NodeArray; } interface ArrayBindingPattern extends Node { kind: SyntaxKind.ArrayBindingPattern; - parent?: VariableDeclaration | ParameterDeclaration | BindingElement; + parent: VariableDeclaration | ParameterDeclaration | BindingElement; elements: NodeArray; } type BindingPattern = ObjectBindingPattern | ArrayBindingPattern; @@ -662,41 +662,41 @@ declare namespace ts { } interface MethodSignature extends SignatureDeclarationBase, TypeElement { kind: SyntaxKind.MethodSignature; - parent?: ObjectTypeDeclaration; + parent: ObjectTypeDeclaration; name: PropertyName; } interface MethodDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer { kind: SyntaxKind.MethodDeclaration; - parent?: ClassLikeDeclaration | ObjectLiteralExpression; + parent: ClassLikeDeclaration | ObjectLiteralExpression; name: PropertyName; body?: FunctionBody; } interface ConstructorDeclaration extends FunctionLikeDeclarationBase, ClassElement, JSDocContainer { kind: SyntaxKind.Constructor; - parent?: ClassLikeDeclaration; + parent: ClassLikeDeclaration; body?: FunctionBody; } /** For when we encounter a semicolon in a class declaration. ES6 allows these as class elements. */ interface SemicolonClassElement extends ClassElement { kind: SyntaxKind.SemicolonClassElement; - parent?: ClassLikeDeclaration; + parent: ClassLikeDeclaration; } interface GetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer { kind: SyntaxKind.GetAccessor; - parent?: ClassLikeDeclaration | ObjectLiteralExpression; + parent: ClassLikeDeclaration | ObjectLiteralExpression; name: PropertyName; body?: FunctionBody; } interface SetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer { kind: SyntaxKind.SetAccessor; - parent?: ClassLikeDeclaration | ObjectLiteralExpression; + parent: ClassLikeDeclaration | ObjectLiteralExpression; name: PropertyName; body?: FunctionBody; } type AccessorDeclaration = GetAccessorDeclaration | SetAccessorDeclaration; interface IndexSignatureDeclaration extends SignatureDeclarationBase, ClassElement, TypeElement { kind: SyntaxKind.IndexSignature; - parent?: ObjectTypeDeclaration; + parent: ObjectTypeDeclaration; } interface TypeNode extends Node { _typeNodeBrand: any; @@ -730,7 +730,7 @@ declare namespace ts { } interface TypePredicateNode extends TypeNode { kind: SyntaxKind.TypePredicate; - parent?: SignatureDeclaration; + parent: SignatureDeclaration; parameterName: Identifier | ThisTypeNode; type: TypeNode; } @@ -959,15 +959,15 @@ declare namespace ts { } interface TemplateHead extends LiteralLikeNode { kind: SyntaxKind.TemplateHead; - parent?: TemplateExpression; + parent: TemplateExpression; } interface TemplateMiddle extends LiteralLikeNode { kind: SyntaxKind.TemplateMiddle; - parent?: TemplateSpan; + parent: TemplateSpan; } interface TemplateTail extends LiteralLikeNode { kind: SyntaxKind.TemplateTail; - parent?: TemplateSpan; + parent: TemplateSpan; } type TemplateLiteral = TemplateExpression | NoSubstitutionTemplateLiteral; interface TemplateExpression extends PrimaryExpression { @@ -977,7 +977,7 @@ declare namespace ts { } interface TemplateSpan extends Node { kind: SyntaxKind.TemplateSpan; - parent?: TemplateExpression; + parent: TemplateExpression; expression: Expression; literal: TemplateMiddle | TemplateTail; } @@ -991,7 +991,7 @@ declare namespace ts { } interface SpreadElement extends Expression { kind: SyntaxKind.SpreadElement; - parent?: ArrayLiteralExpression | CallExpression | NewExpression; + parent: ArrayLiteralExpression | CallExpression | NewExpression; expression: Expression; } /** @@ -1044,7 +1044,7 @@ declare namespace ts { } interface ExpressionWithTypeArguments extends NodeWithTypeArguments { kind: SyntaxKind.ExpressionWithTypeArguments; - parent?: HeritageClause; + parent: HeritageClause; expression: LeftHandSideExpression; } interface NewExpression extends PrimaryExpression, Declaration { @@ -1090,11 +1090,11 @@ declare namespace ts { type JsxAttributeLike = JsxAttribute | JsxSpreadAttribute; type JsxTagNameExpression = PrimaryExpression | PropertyAccessExpression; interface JsxAttributes extends ObjectLiteralExpressionBase { - parent?: JsxOpeningLikeElement; + parent: JsxOpeningLikeElement; } interface JsxOpeningElement extends Expression { kind: SyntaxKind.JsxOpeningElement; - parent?: JsxElement; + parent: JsxElement; tagName: JsxTagNameExpression; typeArguments?: NodeArray; attributes: JsxAttributes; @@ -1113,38 +1113,38 @@ declare namespace ts { } interface JsxOpeningFragment extends Expression { kind: SyntaxKind.JsxOpeningFragment; - parent?: JsxFragment; + parent: JsxFragment; } interface JsxClosingFragment extends Expression { kind: SyntaxKind.JsxClosingFragment; - parent?: JsxFragment; + parent: JsxFragment; } interface JsxAttribute extends ObjectLiteralElement { kind: SyntaxKind.JsxAttribute; - parent?: JsxAttributes; + parent: JsxAttributes; name: Identifier; initializer?: StringLiteral | JsxExpression; } interface JsxSpreadAttribute extends ObjectLiteralElement { kind: SyntaxKind.JsxSpreadAttribute; - parent?: JsxAttributes; + parent: JsxAttributes; expression: Expression; } interface JsxClosingElement extends Node { kind: SyntaxKind.JsxClosingElement; - parent?: JsxElement; + parent: JsxElement; tagName: JsxTagNameExpression; } interface JsxExpression extends Expression { kind: SyntaxKind.JsxExpression; - parent?: JsxElement | JsxAttributeLike; + parent: JsxElement | JsxAttributeLike; dotDotDotToken?: Token; expression?: Expression; } interface JsxText extends Node { kind: SyntaxKind.JsxText; containsOnlyWhiteSpaces: boolean; - parent?: JsxElement; + parent: JsxElement; } type JsxChild = JsxText | JsxExpression | JsxElement | JsxSelfClosingElement | JsxFragment; interface Statement extends Node { @@ -1245,18 +1245,18 @@ declare namespace ts { } interface CaseBlock extends Node { kind: SyntaxKind.CaseBlock; - parent?: SwitchStatement; + parent: SwitchStatement; clauses: NodeArray; } interface CaseClause extends Node { kind: SyntaxKind.CaseClause; - parent?: CaseBlock; + parent: CaseBlock; expression: Expression; statements: NodeArray; } interface DefaultClause extends Node { kind: SyntaxKind.DefaultClause; - parent?: CaseBlock; + parent: CaseBlock; statements: NodeArray; } type CaseOrDefaultClause = CaseClause | DefaultClause; @@ -1267,7 +1267,7 @@ declare namespace ts { } interface ThrowStatement extends Statement { kind: SyntaxKind.ThrowStatement; - expression: Expression; + expression?: Expression; } interface TryStatement extends Statement { kind: SyntaxKind.TryStatement; @@ -1277,7 +1277,7 @@ declare namespace ts { } interface CatchClause extends Node { kind: SyntaxKind.CatchClause; - parent?: TryStatement; + parent: TryStatement; variableDeclaration?: VariableDeclaration; block: Block; } @@ -1317,7 +1317,7 @@ declare namespace ts { } interface HeritageClause extends Node { kind: SyntaxKind.HeritageClause; - parent?: InterfaceDeclaration | ClassLikeDeclaration; + parent: InterfaceDeclaration | ClassLikeDeclaration; token: SyntaxKind.ExtendsKeyword | SyntaxKind.ImplementsKeyword; types: NodeArray; } @@ -1329,7 +1329,7 @@ declare namespace ts { } interface EnumMember extends NamedDeclaration, JSDocContainer { kind: SyntaxKind.EnumMember; - parent?: EnumDeclaration; + parent: EnumDeclaration; name: PropertyName; initializer?: Expression; } @@ -1342,7 +1342,7 @@ declare namespace ts { type ModuleBody = NamespaceBody | JSDocNamespaceBody; interface ModuleDeclaration extends DeclarationStatement, JSDocContainer { kind: SyntaxKind.ModuleDeclaration; - parent?: ModuleBody | SourceFile; + parent: ModuleBody | SourceFile; name: ModuleName; body?: ModuleBody | JSDocNamespaceDeclaration; } @@ -1354,11 +1354,11 @@ declare namespace ts { type JSDocNamespaceBody = Identifier | JSDocNamespaceDeclaration; interface JSDocNamespaceDeclaration extends ModuleDeclaration { name: Identifier; - body: JSDocNamespaceBody; + body?: JSDocNamespaceBody; } interface ModuleBlock extends Node, Statement { kind: SyntaxKind.ModuleBlock; - parent?: ModuleDeclaration; + parent: ModuleDeclaration; statements: NodeArray; } type ModuleReference = EntityName | ExternalModuleReference; @@ -1369,18 +1369,18 @@ declare namespace ts { */ interface ImportEqualsDeclaration extends DeclarationStatement, JSDocContainer { kind: SyntaxKind.ImportEqualsDeclaration; - parent?: SourceFile | ModuleBlock; + parent: SourceFile | ModuleBlock; name: Identifier; moduleReference: ModuleReference; } interface ExternalModuleReference extends Node { kind: SyntaxKind.ExternalModuleReference; - parent?: ImportEqualsDeclaration; - expression?: Expression; + parent: ImportEqualsDeclaration; + expression: Expression; } interface ImportDeclaration extends Statement { kind: SyntaxKind.ImportDeclaration; - parent?: SourceFile | ModuleBlock; + parent: SourceFile | ModuleBlock; importClause?: ImportClause; /** If this is not a StringLiteral it will be a grammar error. */ moduleSpecifier: Expression; @@ -1388,13 +1388,13 @@ declare namespace ts { type NamedImportBindings = NamespaceImport | NamedImports; interface ImportClause extends NamedDeclaration { kind: SyntaxKind.ImportClause; - parent?: ImportDeclaration; + parent: ImportDeclaration; name?: Identifier; namedBindings?: NamedImportBindings; } interface NamespaceImport extends NamedDeclaration { kind: SyntaxKind.NamespaceImport; - parent?: ImportClause; + parent: ImportClause; name: Identifier; } interface NamespaceExportDeclaration extends DeclarationStatement { @@ -1403,7 +1403,7 @@ declare namespace ts { } interface ExportDeclaration extends DeclarationStatement { kind: SyntaxKind.ExportDeclaration; - parent?: SourceFile | ModuleBlock; + parent: SourceFile | ModuleBlock; /** Will not be assigned in the case of `export * from "foo";` */ exportClause?: NamedExports; /** If this is not a StringLiteral it will be a grammar error. */ @@ -1411,24 +1411,24 @@ declare namespace ts { } interface NamedImports extends Node { kind: SyntaxKind.NamedImports; - parent?: ImportClause; + parent: ImportClause; elements: NodeArray; } interface NamedExports extends Node { kind: SyntaxKind.NamedExports; - parent?: ExportDeclaration; + parent: ExportDeclaration; elements: NodeArray; } type NamedImportsOrExports = NamedImports | NamedExports; interface ImportSpecifier extends NamedDeclaration { kind: SyntaxKind.ImportSpecifier; - parent?: NamedImports; + parent: NamedImports; propertyName?: Identifier; name: Identifier; } interface ExportSpecifier extends NamedDeclaration { kind: SyntaxKind.ExportSpecifier; - parent?: NamedExports; + parent: NamedExports; propertyName?: Identifier; name: Identifier; } @@ -1439,7 +1439,7 @@ declare namespace ts { */ interface ExportAssignment extends DeclarationStatement { kind: SyntaxKind.ExportAssignment; - parent?: SourceFile; + parent: SourceFile; isExportEquals?: boolean; expression: Expression; } @@ -1494,15 +1494,15 @@ declare namespace ts { type JSDocTypeReferencingNode = JSDocVariadicType | JSDocOptionalType | JSDocNullableType | JSDocNonNullableType; interface JSDoc extends Node { kind: SyntaxKind.JSDocComment; - parent?: HasJSDoc; - tags: NodeArray | undefined; - comment: string | undefined; + parent: HasJSDoc; + tags?: NodeArray; + comment?: string; } interface JSDocTag extends Node { parent: JSDoc | JSDocTypeLiteral; atToken: AtToken; tagName: Identifier; - comment: string | undefined; + comment?: string; } interface JSDocUnknownTag extends JSDocTag { kind: SyntaxKind.JSDocTag; @@ -1526,11 +1526,11 @@ declare namespace ts { } interface JSDocReturnTag extends JSDocTag { kind: SyntaxKind.JSDocReturnTag; - typeExpression: JSDocTypeExpression; + typeExpression?: JSDocTypeExpression; } interface JSDocTypeTag extends JSDocTag { kind: SyntaxKind.JSDocTypeTag; - typeExpression: JSDocTypeExpression; + typeExpression?: JSDocTypeExpression; } interface JSDocTypedefTag extends JSDocTag, NamedDeclaration { parent: JSDoc; @@ -1608,7 +1608,7 @@ declare namespace ts { container?: FunctionExpression | ArrowFunction | MethodDeclaration; } interface FlowLabel extends FlowNodeBase { - antecedents: FlowNode[]; + antecedents: FlowNode[] | undefined; } interface FlowAssignment extends FlowNodeBase { node: Expression | VariableDeclaration | BindingElement; @@ -1635,7 +1635,7 @@ declare namespace ts { } interface AmdDependency { path: string; - name: string; + name?: string; } interface SourceFile extends Declaration { kind: SyntaxKind.SourceFile; @@ -1644,7 +1644,7 @@ declare namespace ts { fileName: string; text: string; amdDependencies: ReadonlyArray; - moduleName: string; + moduleName?: string; referencedFiles: ReadonlyArray; typeReferenceDirectives: ReadonlyArray; languageVariant: LanguageVariant; @@ -1704,7 +1704,7 @@ declare namespace ts { fileExists(path: string): boolean; readFile(path: string): string | undefined; } - type WriteFileCallback = (fileName: string, data: string, writeByteOrderMark: boolean, onError: ((message: string) => void) | undefined, sourceFiles: ReadonlyArray) => void; + type WriteFileCallback = (fileName: string, data: string, writeByteOrderMark: boolean, onError: ((message: string) => void) | undefined, sourceFiles?: ReadonlyArray) => void; class OperationCanceledException { } interface CancellationToken { @@ -1794,7 +1794,7 @@ declare namespace ts { emitSkipped: boolean; /** Contains declaration emit diagnostics */ diagnostics: ReadonlyArray; - emittedFiles: string[]; + emittedFiles?: string[]; } interface TypeChecker { getTypeOfSymbolAtLocation(symbol: Symbol, node: Node): Type; @@ -1811,7 +1811,7 @@ declare namespace ts { getNullableType(type: Type, flags: TypeFlags): Type; getNonNullableType(type: Type): Type; /** Note that the resulting nodes cannot be checked. */ - typeToTypeNode(type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): TypeNode; + typeToTypeNode(type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): TypeNode | undefined; /** Note that the resulting nodes cannot be checked. */ signatureToSignatureDeclaration(signature: Signature, kind: SyntaxKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): (SignatureDeclaration & { typeArguments?: NodeArray; @@ -1847,7 +1847,7 @@ declare namespace ts { */ getExportSymbolOfSymbol(symbol: Symbol): Symbol; getPropertySymbolOfDestructuringAssignment(location: Identifier): Symbol | undefined; - getTypeAtLocation(node: Node): Type; + getTypeAtLocation(node: Node): Type | undefined; getTypeFromTypeNode(node: TypeNode): Type; signatureToString(signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): string; typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string; @@ -1864,9 +1864,10 @@ declare namespace ts { getContextualType(node: Expression): Type | undefined; /** * returns unknownSignature in the case of an error. + * returns undefined if the node is not valid. * @param argumentCount Apparent number of arguments, passed in case of a possibly incomplete call. This should come from an ArgumentListInfo. See `signatureHelp.ts`. */ - getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[], argumentCount?: number): Signature; + getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[], argumentCount?: number): Signature | undefined; getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature | undefined; isImplementationOfOverload(node: SignatureDeclaration): boolean | undefined; isUndefinedSymbol(symbol: Symbol): boolean; @@ -2070,8 +2071,8 @@ declare namespace ts { interface Symbol { flags: SymbolFlags; escapedName: __String; - declarations?: Declaration[]; - valueDeclaration?: Declaration; + declarations: Declaration[]; + valueDeclaration: Declaration; members?: SymbolTable; exports?: SymbolTable; globalExports?: SymbolTable; @@ -2173,15 +2174,15 @@ declare namespace ts { type DestructuringPattern = BindingPattern | ObjectLiteralExpression | ArrayLiteralExpression; interface Type { flags: TypeFlags; - symbol?: Symbol; + symbol: Symbol; pattern?: DestructuringPattern; aliasSymbol?: Symbol; aliasTypeArguments?: Type[]; } interface LiteralType extends Type { value: string | number; - freshType?: LiteralType; - regularType?: LiteralType; + freshType: LiteralType; + regularType: LiteralType; } interface UniqueESSymbolType extends Type { symbol: Symbol; @@ -2216,18 +2217,18 @@ declare namespace ts { } /** Class and interface types (ObjectFlags.Class and ObjectFlags.Interface). */ interface InterfaceType extends ObjectType { - typeParameters: TypeParameter[]; - outerTypeParameters: TypeParameter[]; - localTypeParameters: TypeParameter[]; - thisType: TypeParameter; + typeParameters: TypeParameter[] | undefined; + outerTypeParameters: TypeParameter[] | undefined; + localTypeParameters: TypeParameter[] | undefined; + thisType: TypeParameter | undefined; } type BaseType = ObjectType | IntersectionType; interface InterfaceTypeWithDeclaredMembers extends InterfaceType { declaredProperties: Symbol[]; declaredCallSignatures: Signature[]; declaredConstructSignatures: Signature[]; - declaredStringIndexInfo: IndexInfo; - declaredNumberIndexInfo: IndexInfo; + declaredStringIndexInfo?: IndexInfo; + declaredNumberIndexInfo?: IndexInfo; } /** * Type references (ObjectFlags.Reference). When a class or interface has type parameters or @@ -2278,11 +2279,11 @@ declare namespace ts { trueType: Type; falseType: Type; isDistributive: boolean; - inferTypeParameters: TypeParameter[]; + inferTypeParameters?: TypeParameter[]; outerTypeParameters?: TypeParameter[]; instantiations?: Map; - aliasSymbol: Symbol; - aliasTypeArguments: Type[]; + aliasSymbol?: Symbol; + aliasTypeArguments?: Type[]; } interface ConditionalType extends InstantiableType { root: ConditionalRoot; @@ -2630,7 +2631,7 @@ declare namespace ts { packageId?: PackageId; } interface ResolvedTypeReferenceDirectiveWithFailedLookupLocations { - readonly resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective; + readonly resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective | undefined; readonly failedLookupLocations: ReadonlyArray; } interface CompilerHost extends ModuleResolutionHost { @@ -2650,8 +2651,8 @@ declare namespace ts { /** * This method is a companion for 'resolveModuleNames' and is used to resolve 'types' references to actual type declaration files */ - resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): (ResolvedTypeReferenceDirective | undefined)[]; - getEnvironmentVariable?(name: string): string; + resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[]; + getEnvironmentVariable?(name: string): string | undefined; createHash?(data: string): string; } interface SourceMapRange extends TextRange { @@ -2663,6 +2664,7 @@ declare namespace ts { skipTrivia?: (pos: number) => number; } enum EmitFlags { + None = 0, SingleLine = 1, AdviseOnEmitNode = 2, NoSubstitution = 4, @@ -2716,7 +2718,7 @@ declare namespace ts { /** Resumes a suspended lexical environment, usually before visiting a function body. */ resumeLexicalEnvironment(): void; /** Ends a lexical environment, returning any declarations. */ - endLexicalEnvironment(): Statement[]; + endLexicalEnvironment(): Statement[] | undefined; /** Hoists a function declaration to the containing scope. */ hoistFunctionDeclaration(node: FunctionDeclaration): void; /** Hoists a variable declaration to the containing scope. */ @@ -2847,7 +2849,7 @@ declare namespace ts { * }); * ``` */ - onEmitNode?(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void; + onEmitNode?(hint: EmitHint, node: Node | undefined, emitCallback: (hint: EmitHint, node: Node | undefined) => void): void; /** * A hook used by the Printer to perform just-in-time substitution of a node. This is * primarily used by node transformations that need to substitute one node for another, @@ -3020,7 +3022,7 @@ declare namespace ts { interface FileWatcher { close(): void; } - function getNodeMajorVersion(): number; + function getNodeMajorVersion(): number | undefined; let sys: System; } declare namespace ts { @@ -3047,8 +3049,8 @@ declare namespace ts { scanJSDocToken(): JsDocSyntaxKind; scan(): SyntaxKind; getText(): string; - setText(text: string, start?: number, length?: number): void; - setOnError(onError: ErrorCallback): void; + setText(text: string | undefined, start?: number, length?: number): void; + setOnError(onError: ErrorCallback | undefined): void; setScriptTarget(scriptTarget: ScriptTarget): void; setLanguageVariant(variant: LanguageVariant): void; setTextPos(textPos: number): void; @@ -3068,15 +3070,15 @@ declare namespace ts { function forEachLeadingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state: T): U | undefined; function forEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean) => U): U | undefined; function forEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state: T): U | undefined; - function reduceEachLeadingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T, memo: U) => U, state: T, initial: U): U; - function reduceEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T, memo: U) => U, state: T, initial: U): U; + function reduceEachLeadingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T, memo: U) => U, state: T, initial: U): U | undefined; + function reduceEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T, memo: U) => U, state: T, initial: U): U | undefined; function getLeadingCommentRanges(text: string, pos: number): CommentRange[] | undefined; function getTrailingCommentRanges(text: string, pos: number): CommentRange[] | undefined; /** Optionally, get the shebang */ function getShebang(text: string): string | undefined; - function isIdentifierStart(ch: number, languageVersion: ScriptTarget): boolean; - function isIdentifierPart(ch: number, languageVersion: ScriptTarget): boolean; - function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean, languageVariant?: LanguageVariant, text?: string, onError?: ErrorCallback, start?: number, length?: number): Scanner; + function isIdentifierStart(ch: number, languageVersion: ScriptTarget | undefined): boolean; + function isIdentifierPart(ch: number, languageVersion: ScriptTarget | undefined): boolean; + function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean, languageVariant?: LanguageVariant, textInitial?: string, onError?: ErrorCallback, start?: number, length?: number): Scanner; } declare namespace ts { function getDefaultLibFileName(options: CompilerOptions): string; @@ -3085,12 +3087,12 @@ declare namespace ts { function textSpanContainsPosition(span: TextSpan, position: number): boolean; function textSpanContainsTextSpan(span: TextSpan, other: TextSpan): boolean; function textSpanOverlapsWith(span: TextSpan, other: TextSpan): boolean; - function textSpanOverlap(span1: TextSpan, span2: TextSpan): TextSpan; + function textSpanOverlap(span1: TextSpan, span2: TextSpan): TextSpan | undefined; function textSpanIntersectsWithTextSpan(span: TextSpan, other: TextSpan): boolean; function textSpanIntersectsWith(span: TextSpan, start: number, length: number): boolean; function decodedTextSpanIntersectsWith(start1: number, length1: number, start2: number, length2: number): boolean; function textSpanIntersectsWithPosition(span: TextSpan, position: number): boolean; - function textSpanIntersection(span1: TextSpan, span2: TextSpan): TextSpan; + function textSpanIntersection(span1: TextSpan, span2: TextSpan): TextSpan | undefined; function createTextSpan(start: number, length: number): TextSpan; function createTextSpanFromBounds(start: number, end: number): TextSpan; function textChangeRangeNewSpan(range: TextChangeRange): TextSpan; @@ -3106,7 +3108,7 @@ declare namespace ts { * Vn. */ function collapseTextChangeRangesAcrossMultipleVersions(changes: ReadonlyArray): TextChangeRange; - function getTypeParameterOwner(d: Declaration): Declaration; + function getTypeParameterOwner(d: Declaration): Declaration | undefined; type ParameterPropertyDeclaration = ParameterDeclaration & { parent: ConstructorDeclaration; name: Identifier; @@ -3128,6 +3130,8 @@ declare namespace ts { }, errors?: Push): void; function getOriginalNode(node: Node): Node; function getOriginalNode(node: Node, nodeTest: (node: Node) => node is T): T; + function getOriginalNode(node: Node | undefined): Node | undefined; + function getOriginalNode(node: Node | undefined, nodeTest: (node: Node | undefined) => node is T): T | undefined; /** * Gets a value indicating whether a node originated in the parse tree. * @@ -3148,7 +3152,7 @@ declare namespace ts { * @param nodeTest A callback used to ensure the correct type of parse tree node is returned. * @returns The original parse tree node if found; otherwise, undefined. */ - function getParseTreeNode(node: Node, nodeTest?: (node: Node) => node is T): T; + function getParseTreeNode(node: Node | undefined, nodeTest?: (node: Node) => node is T): T | undefined; /** * Remove extra underscore from escaped identifier text content. * @@ -3166,7 +3170,7 @@ declare namespace ts { */ function unescapeIdentifier(id: string): string; function getNameOfJSDocTypedef(declaration: JSDocTypedefTag): Identifier | undefined; - function getNameOfDeclaration(declaration: Declaration | Expression): DeclarationName | undefined; + function getNameOfDeclaration(declaration: Declaration | Expression): DeclarationName; /** * Gets the JSDoc parameter tags for the node if present. * @@ -3448,7 +3452,7 @@ declare namespace ts { */ function forEachChild(node: Node, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined; function createSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, setParentNodes?: boolean, scriptKind?: ScriptKind): SourceFile; - function parseIsolatedEntityName(text: string, languageVersion: ScriptTarget): EntityName; + function parseIsolatedEntityName(text: string, languageVersion: ScriptTarget): EntityName | undefined; /** * Parse json text into SyntaxTree and return node and parse errors if any * @param fileName @@ -3494,7 +3498,7 @@ declare namespace ts { getOrCreateCacheForModuleName(nonRelativeModuleName: string): PerModuleNameCache; } interface PerModuleNameCache { - get(directory: string): ResolvedModuleWithFailedLookupLocations; + get(directory: string): ResolvedModuleWithFailedLookupLocations | undefined; set(directory: string, result: ResolvedModuleWithFailedLookupLocations): void; } function createModuleResolutionCache(currentDirectory: string, getCanonicalFileName: (s: string) => string): ModuleResolutionCache; @@ -3576,7 +3580,7 @@ declare namespace ts { function updateConstructorTypeNode(node: ConstructorTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): ConstructorTypeNode; function createTypeQueryNode(exprName: EntityName): TypeQueryNode; function updateTypeQueryNode(node: TypeQueryNode, exprName: EntityName): TypeQueryNode; - function createTypeLiteralNode(members: ReadonlyArray): TypeLiteralNode; + function createTypeLiteralNode(members: ReadonlyArray | undefined): TypeLiteralNode; function updateTypeLiteralNode(node: TypeLiteralNode, members: NodeArray): TypeLiteralNode; function createArrayTypeNode(elementType: TypeNode): ArrayTypeNode; function updateArrayTypeNode(node: ArrayTypeNode, elementType: TypeNode): ArrayTypeNode; @@ -3615,23 +3619,23 @@ declare namespace ts { function updateArrayLiteral(node: ArrayLiteralExpression, elements: ReadonlyArray): ArrayLiteralExpression; function createObjectLiteral(properties?: ReadonlyArray, multiLine?: boolean): ObjectLiteralExpression; function updateObjectLiteral(node: ObjectLiteralExpression, properties: ReadonlyArray): ObjectLiteralExpression; - function createPropertyAccess(expression: Expression, name: string | Identifier): PropertyAccessExpression; + function createPropertyAccess(expression: Expression, name: string | Identifier | undefined): PropertyAccessExpression; function updatePropertyAccess(node: PropertyAccessExpression, expression: Expression, name: Identifier): PropertyAccessExpression; function createElementAccess(expression: Expression, index: number | Expression): ElementAccessExpression; function updateElementAccess(node: ElementAccessExpression, expression: Expression, argumentExpression: Expression): ElementAccessExpression; - function createCall(expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray): CallExpression; + function createCall(expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray | undefined): CallExpression; function updateCall(node: CallExpression, expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray): CallExpression; function createNew(expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray | undefined): NewExpression; function updateNew(node: NewExpression, expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray | undefined): NewExpression; function createTaggedTemplate(tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; - function createTaggedTemplate(tag: Expression, typeArguments: ReadonlyArray, template: TemplateLiteral): TaggedTemplateExpression; + function createTaggedTemplate(tag: Expression, typeArguments: ReadonlyArray | undefined, template: TemplateLiteral): TaggedTemplateExpression; function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; - function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: ReadonlyArray, template: TemplateLiteral): TaggedTemplateExpression; + function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: ReadonlyArray | undefined, template: TemplateLiteral): TaggedTemplateExpression; function createTypeAssertion(type: TypeNode, expression: Expression): TypeAssertion; function updateTypeAssertion(node: TypeAssertion, type: TypeNode, expression: Expression): TypeAssertion; function createParen(expression: Expression): ParenthesizedExpression; function updateParen(node: ParenthesizedExpression, expression: Expression): ParenthesizedExpression; - function createFunctionExpression(modifiers: ReadonlyArray | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: ReadonlyArray | undefined, parameters: ReadonlyArray, type: TypeNode | undefined, body: Block): FunctionExpression; + function createFunctionExpression(modifiers: ReadonlyArray | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: ReadonlyArray | undefined, parameters: ReadonlyArray | undefined, type: TypeNode | undefined, body: Block): FunctionExpression; function updateFunctionExpression(node: FunctionExpression, modifiers: ReadonlyArray | undefined, asteriskToken: AsteriskToken | undefined, name: Identifier | undefined, typeParameters: ReadonlyArray | undefined, parameters: ReadonlyArray, type: TypeNode | undefined, body: Block): FunctionExpression; function createArrowFunction(modifiers: ReadonlyArray | undefined, typeParameters: ReadonlyArray | undefined, parameters: ReadonlyArray, type: TypeNode | undefined, equalsGreaterThanToken: EqualsGreaterThanToken | undefined, body: ConciseBody): ArrowFunction; function updateArrowFunction(node: ArrowFunction, modifiers: ReadonlyArray | undefined, typeParameters: ReadonlyArray | undefined, parameters: ReadonlyArray, type: TypeNode | undefined, body: ConciseBody): ArrowFunction; @@ -3661,15 +3665,15 @@ declare namespace ts { function createTemplateTail(text: string): TemplateTail; function createNoSubstitutionTemplateLiteral(text: string): NoSubstitutionTemplateLiteral; function createYield(expression?: Expression): YieldExpression; - function createYield(asteriskToken: AsteriskToken, expression: Expression): YieldExpression; + function createYield(asteriskToken: AsteriskToken | undefined, expression: Expression): YieldExpression; function updateYield(node: YieldExpression, asteriskToken: AsteriskToken | undefined, expression: Expression): YieldExpression; function createSpread(expression: Expression): SpreadElement; function updateSpread(node: SpreadElement, expression: Expression): SpreadElement; - function createClassExpression(modifiers: ReadonlyArray | undefined, name: string | Identifier | undefined, typeParameters: ReadonlyArray | undefined, heritageClauses: ReadonlyArray, members: ReadonlyArray): ClassExpression; - function updateClassExpression(node: ClassExpression, modifiers: ReadonlyArray | undefined, name: Identifier | undefined, typeParameters: ReadonlyArray | undefined, heritageClauses: ReadonlyArray, members: ReadonlyArray): ClassExpression; + function createClassExpression(modifiers: ReadonlyArray | undefined, name: string | Identifier | undefined, typeParameters: ReadonlyArray | undefined, heritageClauses: ReadonlyArray | undefined, members: ReadonlyArray): ClassExpression; + function updateClassExpression(node: ClassExpression, modifiers: ReadonlyArray | undefined, name: Identifier | undefined, typeParameters: ReadonlyArray | undefined, heritageClauses: ReadonlyArray | undefined, members: ReadonlyArray): ClassExpression; function createOmittedExpression(): OmittedExpression; - function createExpressionWithTypeArguments(typeArguments: ReadonlyArray, expression: Expression): ExpressionWithTypeArguments; - function updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, typeArguments: ReadonlyArray, expression: Expression): ExpressionWithTypeArguments; + function createExpressionWithTypeArguments(typeArguments: ReadonlyArray | undefined, expression: Expression): ExpressionWithTypeArguments; + function updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, typeArguments: ReadonlyArray | undefined, expression: Expression): ExpressionWithTypeArguments; function createAsExpression(expression: Expression, type: TypeNode): AsExpression; function updateAsExpression(node: AsExpression, expression: Expression, type: TypeNode): AsExpression; function createNonNullExpression(expression: Expression): NonNullExpression; @@ -3696,8 +3700,8 @@ declare namespace ts { function updateFor(node: ForStatement, initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement): ForStatement; function createForIn(initializer: ForInitializer, expression: Expression, statement: Statement): ForInStatement; function updateForIn(node: ForInStatement, initializer: ForInitializer, expression: Expression, statement: Statement): ForInStatement; - function createForOf(awaitModifier: AwaitKeywordToken, initializer: ForInitializer, expression: Expression, statement: Statement): ForOfStatement; - function updateForOf(node: ForOfStatement, awaitModifier: AwaitKeywordToken, initializer: ForInitializer, expression: Expression, statement: Statement): ForOfStatement; + function createForOf(awaitModifier: AwaitKeywordToken | undefined, initializer: ForInitializer, expression: Expression, statement: Statement): ForOfStatement; + function updateForOf(node: ForOfStatement, awaitModifier: AwaitKeywordToken | undefined, initializer: ForInitializer, expression: Expression, statement: Statement): ForOfStatement; function createContinue(label?: string | Identifier): ContinueStatement; function updateContinue(node: ContinueStatement, label: Identifier | undefined): ContinueStatement; function createBreak(label?: string | Identifier): BreakStatement; @@ -3721,8 +3725,8 @@ declare namespace ts { function updateVariableDeclarationList(node: VariableDeclarationList, declarations: ReadonlyArray): VariableDeclarationList; function createFunctionDeclaration(decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: ReadonlyArray | undefined, parameters: ReadonlyArray, type: TypeNode | undefined, body: Block | undefined): FunctionDeclaration; function updateFunctionDeclaration(node: FunctionDeclaration, decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, asteriskToken: AsteriskToken | undefined, name: Identifier | undefined, typeParameters: ReadonlyArray | undefined, parameters: ReadonlyArray, type: TypeNode | undefined, body: Block | undefined): FunctionDeclaration; - function createClassDeclaration(decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, name: string | Identifier | undefined, typeParameters: ReadonlyArray | undefined, heritageClauses: ReadonlyArray, members: ReadonlyArray): ClassDeclaration; - function updateClassDeclaration(node: ClassDeclaration, decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, name: Identifier | undefined, typeParameters: ReadonlyArray | undefined, heritageClauses: ReadonlyArray, members: ReadonlyArray): ClassDeclaration; + function createClassDeclaration(decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, name: string | Identifier | undefined, typeParameters: ReadonlyArray | undefined, heritageClauses: ReadonlyArray | undefined, members: ReadonlyArray): ClassDeclaration; + function updateClassDeclaration(node: ClassDeclaration, decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, name: Identifier | undefined, typeParameters: ReadonlyArray | undefined, heritageClauses: ReadonlyArray | undefined, members: ReadonlyArray): ClassDeclaration; function createInterfaceDeclaration(decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, name: string | Identifier, typeParameters: ReadonlyArray | undefined, heritageClauses: ReadonlyArray | undefined, members: ReadonlyArray): InterfaceDeclaration; function updateInterfaceDeclaration(node: InterfaceDeclaration, decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, name: Identifier, typeParameters: ReadonlyArray | undefined, heritageClauses: ReadonlyArray | undefined, members: ReadonlyArray): InterfaceDeclaration; function createTypeAliasDeclaration(decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, name: string | Identifier, typeParameters: ReadonlyArray | undefined, type: TypeNode): TypeAliasDeclaration; @@ -3740,7 +3744,7 @@ declare namespace ts { function createImportEqualsDeclaration(decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, name: string | Identifier, moduleReference: ModuleReference): ImportEqualsDeclaration; function updateImportEqualsDeclaration(node: ImportEqualsDeclaration, decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, name: Identifier, moduleReference: ModuleReference): ImportEqualsDeclaration; function createImportDeclaration(decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression): ImportDeclaration; - function updateImportDeclaration(node: ImportDeclaration, decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression | undefined): ImportDeclaration; + function updateImportDeclaration(node: ImportDeclaration, decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression): ImportDeclaration; function createImportClause(name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause; function updateImportClause(node: ImportClause, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause; function createNamespaceImport(name: Identifier): NamespaceImport; @@ -3749,7 +3753,7 @@ declare namespace ts { function updateNamedImports(node: NamedImports, elements: ReadonlyArray): NamedImports; function createImportSpecifier(propertyName: Identifier | undefined, name: Identifier): ImportSpecifier; function updateImportSpecifier(node: ImportSpecifier, propertyName: Identifier | undefined, name: Identifier): ImportSpecifier; - function createExportAssignment(decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, isExportEquals: boolean, expression: Expression): ExportAssignment; + function createExportAssignment(decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, isExportEquals: boolean | undefined, expression: Expression): ExportAssignment; function updateExportAssignment(node: ExportAssignment, decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, expression: Expression): ExportAssignment; function createExportDeclaration(decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, exportClause: NamedExports | undefined, moduleSpecifier?: Expression): ExportDeclaration; function updateExportDeclaration(node: ExportDeclaration, decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, exportClause: NamedExports | undefined, moduleSpecifier: Expression | undefined): ExportDeclaration; @@ -3879,16 +3883,16 @@ declare namespace ts { */ function setCommentRange(node: T, range: TextRange): T; function getSyntheticLeadingComments(node: Node): SynthesizedComment[] | undefined; - function setSyntheticLeadingComments(node: T, comments: SynthesizedComment[]): T; + function setSyntheticLeadingComments(node: T, comments: SynthesizedComment[] | undefined): T; function addSyntheticLeadingComment(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean): T; function getSyntheticTrailingComments(node: Node): SynthesizedComment[] | undefined; - function setSyntheticTrailingComments(node: T, comments: SynthesizedComment[]): T; + function setSyntheticTrailingComments(node: T, comments: SynthesizedComment[] | undefined): T; function addSyntheticTrailingComment(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean): T; function moveSyntheticComments(node: T, original: Node): T; /** * Gets the constant value to emit for an expression. */ - function getConstantValue(node: PropertyAccessExpression | ElementAccessExpression): string | number; + function getConstantValue(node: PropertyAccessExpression | ElementAccessExpression): string | number | undefined; /** * Sets the constant value to emit for an expression. */ @@ -3924,7 +3928,7 @@ declare namespace ts { * @param test A callback to execute to verify the Node is valid. * @param lift An optional callback to execute to lift a NodeArray into a valid Node. */ - function visitNode(node: T, visitor: Visitor, test?: (node: Node) => boolean, lift?: (node: NodeArray) => T): T; + function visitNode(node: T | undefined, visitor: Visitor | undefined, test?: (node: Node) => boolean, lift?: (node: NodeArray) => T): T; /** * Visits a Node using the supplied visitor, possibly returning a new Node in its place. * @@ -3933,7 +3937,7 @@ declare namespace ts { * @param test A callback to execute to verify the Node is valid. * @param lift An optional callback to execute to lift a NodeArray into a valid Node. */ - function visitNode(node: T | undefined, visitor: Visitor, test?: (node: Node) => boolean, lift?: (node: NodeArray) => T): T | undefined; + function visitNode(node: T | undefined, visitor: Visitor | undefined, test?: (node: Node) => boolean, lift?: (node: NodeArray) => T): T | undefined; /** * Visits a NodeArray using the supplied visitor, possibly returning a new NodeArray in its place. * @@ -3943,7 +3947,7 @@ declare namespace ts { * @param start An optional value indicating the starting offset at which to start visiting. * @param count An optional value indicating the maximum number of nodes to visit. */ - function visitNodes(nodes: NodeArray, visitor: Visitor, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray; + function visitNodes(nodes: NodeArray | undefined, visitor: Visitor, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray; /** * Visits a NodeArray using the supplied visitor, possibly returning a new NodeArray in its place. * @@ -3963,7 +3967,7 @@ declare namespace ts { * Starts a new lexical environment and visits a parameter list, suspending the lexical * environment upon completion. */ - function visitParameterList(nodes: NodeArray, visitor: Visitor, context: TransformationContext, nodesVisitor?: typeof visitNodes): NodeArray; + function visitParameterList(nodes: NodeArray | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: typeof visitNodes): NodeArray; /** * Resumes a suspended lexical environment and visits a function body, ending the lexical * environment and merging hoisted declarations upon completion. @@ -4012,7 +4016,7 @@ declare namespace ts { function formatDiagnostics(diagnostics: ReadonlyArray, host: FormatDiagnosticsHost): string; function formatDiagnostic(diagnostic: Diagnostic, host: FormatDiagnosticsHost): string; function formatDiagnosticsWithColorAndContext(diagnostics: ReadonlyArray, host: FormatDiagnosticsHost): string; - function flattenDiagnosticMessageText(messageText: string | DiagnosticMessageChain, newLine: string): string; + function flattenDiagnosticMessageText(messageText: string | DiagnosticMessageChain | undefined, newLine: string): string; function getConfigFileParsingDiagnostics(configFileParseResult: ParsedCommandLine): ReadonlyArray; /** * Create a new 'Program' instance. A Program is an immutable collection of 'SourceFile's and a 'CompilerOptions' @@ -4207,11 +4211,11 @@ declare namespace ts { /** If provided would be used to write log about compilation */ trace?(s: string): void; /** If provided is used to get the environment variable */ - getEnvironmentVariable?(name: string): string; + getEnvironmentVariable?(name: string): string | undefined; /** If provided, used to resolve the module names, otherwise typescript's default module resolution */ resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[]): ResolvedModule[]; /** If provided, used to resolve type reference directives, otherwise typescript's default resolution */ - resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): (ResolvedTypeReferenceDirective | undefined)[]; + resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[]; /** Used to watch changes in source files, missing files needed to update the program or config file */ watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher; /** Used to watch resolved module's failed lookup locations, config file specs, type roots where auto type reference directives are added */ @@ -4361,8 +4365,8 @@ declare namespace ts { getLeadingTriviaWidth(sourceFile?: SourceFile): number; getFullText(sourceFile?: SourceFile): string; getText(sourceFile?: SourceFile): string; - getFirstToken(sourceFile?: SourceFile): Node; - getLastToken(sourceFile?: SourceFile): Node; + getFirstToken(sourceFile?: SourceFile): Node | undefined; + getLastToken(sourceFile?: SourceFile): Node | undefined; forEachChild(cbNode: (node: Node) => T | undefined, cbNodeArray?: (nodes: NodeArray) => T | undefined): T | undefined; } interface Identifier { @@ -4450,7 +4454,7 @@ declare namespace ts { referencedFiles: FileReference[]; typeReferenceDirectives: FileReference[]; importedFiles: FileReference[]; - ambientExternalModules: string[]; + ambientExternalModules?: string[]; isLibFile: boolean; } interface HostCancellationToken { @@ -4483,7 +4487,7 @@ declare namespace ts { fileExists?(path: string): boolean; getTypeRootsVersion?(): number; resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[]): ResolvedModule[]; - getResolvedModuleWithFailedLookupLocationsFromCache?(modulename: string, containingFile: string): ResolvedModuleWithFailedLookupLocations; + getResolvedModuleWithFailedLookupLocationsFromCache?(modulename: string, containingFile: string): ResolvedModuleWithFailedLookupLocations | undefined; resolveTypeReferenceDirectives?(typeDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[]; getDirectories?(directoryName: string): string[]; /** @@ -4518,24 +4522,24 @@ declare namespace ts { getSemanticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[]; getEncodedSyntacticClassifications(fileName: string, span: TextSpan): Classifications; getEncodedSemanticClassifications(fileName: string, span: TextSpan): Classifications; - getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions | undefined): CompletionInfo; - getCompletionEntryDetails(fileName: string, position: number, name: string, formatOptions: FormatCodeOptions | FormatCodeSettings | undefined, source: string | undefined, preferences: UserPreferences | undefined): CompletionEntryDetails; - getCompletionEntrySymbol(fileName: string, position: number, name: string, source: string | undefined): Symbol; - getQuickInfoAtPosition(fileName: string, position: number): QuickInfo; - getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan; - getBreakpointStatementAtPosition(fileName: string, position: number): TextSpan; - getSignatureHelpItems(fileName: string, position: number): SignatureHelpItems; + getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions | undefined): CompletionInfo | undefined; + getCompletionEntryDetails(fileName: string, position: number, name: string, formatOptions: FormatCodeOptions | FormatCodeSettings | undefined, source: string | undefined, preferences: UserPreferences | undefined): CompletionEntryDetails | undefined; + getCompletionEntrySymbol(fileName: string, position: number, name: string, source: string | undefined): Symbol | undefined; + getQuickInfoAtPosition(fileName: string, position: number): QuickInfo | undefined; + getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan | undefined; + getBreakpointStatementAtPosition(fileName: string, position: number): TextSpan | undefined; + getSignatureHelpItems(fileName: string, position: number): SignatureHelpItems | undefined; getRenameInfo(fileName: string, position: number): RenameInfo; - findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[]; - getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[]; - getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan; - getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[]; - getImplementationAtPosition(fileName: string, position: number): ImplementationLocation[]; - getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[]; - findReferences(fileName: string, position: number): ReferencedSymbol[]; - getDocumentHighlights(fileName: string, position: number, filesToSearch: string[]): DocumentHighlights[]; + findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[] | undefined; + getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] | undefined; + getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan | undefined; + getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] | undefined; + getImplementationAtPosition(fileName: string, position: number): ImplementationLocation[] | undefined; + getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] | undefined; + findReferences(fileName: string, position: number): ReferencedSymbol[] | undefined; + getDocumentHighlights(fileName: string, position: number, filesToSearch: string[]): DocumentHighlights[] | undefined; /** @deprecated */ - getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[]; + getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[] | undefined; getNavigateToItems(searchValue: string, maxResultCount?: number, fileName?: string, excludeDtsFiles?: boolean): NavigateToItem[]; getNavigationBarItems(fileName: string): NavigationBarItem[]; getNavigationTree(fileName: string): NavigationTree; @@ -4546,9 +4550,9 @@ declare namespace ts { getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions | FormatCodeSettings): TextChange[]; getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[]; getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[]; - getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion; + getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion | undefined; isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean; - getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan; + getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan | undefined; toLineColumnOffset?(fileName: string, position: number): LineAndCharacter; getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: ReadonlyArray, formatOptions: FormatCodeSettings, preferences: UserPreferences): ReadonlyArray; getCombinedCodeFix(scope: CombinedCodeFixScope, fixId: {}, formatOptions: FormatCodeSettings, preferences: UserPreferences): CombinedCodeActions; @@ -4566,7 +4570,7 @@ declare namespace ts { organizeImports(scope: OrganizeImportsScope, formatOptions: FormatCodeSettings, preferences: UserPreferences | undefined): ReadonlyArray; getEditsForFileRename(oldFilePath: string, newFilePath: string, formatOptions: FormatCodeSettings): ReadonlyArray; getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean): EmitOutput; - getProgram(): Program; + getProgram(): Program | undefined; dispose(): void; } interface CombinedCodeFixScope { @@ -4669,7 +4673,7 @@ declare namespace ts { } interface CombinedCodeActions { changes: ReadonlyArray; - commands: ReadonlyArray | undefined; + commands?: ReadonlyArray; } type CodeActionCommand = InstallPackageAction; interface InstallPackageAction { @@ -4719,8 +4723,8 @@ declare namespace ts { */ interface RefactorEditInfo { edits: FileTextChanges[]; - renameFilename: string | undefined; - renameLocation: number | undefined; + renameFilename?: string; + renameLocation?: number; commands?: CodeActionCommand[]; } interface TextInsertion { @@ -4841,7 +4845,7 @@ declare namespace ts { containerName: string; } interface DefinitionInfoAndBoundSpan { - definitions: ReadonlyArray; + definitions?: ReadonlyArray; textSpan: TextSpan; } interface ReferencedSymbolDefinitionInfo extends DefinitionInfo { @@ -4887,13 +4891,13 @@ declare namespace ts { kind: ScriptElementKind; kindModifiers: string; textSpan: TextSpan; - displayParts: SymbolDisplayPart[]; - documentation: SymbolDisplayPart[]; - tags: JSDocTagInfo[]; + displayParts?: SymbolDisplayPart[]; + documentation?: SymbolDisplayPart[]; + tags?: JSDocTagInfo[]; } interface RenameInfo { canRename: boolean; - localizedErrorMessage: string; + localizedErrorMessage?: string; displayName: string; fullDisplayName: string; kind: ScriptElementKind; @@ -4945,7 +4949,7 @@ declare namespace ts { interface CompletionEntry { name: string; kind: ScriptElementKind; - kindModifiers: string; + kindModifiers?: string; sortText: string; insertText?: string; /** @@ -4963,8 +4967,8 @@ declare namespace ts { kind: ScriptElementKind; kindModifiers: string; displayParts: SymbolDisplayPart[]; - documentation: SymbolDisplayPart[]; - tags: JSDocTagInfo[]; + documentation?: SymbolDisplayPart[]; + tags?: JSDocTagInfo[]; codeActions?: CodeAction[]; source?: SymbolDisplayPart[]; } @@ -5277,12 +5281,12 @@ declare namespace ts { /** The version of the language service API */ const servicesVersion = "0.8"; function toEditorSettings(options: EditorOptions | EditorSettings): EditorSettings; - function displayPartsToString(displayParts: SymbolDisplayPart[]): string; + function displayPartsToString(displayParts: SymbolDisplayPart[] | undefined): string; function getDefaultCompilerOptions(): CompilerOptions; function getSupportedCodeFixes(): string[]; function createLanguageServiceSourceFile(fileName: string, scriptSnapshot: IScriptSnapshot, scriptTarget: ScriptTarget, version: string, setNodeParents: boolean, scriptKind?: ScriptKind): SourceFile; let disableIncrementalParsing: boolean; - function updateLanguageServiceSourceFile(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile; + function updateLanguageServiceSourceFile(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string, textChangeRange: TextChangeRange | undefined, aggressiveChecks?: boolean): SourceFile; function createLanguageService(host: LanguageServiceHost, documentRegistry?: DocumentRegistry, syntaxOnly?: boolean): LanguageService; /** * Get the path of the default library files (lib.d.ts) as distributed with the typescript diff --git a/tslint.json b/tslint.json index a0756e63a2d3e..a3ca10e75edbc 100644 --- a/tslint.json +++ b/tslint.json @@ -2,7 +2,7 @@ "extends": "tslint:latest", "rulesDirectory": "built/local/tslint/rules", "rules": { - "no-unnecessary-type-assertion-2": true, + "no-unnecessary-type-assertion": true, "array-type": [true, "array"], "ban-types": {