From 8deee1184b315b4536dc64df6f88a5b59ea56925 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Wed, 21 Feb 2018 10:48:14 -0800 Subject: [PATCH 01/42] Enable '--strictNullChecks' --- .../rules/noUnnecessaryTypeAssertion2Rule.ts | 98 - src/compiler/binder.ts | 176 +- src/compiler/builder.ts | 63 +- src/compiler/builderState.ts | 24 +- src/compiler/checker.ts | 2572 +++++++++-------- src/compiler/commandLineParser.ts | 67 +- src/compiler/comments.ts | 28 +- src/compiler/core.ts | 224 +- src/compiler/declarationEmitter.ts | 142 +- src/compiler/emitter.ts | 144 +- src/compiler/factory.ts | 156 +- src/compiler/moduleNameResolver.ts | 55 +- src/compiler/parser.ts | 176 +- src/compiler/performance.ts | 2 +- src/compiler/program.ts | 215 +- src/compiler/resolutionCache.ts | 30 +- src/compiler/scanner.ts | 59 +- src/compiler/sourcemap.ts | 56 +- src/compiler/symbolWalker.ts | 15 +- src/compiler/sys.ts | 16 +- src/compiler/transformer.ts | 28 +- src/compiler/transformers/destructuring.ts | 52 +- src/compiler/transformers/es2015.ts | 267 +- src/compiler/transformers/es2016.ts | 4 +- src/compiler/transformers/es2017.ts | 31 +- src/compiler/transformers/es5.ts | 4 +- src/compiler/transformers/esnext.ts | 44 +- src/compiler/transformers/generators.ts | 154 +- src/compiler/transformers/jsx.ts | 16 +- src/compiler/transformers/module/es2015.ts | 4 +- src/compiler/transformers/module/module.ts | 44 +- src/compiler/transformers/module/system.ts | 78 +- src/compiler/transformers/ts.ts | 106 +- src/compiler/transformers/utilities.ts | 22 +- src/compiler/types.ts | 249 +- src/compiler/utilities.ts | 315 +- src/compiler/visitor.ts | 78 +- src/compiler/watch.ts | 91 +- src/compiler/watchUtilities.ts | 19 +- src/harness/compilerRunner.ts | 26 +- src/harness/externalCompileRunner.ts | 4 +- src/harness/fourslash.ts | 191 +- src/harness/harness.ts | 115 +- src/harness/harnessLanguageService.ts | 39 +- src/harness/loggedIO.ts | 75 +- src/harness/parallel/host.ts | 24 +- src/harness/parallel/worker.ts | 30 +- src/harness/projectsRunner.ts | 64 +- src/harness/runner.ts | 13 +- src/harness/rwcRunner.ts | 28 +- src/harness/sourceMapRecorder.ts | 29 +- src/harness/test262Runner.ts | 10 +- src/harness/typeWriter.ts | 6 +- src/harness/unittests/builder.ts | 2 +- src/harness/unittests/compileOnSave.ts | 6 +- .../convertTypeAcquisitionFromJson.ts | 6 +- src/harness/unittests/customTransforms.ts | 2 +- src/harness/unittests/extractRanges.ts | 13 +- src/harness/unittests/extractTestHelpers.ts | 18 +- src/harness/unittests/hostNewLineSupport.ts | 2 +- src/harness/unittests/jsDocParsing.ts | 8 +- src/harness/unittests/moduleResolution.ts | 21 +- src/harness/unittests/organizeImports.ts | 2 +- src/harness/unittests/programMissingFiles.ts | 4 +- src/harness/unittests/projectErrors.ts | 12 +- src/harness/unittests/publicApi.ts | 2 +- .../unittests/reuseProgramStructure.ts | 30 +- .../unittests/services/colorization.ts | 6 +- .../unittests/services/patternMatcher.ts | 104 +- src/harness/unittests/session.ts | 16 +- src/harness/unittests/symbolWalker.ts | 11 +- src/harness/unittests/textChanges.ts | 10 +- src/harness/unittests/transform.ts | 2 +- src/harness/unittests/transpile.ts | 10 +- src/harness/unittests/tscWatchMode.ts | 26 +- .../unittests/tsserverProjectSystem.ts | 135 +- src/harness/unittests/typingsInstaller.ts | 14 +- src/harness/unittests/versionCache.ts | 32 +- src/harness/virtualFileSystem.ts | 22 +- src/harness/virtualFileSystemWithWatch.ts | 30 +- .../cancellationToken/cancellationToken.ts | 6 +- src/server/client.ts | 104 +- src/server/editorServices.ts | 119 +- src/server/project.ts | 86 +- src/server/protocol.ts | 8 +- src/server/scriptInfo.ts | 24 +- src/server/scriptVersionCache.ts | 23 +- src/server/server.ts | 35 +- src/server/session.ts | 252 +- src/server/typingsCache.ts | 16 +- .../typingsInstaller/nodeTypingsInstaller.ts | 8 +- .../typingsInstaller/typingsInstaller.ts | 18 +- src/server/utilities.ts | 16 +- src/services/breakpoints.ts | 91 +- src/services/classifier.ts | 33 +- src/services/codeFixProvider.ts | 2 +- ...correctQualifiedNameToIndexedAccessType.ts | 4 +- src/services/codefixes/fixAddMissingMember.ts | 12 +- .../codefixes/fixAwaitInSyncFunction.ts | 8 +- src/services/codefixes/fixCannotFindModule.ts | 6 +- ...sDoesntImplementInheritedAbstractMember.ts | 6 +- .../fixClassIncorrectlyImplementsInterface.ts | 8 +- .../fixClassSuperMustPrecedeThisAccess.ts | 4 +- .../fixConstructorForDerivedNeedSuperCall.ts | 2 +- .../fixExtendsInterfaceBecomesImplements.ts | 8 +- .../fixForgottenThisPropertyAccess.ts | 2 +- .../codefixes/fixInvalidImportSyntax.ts | 4 +- src/services/codefixes/fixJSDocTypes.ts | 4 +- src/services/codefixes/fixSpelling.ts | 4 +- src/services/codefixes/fixUnusedIdentifier.ts | 14 +- src/services/codefixes/helpers.ts | 22 +- src/services/codefixes/importFixes.ts | 50 +- src/services/codefixes/inferFromUsage.ts | 47 +- src/services/completions.ts | 186 +- src/services/documentHighlights.ts | 48 +- src/services/documentRegistry.ts | 10 +- src/services/findAllReferences.ts | 126 +- src/services/formatting/formatting.ts | 61 +- src/services/formatting/formattingContext.ts | 10 +- src/services/formatting/formattingScanner.ts | 4 +- src/services/formatting/rules.ts | 2 +- src/services/formatting/smartIndenter.ts | 30 +- src/services/goToDefinition.ts | 41 +- src/services/importTracker.ts | 78 +- src/services/jsDoc.ts | 10 +- src/services/jsTyping.ts | 14 +- src/services/navigateTo.ts | 20 +- src/services/navigationBar.ts | 27 +- src/services/organizeImports.ts | 4 +- src/services/pathCompletions.ts | 28 +- src/services/patternMatcher.ts | 24 +- src/services/preProcess.ts | 6 +- .../refactors/annotateWithTypeFromJSDoc.ts | 18 +- .../refactors/convertFunctionToEs6Class.ts | 19 +- src/services/refactors/convertToEs6Module.ts | 23 +- src/services/refactors/extractSymbol.ts | 137 +- src/services/refactors/useDefaultImport.ts | 15 +- src/services/rename.ts | 13 +- src/services/services.ts | 168 +- src/services/shims.ts | 52 +- src/services/signatureHelp.ts | 46 +- src/services/symbolDisplay.ts | 64 +- src/services/textChanges.ts | 32 +- src/services/transform.ts | 2 +- src/services/transpile.ts | 8 +- src/services/types.ts | 62 +- src/services/utilities.ts | 62 +- src/tsconfig-base.json | 1 + .../reference/api/tsserverlibrary.d.ts | 310 +- tests/baselines/reference/api/typescript.d.ts | 300 +- tslint.json | 2 +- 151 files changed, 5171 insertions(+), 5062 deletions(-) delete mode 100644 scripts/tslint/rules/noUnnecessaryTypeAssertion2Rule.ts 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 782363dd6dfc8..e807f6728fc8e 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -126,13 +126,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 @@ -182,22 +182,22 @@ namespace ts { file.classifiableNames = classifiableNames; } - file = undefined; - options = undefined; - languageVersion = undefined; - parent = undefined; - container = undefined; - blockScopeContainer = undefined; - inferenceContainer = undefined; - lastContainer = undefined; + file = undefined!; + options = undefined!; + languageVersion = undefined!; + parent = undefined!; + container = undefined!; + blockScopeContainer = undefined!; + inferenceContainer = undefined!; + lastContainer = 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; @@ -252,7 +252,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; } @@ -315,7 +315,7 @@ namespace ts { } function getDisplayName(node: Declaration): string { - return (node as NamedDeclaration).name ? declarationNameToString((node as NamedDeclaration).name) : unescapeLeadingUnderscores(getDeclarationName(node)); + return isNamedDeclaration(node) ? declarationNameToString(node.name) : unescapeLeadingUnderscores(getDeclarationName(node)!); // TODO: GH#18217 } /** @@ -326,7 +326,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); @@ -334,7 +334,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); } @@ -383,8 +383,8 @@ namespace ts { symbolTable.set(name, symbol = createSymbol(SymbolFlags.None, name)); } else { - if ((node as NamedDeclaration).name) { - (node as NamedDeclaration).name.parent = node; + if (isNamedDeclaration(node)) { + node.name.parent = node; } // Report errors every position with duplicate declaration @@ -436,10 +436,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 { @@ -462,13 +462,13 @@ namespace ts { const isJSDocTypedefInJSDocNamespace = isJSDocTypedefTag(node) && node.name && node.name.kind === SyntaxKind.Identifier && node.name.isInJSDocNamespace; if ((!isAmbientModule(node) && (hasExportModifier || container.flags & NodeFlags.ExportContext)) || isJSDocTypedefInJSDocNamespace) { 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); } } } @@ -544,6 +544,7 @@ namespace ts { if (node.kind === SyntaxKind.SourceFile) { node.flags |= emitFlags; } + if (currentReturnTarget) { addAntecedent(currentReturnTarget, currentFlow); currentFlow = finishFlowLabel(currentReturnTarget); @@ -583,11 +584,11 @@ namespace ts { if (skipTransformFlagAggregation) { bindChildrenWorker(node); } - else if (node.transformFlags & TransformFlags.HasComputedFlags) { + else if (node.transformFlags! & TransformFlags.HasComputedFlags) { skipTransformFlagAggregation = true; bindChildrenWorker(node); skipTransformFlagAggregation = false; - subtreeTransformFlags |= node.transformFlags & ~getTransformFlagsSubtreeExclusions(node.kind); + subtreeTransformFlags |= node.transformFlags! & ~getTransformFlagsSubtreeExclusions(node.kind); } else { const savedSubtreeTransformFlags = subtreeTransformFlags; @@ -597,7 +598,7 @@ namespace ts { } } - function bindEach(nodes: NodeArray) { + function bindEach(nodes: NodeArray | undefined): void { if (nodes === undefined) { return; } @@ -611,7 +612,7 @@ namespace ts { let nodeArrayFlags = TransformFlags.None; for (const node of nodes) { bind(node); - nodeArrayFlags |= node.transformFlags & ~TransformFlags.HasComputedFlags; + nodeArrayFlags |= node.transformFlags! & ~TransformFlags.HasComputedFlags; } nodes.transformFlags = nodeArrayFlags | TransformFlags.HasComputedFlags; subtreeTransformFlags |= savedSubtreeTransformFlags; @@ -628,12 +629,12 @@ namespace ts { // container or not. 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); } } @@ -825,7 +826,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; } @@ -912,7 +913,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; @@ -1037,7 +1038,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); @@ -1167,7 +1168,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]; @@ -1183,7 +1185,7 @@ namespace ts { function bindCaseClause(node: CaseClause): void { const saveCurrentFlow = currentFlow; - currentFlow = preSwitchCaseFlow; + currentFlow = preSwitchCaseFlow!; bind(node.expression); currentFlow = saveCurrentFlow; bindEach(node.statements); @@ -1201,7 +1203,7 @@ namespace ts { } function popActiveLabel() { - activeLabels.pop(); + activeLabels!.pop(); } function bindLabeledStatement(node: LabeledStatement): void { @@ -1248,7 +1250,7 @@ namespace ts { else if (node.kind === SyntaxKind.ObjectLiteralExpression) { for (const p of (node).properties) { if (p.kind === SyntaxKind.PropertyAssignment) { - bindDestructuringTargetFlow(p.initializer); + bindDestructuringTargetFlow(p.initializer!); } else if (p.kind === SyntaxKind.ShorthandPropertyAssignment) { bindAssignmentTargetFlow(p.name); @@ -1306,7 +1308,7 @@ namespace ts { currentFlow = finishFlowLabel(postExpressionLabel); } else { - bindLogicalExpression(node, currentTrueTarget, currentFalseTarget); + bindLogicalExpression(node, currentTrueTarget!, currentFalseTarget!); } } else { @@ -1499,7 +1501,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 @@ -1516,7 +1518,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: @@ -1528,7 +1530,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: @@ -1552,20 +1554,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 { @@ -1612,7 +1614,7 @@ namespace ts { } } - const symbol = declareSymbolAndAddToSymbolTable(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes); + const symbol = declareSymbolAndAddToSymbolTable(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes)!; // TODO: GH#18217 Call 'declareModuleMember' directly if (pattern) { (file.patternAmbientModules || (file.patternAmbientModules = [])).push({ pattern, symbol }); @@ -1622,7 +1624,7 @@ namespace ts { else { const state = declareModuleSymbol(node); if (state !== ModuleInstanceState.NonInstantiated) { - const { symbol } = node; + const symbol = node.symbol!; // if module was already merged with some function, class or non-const enum, treat it as non-const-enum-only symbol.constEnumOnlyModule = (!(symbol.flags & (SymbolFlags.Function | SymbolFlags.Class | SymbolFlags.RegularEnum))) // Current must be `const enum` only @@ -1649,7 +1651,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); @@ -1747,8 +1749,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)) { @@ -1804,7 +1806,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)) { @@ -1868,7 +1870,7 @@ namespace ts { } function checkStrictModeNumericLiteral(node: NumericLiteral) { - if (inStrictMode && node.numericLiteralFlags & TokenFlags.Octal) { + if (inStrictMode && node.numericLiteralFlags! & TokenFlags.Octal) { file.bindDiagnostics.push(createDiagnosticForNode(node, Diagnostics.Octal_literals_are_not_allowed_in_strict_mode)); } } @@ -1904,7 +1906,7 @@ namespace ts { file.bindDiagnostics.push(createFileDiagnostic(file, span.start, span.length, message, arg0, arg1, arg2)); } - function bind(node: Node): void { + function bind(node: Node | undefined): void { if (!node) { return; } @@ -1950,7 +1952,7 @@ namespace ts { } parent = saveParent; } - else if (!skipTransformFlagAggregation && (node.transformFlags & TransformFlags.HasComputedFlags) === 0) { + else if (!skipTransformFlagAggregation && (node.transformFlags! & TransformFlags.HasComputedFlags) === 0) { subtreeTransformFlags |= computeTransformFlagsForNode(node, 0); } inStrictMode = saveInStrictMode; @@ -1961,7 +1963,7 @@ namespace ts { return; } - for (const jsDoc of node.jsDoc) { + for (const jsDoc of node.jsDoc!) { if (!jsDoc.tags) { continue; } @@ -2229,7 +2231,7 @@ namespace ts { function bindExportAssignment(node: ExportAssignment | BinaryExpression) { 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) @@ -2266,14 +2268,14 @@ namespace ts { } } - file.symbol.globalExports = file.symbol.globalExports || createSymbolTable(); - declareSymbol(file.symbol.globalExports, file.symbol, node, SymbolFlags.Alias, SymbolFlags.AliasExcludes); + file.symbol!.globalExports = file.symbol!.globalExports || createSymbolTable(); + declareSymbol(file.symbol!.globalExports!, file.symbol, node, SymbolFlags.Alias, SymbolFlags.AliasExcludes); } 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 @@ -2300,7 +2302,7 @@ namespace ts { // When we create a property via 'exports.foo = bar', the 'exports.foo' property access // expression is the declaration setCommonJsModuleIndicator(node); - declareSymbol(file.symbol.exports, file.symbol, node.left, SymbolFlags.Property | SymbolFlags.ExportValue, SymbolFlags.None); + declareSymbol(file.symbol!.exports!, file.symbol, node.left, SymbolFlags.Property | SymbolFlags.ExportValue, SymbolFlags.None); } function bindModuleExportsAssignment(node: BinaryExpression) { @@ -2317,7 +2319,7 @@ namespace ts { // 'module.exports = expr' assignment setCommonJsModuleIndicator(node); - declareSymbol(file.symbol.exports, file.symbol, node, SymbolFlags.Property | SymbolFlags.ExportValue | SymbolFlags.ValueModule, SymbolFlags.None); + declareSymbol(file.symbol!.exports!, file.symbol, node, SymbolFlags.Property | SymbolFlags.ExportValue | SymbolFlags.ValueModule, SymbolFlags.None); } function bindThisPropertyAssignment(node: BinaryExpression | PropertyAccessExpression) { @@ -2327,9 +2329,9 @@ namespace ts { case SyntaxKind.FunctionDeclaration: case SyntaxKind.FunctionExpression: // Declare a 'member' if the container is an ES5 class or ES6 constructor - container.symbol.members = container.symbol.members || createSymbolTable(); + container.symbol!.members = container.symbol!.members || createSymbolTable(); // It's acceptable for multiple 'this' assignments of the same identifier to occur - declareSymbol(container.symbol.members, container.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes & ~SymbolFlags.Property); + declareSymbol(container.symbol!.members!, container.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes & ~SymbolFlags.Property); break; case SyntaxKind.Constructor: @@ -2340,7 +2342,7 @@ namespace ts { // this.foo assignment in a JavaScript class // Bind this property to the containing class const containingClass = container.parent; - const symbolTable = hasModifier(container, ModifierFlags.Static) ? containingClass.symbol.exports : containingClass.symbol.members; + const symbolTable = hasModifier(container, ModifierFlags.Static) ? containingClass.symbol!.exports! : containingClass.symbol!.members!; declareSymbol(symbolTable, containingClass.symbol, node, SymbolFlags.Property, SymbolFlags.None, /*isReplaceableByMethod*/ true); break; } @@ -2409,7 +2411,7 @@ namespace ts { function bindPropertyAssignment(functionName: __String, propertyAccess: PropertyAccessExpression, isPrototypeProperty: boolean) { const symbol = lookupSymbolForName(functionName); let targetSymbol = symbol && isDeclarationOfFunctionOrClassExpression(symbol) ? - (symbol.valueDeclaration as VariableDeclaration).initializer.symbol : + (symbol.valueDeclaration as VariableDeclaration).initializer!.symbol : symbol; Debug.assert(propertyAccess.parent.kind === SyntaxKind.BinaryExpression || propertyAccess.parent.kind === SyntaxKind.ExpressionStatement); let isLegalPosition: boolean; @@ -2427,10 +2429,10 @@ namespace ts { const flags = SymbolFlags.Module | SymbolFlags.JSContainer; const excludeFlags = SymbolFlags.ValueModuleExcludes & ~SymbolFlags.JSContainer; if (targetSymbol) { - addDeclarationToSymbol(symbol, identifier, flags); + addDeclarationToSymbol(symbol!, identifier, flags); } else { - targetSymbol = declareSymbol(container.locals, /*parent*/ undefined, identifier, flags, excludeFlags); + targetSymbol = declareSymbol(container.locals!, /*parent*/ undefined, identifier, flags, excludeFlags); } } if (!targetSymbol || !(targetSymbol.flags & (SymbolFlags.Function | SymbolFlags.Class | SymbolFlags.NamespaceModule))) { @@ -2467,7 +2469,7 @@ namespace ts { } } - const symbol = node.symbol; + const symbol = node.symbol!; // TypeScript 1.0 spec (April 2014): 8.4 // Every class automatically contains a static property member named 'prototype', the @@ -2479,14 +2481,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))); + 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; } @@ -2541,7 +2543,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); } } @@ -2599,7 +2601,7 @@ namespace ts { declareSymbol(inferenceContainer.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 { @@ -2611,7 +2613,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 { @@ -2668,8 +2670,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 { @@ -2788,13 +2790,13 @@ namespace ts { } if (subtreeFlags & TransformFlags.ContainsSpread - || (expression.transformFlags & (TransformFlags.Super | TransformFlags.ContainsSuper))) { + || (expression.transformFlags! & (TransformFlags.Super | TransformFlags.ContainsSuper))) { // If the this node contains a SpreadExpression, or is a super call, then it is an ES6 // node. transformFlags |= TransformFlags.AssertES2015; // super property or element accesses could be inside lambdas, etc, and need a captured `this`, // while super keyword for super calls (indicated by TransformFlags.Super) does not (since it can only be top-level in a constructor) - if (expression.transformFlags & TransformFlags.ContainsSuper) { + if (expression.transformFlags! & TransformFlags.ContainsSuper) { transformFlags |= TransformFlags.ContainsLexicalThis; } } @@ -2902,7 +2904,7 @@ namespace ts { // If the expression of a ParenthesizedExpression is a destructuring assignment, // then the ParenthesizedExpression is a destructuring assignment. - if (expressionTransformFlags & TransformFlags.DestructuringAssignment) { + if (expressionTransformFlags! & TransformFlags.DestructuringAssignment) { transformFlags |= TransformFlags.DestructuringAssignment; } @@ -3245,7 +3247,7 @@ namespace ts { // If an ElementAccessExpression starts with a super keyword, then it is // ES6 syntax, and requires a lexical `this` binding. - if (expressionFlags & TransformFlags.Super) { + if (expressionFlags! & TransformFlags.Super) { transformFlags &= ~TransformFlags.Super; transformFlags |= TransformFlags.ContainsSuper; } @@ -3283,7 +3285,7 @@ namespace ts { else { transformFlags = subtreeFlags; - if (declarationListTransformFlags & TransformFlags.ContainsBindingPattern) { + if (declarationListTransformFlags! & TransformFlags.ContainsBindingPattern) { transformFlags |= TransformFlags.AssertES2015; } } @@ -3323,7 +3325,7 @@ namespace ts { // If the expression of an expression statement is a destructuring assignment, // then we treat the statement as ES6 so that we can indicate that we do not // need to hold on to the right-hand side. - if (node.expression.transformFlags & TransformFlags.DestructuringAssignment) { + if (node.expression.transformFlags! & TransformFlags.DestructuringAssignment) { transformFlags |= TransformFlags.AssertES2015; } @@ -3428,7 +3430,7 @@ namespace ts { break; case SyntaxKind.NumericLiteral: - if ((node).numericLiteralFlags & TokenFlags.BinaryOrOctalSpecifier) { + if ((node).numericLiteralFlags! & TokenFlags.BinaryOrOctalSpecifier) { transformFlags |= TransformFlags.AssertES2015; } break; diff --git a/src/compiler/builder.ts b/src/compiler/builder.ts index c2f816a4c7167..ef0d4566afc7a 100644 --- a/src/compiler/builder.ts +++ b/src/compiler/builder.ts @@ -5,6 +5,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 @@ -43,7 +44,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)); } /** @@ -58,45 +59,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); } } }); @@ -108,7 +109,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)); } /** @@ -122,25 +123,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; } @@ -163,7 +164,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(); } @@ -178,8 +179,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!++; } } @@ -197,7 +198,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; @@ -205,7 +206,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; } @@ -241,7 +242,7 @@ namespace ts { // Return same program if underlying program doesnt change let oldState = oldProgram && oldProgram.getState(); if (oldState && newProgram === oldState.program) { - newProgram = undefined; + newProgram = undefined!; // TODO: GH#18217 oldState = undefined; return oldProgram; } @@ -257,7 +258,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; @@ -326,8 +327,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; @@ -413,7 +414,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 581aa05f12c16..af6d2d2dc25ad 100644 --- a/src/compiler/builderState.ts +++ b/src/compiler/builderState.ts @@ -109,7 +109,7 @@ namespace ts.BuilderState { return; } - const fileName = resolvedTypeReferenceDirective.resolvedFileName; + const fileName = resolvedTypeReferenceDirective.resolvedFileName!; // TODO: GH#18217 const typeFilePath = toPath(fileName, sourceFileDirectory, getCanonicalFileName); addReferencedFile(typeFilePath); }); @@ -128,7 +128,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; } @@ -144,7 +144,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) { @@ -195,7 +195,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 { return false; } - const info = state.fileInfos.get(sourceFile.path); + const info = state.fileInfos.get(sourceFile.path)!; Debug.assert(!!info); const prevSignature = info.signature; @@ -225,7 +225,7 @@ namespace ts.BuilderState { latestSignature = computeHash(emitOutput.outputFiles[0].text); } else { - latestSignature = prevSignature; + latestSignature = prevSignature!; // TODO: GH#18217 } } cacheToUpdateSignature.set(sourceFile.path, latestSignature); @@ -252,7 +252,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); @@ -286,7 +286,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 )); } @@ -315,7 +315,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) { @@ -367,11 +367,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 00353c1c391f7..634713758899f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -44,7 +44,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; @@ -103,10 +103,10 @@ namespace ts { location = getParseTreeNode(location); return location ? getTypeOfSymbolAtLocation(symbol, location) : unknownType; }, - getSymbolsOfParameterPropertyDeclaration: (parameter, parameterName) => { - parameter = getParseTreeNode(parameter, isParameter); + getSymbolsOfParameterPropertyDeclaration: (parameterIn, parameterName) => { + const parameter = getParseTreeNode(parameterIn, isParameter); Debug.assert(parameter !== undefined, "Cannot get symbols of a synthetic parameter that cannot be resolved to a parse-tree node."); - return getSymbolsOfParameterPropertyDeclaration(parameter, escapeLeadingUnderscores(parameterName)); + return getSymbolsOfParameterPropertyDeclaration(parameter!, escapeLeadingUnderscores(parameterName)); }, getDeclaredTypeOfSymbol, getPropertiesOfType, @@ -117,8 +117,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, @@ -128,11 +128,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) : []; @@ -145,8 +145,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) { @@ -156,8 +156,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) => { @@ -187,41 +187,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, isPropertyAccessOrQualifiedName); + isValidPropertyAccess: (nodeIn, propertyName) => { + const node = getParseTreeNode(nodeIn, isPropertyAccessOrQualifiedName); 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 => { @@ -234,7 +234,7 @@ namespace ts { if (!links.immediateTarget) { const node = getDeclarationOfAliasSymbol(symbol); Debug.assert(!!node); - links.immediateTarget = getTargetOfAliasDeclaration(node, /*dontRecursivelyResolve*/ true); + links.immediateTarget = getTargetOfAliasDeclaration(node!, /*dontRecursivelyResolve*/ true); } return links.immediateTarget; @@ -256,13 +256,13 @@ namespace ts { getFirstIdentifier, ), getAmbientModules, - getAllAttributesTypeFromJsxOpeningLikeElement: node => { - node = getParseTreeNode(node, isJsxOpeningLikeElement); + getAllAttributesTypeFromJsxOpeningLikeElement: nodeIn => { + const node = getParseTreeNode(nodeIn, isJsxOpeningLikeElement); return node ? getAllAttributesTypeFromJsxOpeningLikeElement(node) : undefined; }, getJsxIntrinsicTagNames, - 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), @@ -301,14 +301,14 @@ namespace ts { }, getJsxNamespace: () => unescapeLeadingUnderscores(getJsxNamespace()), 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); }, }; @@ -370,10 +370,11 @@ namespace ts { const noTypePredicate = createIdentifierTypePredicate("<>", 0, anyType); - const anySignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); - const unknownSignature = createSignature(undefined, undefined, undefined, emptyArray, unknownType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); - const resolvingSignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); - const silentNeverSignature = createSignature(undefined, undefined, undefined, emptyArray, silentNeverType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); + // TODO: GH#18217 First parameter is not optional! + const anySignature = createSignature(undefined!, undefined, undefined, emptyArray, anyType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); + const unknownSignature = createSignature(undefined!, undefined, undefined, emptyArray, unknownType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); + const resolvingSignature = createSignature(undefined!, undefined, undefined, emptyArray, anyType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); + const silentNeverSignature = createSignature(undefined!, undefined, undefined, emptyArray, silentNeverType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); const enumNumberIndexInfo = createIndexInfo(stringType, /*isReadonly*/ true); const jsObjectLiteralIndexInfo = createIndexInfo(anyType, /*isReadonly*/ false); @@ -404,11 +405,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; @@ -417,12 +418,12 @@ namespace ts { let deferredGlobalAsyncIteratorType: GenericType; let deferredGlobalAsyncIterableIteratorType: GenericType; let deferredGlobalTemplateStringsArrayType: ObjectType; - let deferredJsxElementClassType: Type; - let deferredJsxElementType: Type; + let deferredJsxElementClassType: Type | undefined; + let deferredJsxElementType: Type | undefined; let deferredJsxStatelessElementType: Type; - let deferredNodes: Node[]; - let deferredUnusedIdentifierNodes: Node[]; + let deferredNodes: Node[] | undefined; + let deferredUnusedIdentifierNodes: Node[] | undefined; let flowLoopStart = 0; let flowLoopCount = 0; @@ -544,10 +545,10 @@ namespace ts { const typeofType = createTypeofType(); let _jsxNamespace: __String; - let _jsxFactoryEntity: EntityName; - let _jsxElementPropertiesName: __String; + let _jsxFactoryEntity: EntityName | undefined; + let _jsxElementPropertiesName: __String | undefined; let _hasComputedJsxElementPropertiesName = false; - let _jsxElementChildrenPropertyName: __String; + let _jsxElementChildrenPropertyName: __String | undefined; let _hasComputedJsxElementChildrenPropertyName = false; /** Things we lazy load from the JSX namespace */ @@ -635,7 +636,7 @@ namespace ts { typeToString(type, enclosingDeclaration, flags, emitTextWriterWrapper(writer)); }, buildSymbolDisplay(symbol, writer, enclosingDeclaration?, meaning?, flags?) { - symbolToString(symbol, enclosingDeclaration, meaning, flags | SymbolFormatFlags.AllowAnyNodeKind, emitTextWriterWrapper(writer)); + symbolToString(symbol, enclosingDeclaration, meaning, flags! | SymbolFormatFlags.AllowAnyNodeKind, emitTextWriterWrapper(writer)); }, buildSignatureDisplay(signature, writer, enclosing?, flags?, kind?) { signatureToString(signature, enclosing, flags, kind, emitTextWriterWrapper(writer)); @@ -648,12 +649,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)); @@ -666,13 +667,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?) { @@ -684,7 +685,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 } }; @@ -788,7 +789,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); @@ -874,7 +875,7 @@ namespace ts { recordMergedSymbol(target, source); } else if (target.flags & SymbolFlags.NamespaceModule) { - error(getNameOfDeclaration(source.declarations[0]), Diagnostics.Cannot_augment_module_0_with_value_exports_because_it_resolves_to_a_non_module_entity, symbolToString(target)); + error(getNameOfDeclaration(source.declarations![0]), Diagnostics.Cannot_augment_module_0_with_value_exports_because_it_resolves_to_a_non_module_entity, symbolToString(target)); } else { const message = target.flags & SymbolFlags.Enum || source.flags & SymbolFlags.Enum @@ -918,16 +919,16 @@ namespace ts { function mergeModuleAugmentation(moduleName: StringLiteral | Identifier): void { const moduleAugmentation = moduleName.parent; - if (moduleAugmentation.symbol.declarations[0] !== moduleAugmentation) { + if (moduleAugmentation.symbol!.declarations![0] !== moduleAugmentation) { // this is a combined symbol for multiple augmentations within the same file. // its symbol already has accumulated information for all declarations // so we need to add it just once - do the work only for first declaration - Debug.assert(moduleAugmentation.symbol.declarations.length > 1); + Debug.assert(moduleAugmentation.symbol!.declarations!.length > 1); return; } if (isGlobalScopeAugmentation(moduleAugmentation)) { - mergeSymbolTable(globals, moduleAugmentation.symbol.exports); + mergeSymbolTable(globals, moduleAugmentation.symbol!.exports!); } else { // find a module that about to be augmented @@ -945,7 +946,7 @@ namespace ts { // if module symbol has already been merged - it is safe to use it. // otherwise clone it mainModule = mainModule.flags & SymbolFlags.Transient ? mainModule : cloneSymbol(mainModule); - mergeSymbol(mainModule, moduleAugmentation.symbol); + mergeSymbol(mainModule, moduleAugmentation.symbol!); } else { // moduleName will be a StringLiteral since this is not `declare global`. @@ -986,7 +987,7 @@ namespace ts { 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) { @@ -1016,14 +1017,14 @@ namespace ts { const constructorDeclaration = parameter.parent; const classDeclaration = parameter.parent.parent; - const parameterSymbol = getSymbol(constructorDeclaration.locals, parameterName, SymbolFlags.Value); - const propertySymbol = getSymbol(getMembersOfSymbol(classDeclaration.symbol), 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 { @@ -1102,7 +1103,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 { @@ -1131,6 +1133,7 @@ namespace ts { } } } + return false; }); } } @@ -1147,10 +1150,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); } @@ -1158,17 +1161,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; @@ -1203,7 +1206,7 @@ namespace ts { lastLocation.kind === SyntaxKind.Parameter || ( lastLocation === (location).type && - result.valueDeclaration.kind === SyntaxKind.Parameter + result.valueDeclaration!.kind === SyntaxKind.Parameter ); } } @@ -1227,7 +1230,7 @@ namespace ts { isInExternalModule = true; // falls through case SyntaxKind.ModuleDeclaration: - const moduleExports = getSymbolOfNode(location).exports; + const moduleExports = getSymbolOfNode(location)!.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 @@ -1264,7 +1267,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; @@ -1289,7 +1292,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)!), name, meaning & SymbolFlags.Type)) { if (!isTypeParameterSymbolDeclaredInContainer(result, location)) { // ignore type parameters not declared in this container result = undefined; @@ -1316,7 +1319,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); } @@ -1336,7 +1339,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)!.members!, name, meaning & SymbolFlags.Type)) { error(errorLocation, Diagnostics.A_computed_property_name_cannot_reference_a_type_parameter_from_its_containing_type); return undefined; } @@ -1402,7 +1405,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 && nameNotFoundMessage && noUnusedIdentifiers && (!lastSelfReferenceLocation || result !== lastSelfReferenceLocation.symbol)) { - result.isReferenced |= meaning; + result.isReferenced! |= meaning; } if (!result) { @@ -1421,7 +1424,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) && @@ -1430,11 +1433,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++; } @@ -1449,7 +1452,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; } @@ -1477,7 +1480,7 @@ namespace ts { if (result && isInExternalModule && (meaning & SymbolFlags.Value) === SymbolFlags.Value) { 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 } } } @@ -1503,7 +1506,7 @@ namespace ts { } function isTypeParameterSymbolDeclaredInContainer(symbol: Symbol, container: Node) { - for (const decl of symbol.declarations) { + for (const decl of symbol.declarations!) { if (decl.kind === SyntaxKind.TypeParameter && decl.parent === container) { return true; } @@ -1536,7 +1539,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; @@ -1552,11 +1555,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, @@ -1644,15 +1647,15 @@ namespace ts { Debug.assert(declaration !== undefined, "Declaration to checkResolvedBlockScopedVariable is undefined"); - if (!(declaration.flags & NodeFlags.Ambient) && !isBlockScopedNameDeclaredBeforeUse(declaration, errorLocation)) { + if (!(declaration!.flags & NodeFlags.Ambient) && !isBlockScopedNameDeclaredBeforeUse(declaration!, errorLocation)) { if (result.flags & SymbolFlags.BlockScopedVariable) { - error(errorLocation, Diagnostics.Block_scoped_variable_0_used_before_its_declaration, declarationNameToString(getNameOfDeclaration(declaration))); + error(errorLocation, Diagnostics.Block_scoped_variable_0_used_before_its_declaration, declarationNameToString(getNameOfDeclaration(declaration!)!)); } else if (result.flags & SymbolFlags.Class) { - error(errorLocation, Diagnostics.Class_0_used_before_its_declaration, declarationNameToString(getNameOfDeclaration(declaration))); + error(errorLocation, Diagnostics.Class_0_used_before_its_declaration, declarationNameToString(getNameOfDeclaration(declaration!)!)); } else if (result.flags & SymbolFlags.RegularEnum) { - error(errorLocation, Diagnostics.Enum_0_used_before_its_declaration, declarationNameToString(getNameOfDeclaration(declaration))); + error(errorLocation, Diagnostics.Enum_0_used_before_its_declaration, declarationNameToString(getNameOfDeclaration(declaration!)!)); // TODO: GH#18217 } } } @@ -1661,8 +1664,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 { @@ -1681,10 +1684,10 @@ namespace ts { } function getDeclarationOfAliasSymbol(symbol: Symbol): Declaration | undefined { - return find(symbol.declarations, isAliasSymbolDeclaration); + 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))); } @@ -1692,10 +1695,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 canHaveSyntheticDefault(file: SourceFile | undefined, moduleSymbol: Symbol, dontResolveAlias: boolean) { @@ -1728,11 +1731,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; } @@ -1740,7 +1743,7 @@ namespace ts { exportDefaultSymbol = resolveExportByName(moduleSymbol, InternalSymbolName.Default, dontResolveAlias); } - const file = find(moduleSymbol.declarations, isSourceFile); + const file = find(moduleSymbol.declarations!, isSourceFile); const hasSyntheticDefault = canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias); if (!exportDefaultSymbol && !hasSyntheticDefault) { error(node.name, Diagnostics.Module_0_has_no_default_export, symbolToString(moduleSymbol)); @@ -1753,7 +1756,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); } @@ -1792,32 +1795,32 @@ 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!); + const targetSymbol = resolveESModuleSymbol(moduleSymbol, node.moduleSpecifier!, dontResolveAlias); if (targetSymbol) { const name = specifier.propertyName || specifier.name; if (name.escapedText) { - if (isShorthandAmbientModuleSymbol(moduleSymbol)) { - return moduleSymbol; + if (isShorthandAmbientModuleSymbol(moduleSymbol!)) { + 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("export=" as __String)) { symbolFromVariable = getPropertyOfType(getTypeOfSymbol(targetSymbol), name.escapedText); @@ -1836,19 +1839,19 @@ namespace ts { combineValueAndTypeSymbols(symbolFromVariable, symbolFromModule) : symbolFromModule || symbolFromVariable; if (!symbol) { - error(name, Diagnostics.Module_0_has_no_exported_member_1, getFullyQualifiedName(moduleSymbol), declarationNameToString(name)); + error(name, Diagnostics.Module_0_has_no_exported_member_1, getFullyQualifiedName(moduleSymbol!), declarationNameToString(name)); } return symbol; } } } - function getTargetOfImportSpecifier(node: ImportSpecifier, dontResolveAlias: boolean): Symbol { + function getTargetOfImportSpecifier(node: ImportSpecifier, dontResolveAlias: boolean): Symbol | undefined { return getExternalModuleMember(node.parent.parent.parent, node, dontResolveAlias); } function getTargetOfNamespaceExportDeclaration(node: NamespaceExportDeclaration, dontResolveAlias: boolean): Symbol { - return resolveExternalModuleSymbol(node.parent.symbol, dontResolveAlias); + return resolveExternalModuleSymbol(node.parent.symbol!, dontResolveAlias); } function getTargetOfExportSpecifier(node: ExportSpecifier, meaning: SymbolFlags, dontResolveAlias?: boolean) { @@ -1858,10 +1861,10 @@ namespace ts { } function getTargetOfExportAssignment(node: ExportAssignment, dontResolveAlias: boolean): Symbol { - return resolveEntityName(node.expression, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace, /*ignoreErrors*/ false, dontResolveAlias); + return resolveEntityName(node.expression, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace, /*ignoreErrors*/ false, dontResolveAlias)!; } - function getTargetOfAliasDeclaration(node: Declaration, dontRecursivelyResolve?: boolean): Symbol { + function getTargetOfAliasDeclaration(node: Declaration, dontRecursivelyResolve = false): Symbol | undefined { switch (node.kind) { case SyntaxKind.ImportEqualsDeclaration: return getTargetOfImportEqualsDeclaration(node, dontRecursivelyResolve); @@ -1877,19 +1880,23 @@ namespace ts { return getTargetOfExportAssignment(node, dontRecursivelyResolve); case SyntaxKind.NamespaceExportDeclaration: return getTargetOfNamespaceExportDeclaration(node, dontRecursivelyResolve); + default: + return Debug.fail(); } } /** * Indicates that a symbol is an alias that does not merge with a local declaration. */ - function isNonLocalAlias(symbol: Symbol, excludes = SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace) { - return symbol && (symbol.flags & (SymbolFlags.Alias | excludes)) === SymbolFlags.Alias; + function isNonLocalAlias(symbol: Symbol | undefined, excludes = SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace) { + return !!symbol && (symbol.flags & (SymbolFlags.Alias | excludes)) === SymbolFlags.Alias; } - function resolveSymbol(symbol: Symbol, dontResolveAlias?: boolean): 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 { const shouldResolve = !dontResolveAlias && isNonLocalAlias(symbol); - return shouldResolve ? resolveAlias(symbol) : symbol; + return shouldResolve ? resolveAlias(symbol!) : symbol; } function resolveAlias(symbol: Symbol): Symbol { @@ -1897,7 +1904,7 @@ namespace ts { const links = getSymbolLinks(symbol); if (!links.target) { links.target = resolvingSymbol; - const node = getDeclarationOfAliasSymbol(symbol); + const node = getDeclarationOfAliasSymbol(symbol)!; Debug.assert(!!node); const target = getTargetOfAliasDeclaration(node); if (links.target === resolvingSymbol) { @@ -1914,7 +1921,7 @@ namespace ts { } function markExportAsReferenced(node: ImportEqualsDeclaration | ExportAssignment | ExportSpecifier) { - const symbol = getSymbolOfNode(node); + const symbol = getSymbolOfNode(node)!; const target = resolveAlias(symbol); if (target) { const markAlias = target === unknownSymbol || @@ -1933,7 +1940,7 @@ namespace ts { const links = getSymbolLinks(symbol); if (!links.referenced) { links.referenced = true; - const node = getDeclarationOfAliasSymbol(symbol); + const node = getDeclarationOfAliasSymbol(symbol)!; Debug.assert(!!node); if (node.kind === SyntaxKind.ExportAssignment) { // export default @@ -1951,7 +1958,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 |...|: // @@ -1985,7 +1992,7 @@ namespace ts { return undefined; } - let symbol: Symbol; + let symbol: Symbol | undefined; if (name.kind === SyntaxKind.Identifier) { const message = meaning === SymbolFlags.Namespace ? Diagnostics.Cannot_find_namespace_0 : Diagnostics.Cannot_find_name_0; @@ -2019,7 +2026,7 @@ namespace ts { return namespace; } if (isInJavaScriptFile(name) && isDeclarationOfFunctionOrClassExpression(namespace)) { - namespace = getSymbolOfNode((namespace.valueDeclaration as VariableDeclaration).initializer); + namespace = getSymbolOfNode((namespace.valueDeclaration as VariableDeclaration).initializer!)!; } symbol = getSymbol(getExportsOfSymbol(namespace), right.escapedText, meaning); if (!symbol) { @@ -2030,23 +2037,23 @@ 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); } - 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; } @@ -2087,16 +2094,16 @@ namespace ts { if (resolvedModule && !extensionIsTypeScript(resolvedModule.extension) && resolutionDiagnostic === undefined || resolutionDiagnostic === Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type) { if (isForAugmentation) { const diag = Diagnostics.Invalid_module_name_in_augmentation_Module_0_resolves_to_an_untyped_module_at_1_which_cannot_be_augmented; - error(errorNode, diag, moduleReference, resolvedModule.resolvedFileName); + error(errorNode, diag, moduleReference, resolvedModule!.resolvedFileName); // TODO: GH#18217 } else if (noImplicitAny && moduleNotFoundError) { - let errorInfo = resolvedModule.packageId && chainDiagnosticMessages(/*details*/ undefined, + let errorInfo = resolvedModule!.packageId && chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Try_npm_install_types_Slash_0_if_it_exists_or_add_a_new_declaration_d_ts_file_containing_declare_module_0, - resolvedModule.packageId.name); + resolvedModule!.packageId!.name); // TODO: GH#18217 errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type, moduleReference, - resolvedModule.resolvedFileName); + resolvedModule!.resolvedFileName); diagnostics.add(createDiagnosticForNodeFromMessageChain(errorNode, errorInfo)); } // Failed imports and untyped modules are both treated in an untyped manner; only difference is whether we give a diagnostic first. @@ -2106,7 +2113,7 @@ namespace ts { if (moduleNotFoundError) { // report errors only if it was requested if (resolutionDiagnostic) { - error(errorNode, resolutionDiagnostic, moduleReference, resolvedModule.resolvedFileName); + error(errorNode, resolutionDiagnostic, moduleReference, resolvedModule!.resolvedFileName); } else { const tsExtension = tryExtractTypeScriptExtension(moduleReference); @@ -2124,18 +2131,22 @@ 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 { - return moduleSymbol && getMergedSymbol(resolveSymbol(moduleSymbol.exports.get(InternalSymbolName.ExportEquals), dontResolveAlias)) || moduleSymbol; + function resolveExternalModuleSymbol(moduleSymbol: Symbol, dontResolveAlias?: boolean): Symbol; + function resolveExternalModuleSymbol(moduleSymbol: Symbol | undefined, dontResolveAlias?: boolean): Symbol | undefined; + function resolveExternalModuleSymbol(moduleSymbol: Symbol | undefined, dontResolveAlias?: boolean): Symbol | undefined { + return moduleSymbol && getMergedSymbol(resolveSymbol(moduleSymbol.exports!.get(InternalSymbolName.ExportEquals)!, dontResolveAlias)) || moduleSymbol; } // 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, moduleReferenceExpression: Expression, dontResolveAlias: boolean): Symbol { + function resolveESModuleSymbol(moduleSymbol: Symbol, moduleReferenceExpression: Expression, dontResolveAlias: boolean): Symbol; + function resolveESModuleSymbol(moduleSymbol: Symbol | undefined, moduleReferenceExpression: Expression, dontResolveAlias: boolean): Symbol | undefined; + function resolveESModuleSymbol(moduleSymbol: Symbol | undefined, moduleReferenceExpression: Expression, dontResolveAlias: boolean): Symbol | undefined { const symbol = resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias); if (!dontResolveAlias && symbol) { if (!(symbol.flags & (SymbolFlags.Module | SymbolFlags.Variable))) { - error(moduleReferenceExpression, Diagnostics.Module_0_resolves_to_a_non_module_entity_and_cannot_be_imported_using_this_construct, symbolToString(moduleSymbol)); + error(moduleReferenceExpression, Diagnostics.Module_0_resolves_to_a_non_module_entity_and_cannot_be_imported_using_this_construct, symbolToString(moduleSymbol!)); return symbol; } if (compilerOptions.esModuleInterop) { @@ -2150,7 +2161,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() : []; @@ -2172,7 +2183,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[] { @@ -2242,12 +2253,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]; } @@ -2268,18 +2279,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); + for (const node of exportStars.declarations!) { + const resolvedModule = resolveExternalModuleName(node, (node as ExportDeclaration).moduleSpecifier!); const exportedSymbols = visit(resolvedModule); extendExportSymbols( nestedSymbols, @@ -2297,7 +2308,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) )); } @@ -2308,20 +2319,24 @@ 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: 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; @@ -2331,7 +2346,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)) { @@ -2383,7 +2398,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 = []; @@ -2395,7 +2410,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; @@ -2405,12 +2420,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) @@ -2426,7 +2441,7 @@ namespace ts { } // falls through case SyntaxKind.ModuleDeclaration: - if (result = callback(getSymbolOfNode(location).exports)) { + if (result = callback(getSymbolOfNode(location)!.exports!)) { return result; } break; @@ -2441,7 +2456,7 @@ namespace ts { return rightMeaning === SymbolFlags.Value ? SymbolFlags.Value : SymbolFlags.Namespace; } - function getAccessibleSymbolChain(symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags, useOnlyExternalAliasing: boolean): Symbol[] | undefined { + function getAccessibleSymbolChain(symbol: Symbol | undefined, enclosingDeclaration: Node | undefined, meaning: SymbolFlags, useOnlyExternalAliasing: boolean): Symbol[] | undefined { if (!(symbol && !isPropertyOrMethodDeclarationSymbol(symbol))) { return undefined; } @@ -2480,8 +2495,8 @@ namespace ts { function trySymbolTable(symbols: SymbolTable, ignoreQualification: boolean | 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 @@ -2556,7 +2571,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; } @@ -2574,7 +2589,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 && !(symbol.flags & SymbolFlags.TypeParameter)) { const initialSymbol = symbol; let meaningToLook = meaning; @@ -2643,8 +2658,8 @@ namespace ts { return isAmbientModule(declaration) || (declaration.kind === SyntaxKind.SourceFile && isExternalOrCommonJsModule(declaration)); } - function hasVisibleDeclarations(symbol: Symbol, shouldComputeAliasToMakeVisible: boolean): SymbolVisibilityResult { - let aliasesToMakeVisible: AnyImportSyntax[]; + function hasVisibleDeclarations(symbol: Symbol, shouldComputeAliasToMakeVisible: boolean): SymbolVisibilityResult | undefined { + let aliasesToMakeVisible: AnyImportSyntax[] | undefined; if (forEach(symbol.declarations, declaration => !getIsDeclarationVisible(declaration))) { return undefined; } @@ -2723,7 +2738,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); @@ -2736,7 +2751,7 @@ namespace ts { function signatureToStringWorker(writer: EmitTextWriter) { let sigOutput: SyntaxKind; - if (flags & TypeFormatFlags.WriteArrowStyleSignature) { + if (flags! & TypeFormatFlags.WriteArrowStyleSignature) { sigOutput = kind === SignatureKind.Construct ? SyntaxKind.ConstructorType : SyntaxKind.FunctionType; } else { @@ -2745,7 +2760,7 @@ 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; } } @@ -2756,10 +2771,10 @@ namespace ts { const options = { removeComments: true }; const printer = createPrinter(options); const sourceFile = enclosingDeclaration && getSourceFileOfNode(enclosingDeclaration); - printer.writeNode(EmitHint.Unspecified, typeNode, /*sourceFile*/ sourceFile, writer); + printer.writeNode(EmitHint.Unspecified, typeNode!, /*sourceFile*/ sourceFile, writer); const result = writer.getText(); - const maxLength = compilerOptions.noErrorTruncation || flags & TypeFormatFlags.NoTruncation ? undefined : 100; + const maxLength = compilerOptions.noErrorTruncation || flags! & TypeFormatFlags.NoTruncation ? undefined : 100; if (maxLength && result && result.length >= maxLength) { return result.substr(0, maxLength - "...".length) + "..."; } @@ -2767,7 +2782,7 @@ namespace ts { } function toNodeBuilderFlags(flags?: TypeFormatFlags): NodeBuilderFlags { - return flags & TypeFormatFlags.NodeBuilderFlagsMask; + return flags! & TypeFormatFlags.NodeBuilderFlagsMask; } function createNodeBuilder() { @@ -2784,7 +2799,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); @@ -2840,9 +2855,9 @@ namespace ts { }; } - function typeToTypeNodeHelper(type: Type, context: NodeBuilderContext): TypeNode { - const inTypeAlias = context.flags & NodeBuilderFlags.InTypeAlias; - context.flags &= ~NodeBuilderFlags.InTypeAlias; + function typeToTypeNodeHelper(type: Type, context: NodeBuilderContext): TypeNode | undefined { + const inTypeAlias = context.flags! & NodeBuilderFlags.InTypeAlias; + context.flags! &= ~NodeBuilderFlags.InTypeAlias; if (!type) { context.encounteredError = true; @@ -2862,13 +2877,13 @@ 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)); + const enumLiteralName = getDeclaredTypeOfSymbol(parentSymbol) === type ? parentName : createQualifiedName(parentName, symbolName(type.symbol!)); return createTypeReferenceNode(enumLiteralName, /*typeArguments*/ undefined); } if (type.flags & TypeFlags.EnumLike) { - const name = symbolToName(type.symbol, context, SymbolFlags.Type, /*expectsIdentifier*/ false); + const name = symbolToName(type.symbol!, context, SymbolFlags.Type, /*expectsIdentifier*/ false); return createTypeReferenceNode(name, /*typeArguments*/ undefined); } if (type.flags & (TypeFlags.StringLiteral)) { @@ -2881,9 +2896,9 @@ namespace ts { return (type).intrinsicName === "true" ? createTrue() : createFalse(); } if (type.flags & TypeFlags.UniqueESSymbol) { - if (!(context.flags & NodeBuilderFlags.AllowUniqueESSymbolType)) { - if (context.tracker.reportInaccessibleUniqueSymbolError) { - context.tracker.reportInaccessibleUniqueSymbolError(); + if (!(context.flags! & NodeBuilderFlags.AllowUniqueESSymbolType)) { + if (context.tracker!.reportInaccessibleUniqueSymbolError) { + context.tracker!.reportInaccessibleUniqueSymbolError!(); } } return createTypeOperatorNode(SyntaxKind.UniqueKeyword, createKeywordTypeNode(SyntaxKind.SymbolKeyword)); @@ -2907,12 +2922,12 @@ namespace ts { return createKeywordTypeNode(SyntaxKind.ObjectKeyword); } if (type.flags & TypeFlags.TypeParameter && (type as TypeParameter).isThisType) { - if (context.flags & NodeBuilderFlags.InObjectTypeLiteral) { - if (!context.encounteredError && !(context.flags & NodeBuilderFlags.AllowThisInObjectLiteral)) { + if (context.flags! & NodeBuilderFlags.InObjectTypeLiteral) { + if (!context.encounteredError && !(context.flags! & NodeBuilderFlags.AllowThisInObjectLiteral)) { context.encounteredError = true; } - if (context.tracker.reportInaccessibleThisError) { - context.tracker.reportInaccessibleThisError(); + if (context.tracker!.reportInaccessibleThisError) { + context.tracker!.reportInaccessibleThisError!(); } } return createThis(); @@ -2929,7 +2944,7 @@ namespace ts { // Ignore constraint/default when creating a usage (as opposed to declaration) of a type parameter. return createTypeReferenceNode(name, /*typeArguments*/ undefined); } - if (!inTypeAlias && type.aliasSymbol && (context.flags & NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope || isTypeSymbolAccessible(type.aliasSymbol, context.enclosingDeclaration))) { + if (!inTypeAlias && type.aliasSymbol && (context.flags! & NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope || isTypeSymbolAccessible(type.aliasSymbol, context.enclosingDeclaration))) { const name = symbolToTypeReferenceName(type.aliasSymbol); const typeArgumentNodes = mapToTypeNodes(type.aliasTypeArguments, context); return createTypeReferenceNode(name, typeArgumentNodes); @@ -2942,7 +2957,7 @@ namespace ts { return unionOrIntersectionTypeNode; } else { - if (!context.encounteredError && !(context.flags & NodeBuilderFlags.AllowEmptyUnionOrIntersection)) { + if (!context.encounteredError && !(context.flags! & NodeBuilderFlags.AllowEmptyUnionOrIntersection)) { context.encounteredError = true; } return undefined; @@ -2955,19 +2970,19 @@ namespace ts { } if (type.flags & TypeFlags.Index) { const indexedType = (type).type; - const indexTypeNode = typeToTypeNodeHelper(indexedType, context); + const indexTypeNode = typeToTypeNodeHelper(indexedType, context)!; // TODO: GH#18217 return createTypeOperatorNode(indexTypeNode); } if (type.flags & TypeFlags.IndexedAccess) { - const objectTypeNode = typeToTypeNodeHelper((type).objectType, context); - const indexTypeNode = typeToTypeNodeHelper((type).indexType, context); + const objectTypeNode = typeToTypeNodeHelper((type).objectType, context)!; // TODO: GH#18217 + const indexTypeNode = typeToTypeNodeHelper((type).indexType, context)!; return createIndexedAccessTypeNode(objectTypeNode, indexTypeNode); } if (type.flags & TypeFlags.Conditional) { - const checkTypeNode = typeToTypeNodeHelper((type).checkType, context); - const extendsTypeNode = typeToTypeNodeHelper((type).extendsType, context); - const trueTypeNode = typeToTypeNodeHelper((type).trueType, context); - const falseTypeNode = typeToTypeNodeHelper((type).falseType, context); + const checkTypeNode = typeToTypeNodeHelper((type).checkType, context)!; // TODO: GH#18217 (and below) + const extendsTypeNode = typeToTypeNodeHelper((type).extendsType, context)!; + const trueTypeNode = typeToTypeNodeHelper((type).trueType, context)!; + const falseTypeNode = typeToTypeNodeHelper((type).falseType, context)!; return createConditionalTypeNode(checkTypeNode, extendsTypeNode, trueTypeNode, falseTypeNode); } if (type.flags & TypeFlags.Substitution) { @@ -2990,7 +3005,7 @@ namespace ts { const symbol = type.symbol; if (symbol) { // Always use 'typeof T' for type of class, enum, and module objects - if (symbol.flags & SymbolFlags.Class && !getBaseTypeVariableOfClass(symbol) && !(symbol.valueDeclaration.kind === SyntaxKind.ClassExpression && context.flags & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral) || + if (symbol.flags & SymbolFlags.Class && !getBaseTypeVariableOfClass(symbol) && !(symbol.valueDeclaration!.kind === SyntaxKind.ClassExpression && context.flags! & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral) || symbol.flags & (SymbolFlags.Enum | SymbolFlags.ValueModule) || shouldWriteTypeOfFunctionSymbol()) { return createTypeQueryNodeFromSymbol(symbol, SymbolFlags.Value); @@ -3032,16 +3047,17 @@ namespace ts { } function shouldWriteTypeOfFunctionSymbol() { - const isStaticMethodSymbol = !!(symbol.flags & SymbolFlags.Method) && // typeof static method - some(symbol.declarations, declaration => hasModifier(declaration, ModifierFlags.Static)); - const isNonLocalFunctionSymbol = !!(symbol.flags & SymbolFlags.Function) && - (symbol.parent || // is exported function symbol - forEach(symbol.declarations, declaration => + const isStaticMethodSymbol = !!(symbol!.flags & SymbolFlags.Method) && // typeof static method + some(symbol!.declarations, declaration => hasModifier(declaration, ModifierFlags.Static)); + const isNonLocalFunctionSymbol = !!(symbol!.flags & SymbolFlags.Function) && + (symbol!.parent || // is exported function symbol + forEach(symbol!.declarations, declaration => declaration.parent.kind === SyntaxKind.SourceFile || declaration.parent.kind === SyntaxKind.ModuleBlock)); if (isStaticMethodSymbol || isNonLocalFunctionSymbol) { // typeof is allowed only for static/non local functions - return (!!(context.flags & NodeBuilderFlags.UseTypeOfFunction) || contains(context.symbolStack, symbol)) && // 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 + return (!!(context.flags! & NodeBuilderFlags.UseTypeOfFunction) || contains(context.symbolStack, symbol)) && // it is type of the symbol uses itself recursively + // 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 } } } @@ -3072,11 +3088,11 @@ namespace ts { } const savedFlags = context.flags; - context.flags |= NodeBuilderFlags.InObjectTypeLiteral; + context.flags! |= NodeBuilderFlags.InObjectTypeLiteral; const members = createTypeNodesFromResolvedType(resolved); context.flags = savedFlags; const typeLiteralNode = createTypeLiteralNode(members); - return setEmitFlags(typeLiteralNode, (context.flags & NodeBuilderFlags.MultilineObjectLiterals) ? 0 : EmitFlags.SingleLine); + return setEmitFlags(typeLiteralNode, (context.flags! & NodeBuilderFlags.MultilineObjectLiterals) ? 0 : EmitFlags.SingleLine); } function createTypeQueryNodeFromSymbol(symbol: Symbol, symbolFlags: SymbolFlags) { @@ -3093,12 +3109,12 @@ namespace ts { function typeReferenceToTypeNode(type: TypeReference) { const typeArguments: Type[] = type.typeArguments || emptyArray; if (type.target === globalArrayType) { - if (context.flags & NodeBuilderFlags.WriteArrayAsGenericType) { - const typeArgumentNode = typeToTypeNodeHelper(typeArguments[0], context); + if (context.flags! & NodeBuilderFlags.WriteArrayAsGenericType) { + const typeArgumentNode = typeToTypeNodeHelper(typeArguments[0], context)!; return createTypeReferenceNode("Array", [typeArgumentNode]); } - const elementType = typeToTypeNodeHelper(typeArguments[0], context); + const elementType = typeToTypeNodeHelper(typeArguments[0], context)!; return createArrayTypeNode(elementType); } else if (type.target.objectFlags & ObjectFlags.Tuple) { @@ -3108,15 +3124,15 @@ namespace ts { return createTupleTypeNode(tupleConstituentNodes); } } - if (context.encounteredError || (context.flags & NodeBuilderFlags.AllowEmptyTuple)) { + if (context.encounteredError || (context.flags! & NodeBuilderFlags.AllowEmptyTuple)) { return createTupleTypeNode([]); } context.encounteredError = true; return undefined; } - else if (context.flags & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral && - type.symbol.valueDeclaration && - type.symbol.valueDeclaration.kind === SyntaxKind.ClassExpression) { + else if (context.flags! & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral && + type.symbol!.valueDeclaration && + type.symbol!.valueDeclaration!.kind === SyntaxKind.ClassExpression) { return createAnonymousTypeNode(type); } else { @@ -3128,7 +3144,7 @@ namespace ts { 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); @@ -3143,17 +3159,17 @@ namespace ts { if (qualifiedName) { Debug.assert(!qualifiedName.right); qualifiedName = addToQualifiedNameMissingRightIdentifier(qualifiedName, namePart); - qualifiedName = createQualifiedName(qualifiedName, /*right*/ undefined); + qualifiedName = createQualifiedName(qualifiedName, /*right*/ undefined!); // TODO: GH#18217 } else { - qualifiedName = createQualifiedName(namePart, /*right*/ undefined); + qualifiedName = createQualifiedName(namePart, /*right*/ undefined!); } } } } - let entityName: EntityName = undefined; - const nameIdentifier = symbolToTypeReferenceName(type.symbol); + let entityName: EntityName | undefined; + const nameIdentifier = symbolToTypeReferenceName(type.symbol!); if (qualifiedName) { Debug.assert(!qualifiedName.right); qualifiedName = addToQualifiedNameMissingRightIdentifier(qualifiedName, nameIdentifier); @@ -3196,7 +3212,7 @@ namespace ts { return right; } - 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)); @@ -3220,23 +3236,23 @@ namespace ts { } for (const propertySymbol of properties) { - if (context.flags & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral) { + if (context.flags! & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral) { if (propertySymbol.flags & SymbolFlags.Prototype) { continue; } - if (getDeclarationModifierFlagsFromSymbol(propertySymbol) & (ModifierFlags.Private | ModifierFlags.Protected) && context.tracker.reportPrivateInBaseOfClassExpression) { - context.tracker.reportPrivateInBaseOfClassExpression(unescapeLeadingUnderscores(propertySymbol.escapedName)); + if (getDeclarationModifierFlagsFromSymbol(propertySymbol) & (ModifierFlags.Private | ModifierFlags.Protected) && context.tracker!.reportPrivateInBaseOfClassExpression) { + context.tracker!.reportPrivateInBaseOfClassExpression!(unescapeLeadingUnderscores(propertySymbol.escapedName)); } } - const propertyType = getCheckFlags(propertySymbol) & CheckFlags.ReverseMapped && context.flags & NodeBuilderFlags.InReverseMappedType ? + const propertyType = getCheckFlags(propertySymbol) & CheckFlags.ReverseMapped && context.flags! & NodeBuilderFlags.InReverseMappedType ? anyType : getTypeOfSymbol(propertySymbol); 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); + if (name && context.tracker!.trackSymbol) { + context.tracker!.trackSymbol!(name, saveEnclosingDeclaration, SymbolFlags.Value); } } const propertyName = symbolToName(propertySymbol, context, SymbolFlags.Value, /*expectsIdentifier*/ true); @@ -3253,7 +3269,7 @@ namespace ts { } else { const savedFlags = context.flags; - context.flags |= !!(getCheckFlags(propertySymbol) & CheckFlags.ReverseMapped) ? NodeBuilderFlags.InReverseMappedType : 0; + context.flags! |= !!(getCheckFlags(propertySymbol) & CheckFlags.ReverseMapped) ? NodeBuilderFlags.InReverseMappedType : 0; const propertyTypeNode = propertyType ? typeToTypeNodeHelper(propertyType, context) : createKeywordTypeNode(SyntaxKind.AnyKeyword); context.flags = savedFlags; @@ -3271,10 +3287,10 @@ 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) { + for (const type of types!) { const typeNode = typeToTypeNodeHelper(type, context); if (typeNode) { result.push(typeNode); @@ -3297,8 +3313,8 @@ namespace ts { /*questionToken*/ undefined, indexerTypeNode, /*initializer*/ undefined); - const typeNode = indexInfo.type ? typeToTypeNodeHelper(indexInfo.type, context) : typeToTypeNodeHelper(anyType, context); - if (!indexInfo.type && !(context.flags & NodeBuilderFlags.AllowEmptyIndexInfoType)) { + const typeNode = typeToTypeNodeHelper(indexInfo.type || anyType, context)!; // TODO: GH#18217 + if (!indexInfo.type && !(context.flags! & NodeBuilderFlags.AllowEmptyIndexInfoType)) { context.encounteredError = true; } return createIndexSignature( @@ -3309,10 +3325,10 @@ namespace ts { } function signatureToSignatureDeclarationHelper(signature: Signature, kind: SyntaxKind, context: NodeBuilderContext): SignatureDeclaration { - let typeParameters: TypeParameterDeclaration[]; - let typeArguments: TypeNode[]; - if (context.flags & NodeBuilderFlags.WriteTypeArgumentsOfSignature && signature.target && signature.mapper && signature.target.typeParameters) { - typeArguments = signature.target.typeParameters.map(parameter => typeToTypeNodeHelper(instantiateType(parameter, signature.mapper), context)); + 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)!); // TODO: GH#18217 } else { typeParameters = signature.typeParameters && signature.typeParameters.map(parameter => typeParameterToDeclaration(parameter, context)); @@ -3322,20 +3338,21 @@ 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 ? setEmitFlags(createIdentifier(typePredicate.parameterName), EmitFlags.NoAsciiEscaping) : createThisTypeNode(); - const typeNode = typeToTypeNodeHelper(typePredicate.type, context); + const typeNode = typeToTypeNodeHelper(typePredicate.type, context)!; returnTypeNode = createTypePredicateNode(parameterName, typeNode); } else { const returnType = getReturnTypeOfSignature(signature); returnTypeNode = returnType && typeToTypeNodeHelper(returnType, context); } - if (context.flags & NodeBuilderFlags.SuppressAnyReturnType) { + if (context.flags! & NodeBuilderFlags.SuppressAnyReturnType) { if (returnTypeNode && returnTypeNode.kind === SyntaxKind.AnyKeyword) { returnTypeNode = undefined; } @@ -3348,8 +3365,8 @@ namespace ts { function typeParameterToDeclaration(type: TypeParameter, context: NodeBuilderContext, constraint = getConstraintFromTypeParameter(type)): TypeParameterDeclaration { const savedContextFlags = context.flags; - context.flags &= ~NodeBuilderFlags.WriteTypeParametersInQualifiedName; // Avoids potential infinite loop when building for a claimspace with a generic - const name = symbolToName(type.symbol, context, SymbolFlags.Type, /*expectsIdentifier*/ true); + context.flags! &= ~NodeBuilderFlags.WriteTypeParametersInQualifiedName; // Avoids potential infinite loop when building for a claimspace with a generic + const name = symbolToName(type.symbol!, context, SymbolFlags.Type, /*expectsIdentifier*/ true); const constraintNode = constraint && typeToTypeNodeHelper(constraint, context); const defaultParameter = getDefaultFromTypeParameter(type); const defaultParameterNode = defaultParameter && typeToTypeNodeHelper(defaultParameter, context); @@ -3367,7 +3384,7 @@ namespace ts { } const parameterTypeNode = typeToTypeNodeHelper(parameterType, context); - const modifiers = !(context.flags & NodeBuilderFlags.OmitParameterModifiers) && parameterDeclaration && parameterDeclaration.modifiers && parameterDeclaration.modifiers.map(getSynthesizedClone); + const modifiers = !(context.flags! & NodeBuilderFlags.OmitParameterModifiers) && parameterDeclaration && parameterDeclaration.modifiers ? parameterDeclaration.modifiers.map(getSynthesizedClone) : undefined; const dotDotDotToken = !parameterDeclaration || isRestParameter(parameterDeclaration) ? createToken(SyntaxKind.DotDotDotToken) : undefined; const name = parameterDeclaration ? parameterDeclaration.name ? @@ -3390,7 +3407,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; @@ -3401,12 +3418,12 @@ namespace ts { } function lookupSymbolChain(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags) { - context.tracker.trackSymbol(symbol, context.enclosingDeclaration, meaning); + context.tracker!.trackSymbol!(symbol, context.enclosingDeclaration, meaning); // 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); + if (!isTypeParameter && (context.enclosingDeclaration || context.flags! & NodeBuilderFlags.UseFullyQualifiedType)) { + chain = getSymbolChain(symbol, meaning, /*endOfChain*/ true)!; Debug.assert(chain && chain.length > 0); } else { @@ -3416,8 +3433,8 @@ 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 accessibleSymbolChain = getAccessibleSymbolChain(symbol, context.enclosingDeclaration, meaning, !!(context.flags! & NodeBuilderFlags.UseOnlyExternalAliasing)); + let parentSymbol: Symbol | undefined; if (!accessibleSymbolChain || needsQualification(accessibleSymbolChain[0], context.enclosingDeclaration, accessibleSymbolChain.length === 1 ? meaning : getQualifiedLeftMeaning(meaning))) { @@ -3462,14 +3479,14 @@ namespace ts { Debug.assert(chain && 0 <= index && index < chain.length); const symbol = chain[index]; let typeParameterNodes: ReadonlyArray | ReadonlyArray | undefined; - if (context.flags & NodeBuilderFlags.WriteTypeParametersInQualifiedName && index < (chain.length - 1)) { + if (context.flags! & NodeBuilderFlags.WriteTypeParametersInQualifiedName && index < (chain.length - 1)) { const parentSymbol = symbol; const nextSymbol = chain[index + 1]; if (getCheckFlags(nextSymbol) & CheckFlags.Instantiated) { 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); @@ -3485,7 +3502,7 @@ namespace ts { if (expectsIdentifier && chain.length !== 1 && !context.encounteredError - && !(context.flags & NodeBuilderFlags.AllowQualifedNameInPlaceOfIdentifier)) { + && !(context.flags! & NodeBuilderFlags.AllowQualifedNameInPlaceOfIdentifier)) { context.encounteredError = true; } return createEntityNameFromSymbolChain(chain, chain.length - 1); @@ -3495,11 +3512,11 @@ namespace ts { const symbol = chain[index]; if (index === 0) { - context.flags |= NodeBuilderFlags.InInitialEntityName; + context.flags! |= NodeBuilderFlags.InInitialEntityName; } const symbolName = getNameOfSymbolAsWritten(symbol, context); if (index === 0) { - context.flags ^= NodeBuilderFlags.InInitialEntityName; + context.flags! ^= NodeBuilderFlags.InInitialEntityName; } const identifier = setEmitFlags(createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping); identifier.symbol = symbol; @@ -3518,11 +3535,11 @@ namespace ts { const symbol = chain[index]; if (index === 0) { - context.flags |= NodeBuilderFlags.InInitialEntityName; + context.flags! |= NodeBuilderFlags.InInitialEntityName; } let symbolName = getNameOfSymbolAsWritten(symbol, context); if (index === 0) { - context.flags ^= NodeBuilderFlags.InInitialEntityName; + context.flags! ^= NodeBuilderFlags.InInitialEntityName; } let firstChar = symbolName.charCodeAt(0); const canUsePropertyAccess = isIdentifierStart(firstChar, languageVersion); @@ -3537,7 +3554,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; @@ -3561,7 +3578,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); @@ -3606,9 +3623,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); } @@ -3648,9 +3665,9 @@ namespace ts { * It will also use a representation of a number as written instead of a decimal form, e.g. `0o11` instead of `9`. */ function getNameOfSymbolAsWritten(symbol: Symbol, context?: NodeBuilderContext): string { - if (context && symbol.escapedName === InternalSymbolName.Default && !(context.flags & NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope) && + if (context && symbol.escapedName === InternalSymbolName.Default && !(context.flags! & NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope) && // If it's not the first part of an entity name, it must print as `default` - (!(context.flags & NodeBuilderFlags.InInitialEntityName) || + (!(context.flags! & NodeBuilderFlags.InInitialEntityName) || // if the symbol is synthesized, it will only be referenced externally it must print as `default` !symbol.declarations || // if not in the same binding context (source file, module declaration), it must print as `default` @@ -3666,7 +3683,7 @@ namespace ts { if (declaration.parent && declaration.parent.kind === SyntaxKind.VariableDeclaration) { return declarationNameToString((declaration.parent).name); } - if (context && !context.encounteredError && !(context.flags & NodeBuilderFlags.AllowAnonymousIdentifier)) { + if (context && !context.encounteredError && !(context.flags! & NodeBuilderFlags.AllowAnonymousIdentifier)) { context.encounteredError = true; } switch (declaration.kind) { @@ -3678,7 +3695,7 @@ namespace ts { } } if ((symbol as TransientSymbol).syntheticLiteralTypeOrigin) { - const stringValue = (symbol as TransientSymbol).syntheticLiteralTypeOrigin.value; + const stringValue = (symbol as TransientSymbol).syntheticLiteralTypeOrigin!.value; if (!isIdentifierText(stringValue, compilerOptions.target)) { return `"${escapeString(stringValue, CharacterCodes.doubleQuote)}"`; } @@ -3783,16 +3800,16 @@ 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); + buildVisibleNodeList(exportSymbol.declarations!); } return result; @@ -3814,7 +3831,7 @@ namespace ts { const importSymbol = resolveName(declaration, firstIdentifier.escapedText, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace, undefined, undefined, /*isUse*/ false); if (importSymbol) { - buildVisibleNodeList(importSymbol.declarations); + buildVisibleNodeList(importSymbol.declarations!); } } }); @@ -3861,25 +3878,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 @@ -3887,11 +3904,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: @@ -3903,8 +3920,7 @@ namespace ts { default: return true; } - }); - return node && node.parent; + })!.parent; } function getTypeOfPrototypeProperty(prototype: Symbol): Type { @@ -3912,17 +3928,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; } @@ -3937,7 +3953,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; @@ -3966,7 +3982,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 @@ -3983,7 +3999,7 @@ namespace ts { return parentType; } - let type: Type; + let type: Type | undefined; if (pattern.kind === SyntaxKind.ObjectBindingPattern) { if (declaration.dotDotDotToken) { if (!isValidSpreadType(parentType)) { @@ -4084,7 +4100,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) { @@ -4132,21 +4148,21 @@ namespace ts { const func = declaration.parent; // For a parameter of a set accessor, use the type of the get accessor if one is present if (func.kind === SyntaxKind.SetAccessor && !hasNonBindableDynamicName(func)) { - const getter = getDeclarationOfKind(getSymbolOfNode(declaration.parent), SyntaxKind.GetAccessor); + const getter = getDeclarationOfKind(getSymbolOfNode(declaration.parent)!, SyntaxKind.GetAccessor); if (getter) { const getterSignature = getSignatureFromDeclaration(getter); const thisParameter = getAccessorThisParameter(func as AccessorDeclaration); 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; - if (declaration.symbol.escapedName === "this") { + let type: Type | undefined; + if (declaration.symbol!.escapedName === "this") { type = getContextualThisParameterType(func); } else { @@ -4182,8 +4198,8 @@ namespace ts { const types: Type[] = []; let definedInConstructor = false; let definedInMethod = false; - let jsDocType: Type; - for (const declaration of symbol.declarations) { + let jsDocType: Type | undefined; + for (const declaration of symbol.declarations!) { const expression = declaration.kind === SyntaxKind.BinaryExpression ? declaration : declaration.kind === SyntaxKind.PropertyAccessExpression ? getAncestor(declaration, SyntaxKind.BinaryExpression) : undefined; @@ -4243,7 +4259,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 hasComputedProperties = false; forEach(pattern.elements, e => { const name = e.propertyName || e.name; @@ -4278,7 +4294,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. @@ -4298,7 +4314,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); @@ -4361,7 +4377,7 @@ namespace ts { return links.type = getTypeOfPrototypeProperty(symbol); } // Handle catch clause variables - const declaration = symbol.valueDeclaration; + const declaration = symbol.valueDeclaration!; if (isCatchClauseVariableDeclarationOrBindingElement(declaration)) { return links.type = anyType; } @@ -4419,7 +4435,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()) { @@ -4430,7 +4446,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); @@ -4577,7 +4593,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); @@ -4639,34 +4655,36 @@ 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[], declarations: ReadonlyArray): TypeParameter[] { + function appendTypeParameters(typeParameters: TypeParameter[] | undefined, declarations: ReadonlyArray): TypeParameter[] | undefined { for (const declaration of declarations) { - const tp = getDeclaredTypeOfTypeParameter(getSymbolOfNode(declaration)); + const tp = getDeclaredTypeOfTypeParameter(getSymbolOfNode(declaration)!); typeParameters = appendIfUnique(typeParameters, tp); } return typeParameters; } // 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; } @@ -4690,7 +4708,7 @@ namespace ts { case SyntaxKind.ConditionalType: const outerTypeParameters = getOuterTypeParameters(node, includeThisTypes); if (node.kind === SyntaxKind.MappedType) { - return append(outerTypeParameters, getDeclaredTypeOfTypeParameter(getSymbolOfNode((node).typeParameter))); + return append(outerTypeParameters, getDeclaredTypeOfTypeParameter(getSymbolOfNode((node).typeParameter)!)); } else if (node.kind === SyntaxKind.ConditionalType) { return concatenate(outerTypeParameters, getInferTypeParameters(node)); @@ -4698,23 +4716,23 @@ namespace ts { const outerAndOwnTypeParameters = appendTypeParameters(outerTypeParameters, getEffectiveTypeParameterDeclarations(node) || emptyArray); const thisType = includeThisTypes && (node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassExpression || node.kind === SyntaxKind.InterfaceDeclaration) && - getDeclaredTypeOfClassOrInterface(getSymbolOfNode(node)).thisType; + getDeclaredTypeOfClassOrInterface(getSymbolOfNode(node)!).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[] { - let result: TypeParameter[]; - for (const node of symbol.declarations) { + function getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol: Symbol): TypeParameter[] | undefined { + let result: TypeParameter[] | undefined; + for (const node of symbol.declarations!) { if (node.kind === SyntaxKind.InterfaceDeclaration || node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassExpression || node.kind === SyntaxKind.TypeAliasDeclaration) { const declaration = node; @@ -4728,7 +4746,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)); } @@ -4749,13 +4767,13 @@ 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 { - const decl = type.symbol.valueDeclaration; + function getBaseTypeNodeOfClass(type: InterfaceType): ExpressionWithTypeArguments | undefined { + const decl = type.symbol!.valueDeclaration; if (isInJavaScriptFile(decl)) { // Prefer an @augments tag because it may have type parameters. const tag = getJSDocAugmentsTag(decl); @@ -4767,17 +4785,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); } /** @@ -4790,7 +4808,7 @@ namespace ts { */ function getBaseConstructorTypeOfClass(type: InterfaceType): Type { if (!type.resolvedBaseConstructorType) { - const decl = type.symbol.valueDeclaration; + const decl = type.symbol!.valueDeclaration; const extended = getClassExtendsHeritageClauseElement(decl); const baseTypeNode = getBaseTypeNodeOfClass(type); if (!baseTypeNode) { @@ -4810,7 +4828,7 @@ namespace ts { resolveStructuredTypeMembers(baseConstructorType); } if (!popTypeResolution()) { - error(type.symbol.valueDeclaration, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_base_expression, symbolToString(type.symbol)); + error(type.symbol!.valueDeclaration, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_base_expression, symbolToString(type.symbol!)); return type.resolvedBaseConstructorType = unknownType; } if (!(baseConstructorType.flags & TypeFlags.Any) && baseConstructorType !== nullWideningType && !isConstructorType(baseConstructorType)) { @@ -4825,13 +4843,13 @@ 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) { + else if (type.symbol!.flags & (SymbolFlags.Class | SymbolFlags.Interface)) { + if (type.symbol!.flags & SymbolFlags.Class) { resolveBaseTypesOfClass(type); } - if (type.symbol.flags & SymbolFlags.Interface) { + if (type.symbol!.flags & SymbolFlags.Interface) { resolveBaseTypesOfInterface(type); } } @@ -4848,12 +4866,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. @@ -4882,7 +4900,7 @@ namespace ts { return type.resolvedBaseTypes = emptyArray; } if (type === baseType || hasBaseType(baseType, type)) { - error(type.symbol.valueDeclaration, Diagnostics.Type_0_recursively_references_itself_as_a_base_type, + error(type.symbol!.valueDeclaration, Diagnostics.Type_0_recursively_references_itself_as_a_base_type, typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType)); return type.resolvedBaseTypes = emptyArray; } @@ -4891,18 +4909,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; @@ -4911,15 +4929,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) { + 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)) { @@ -4952,7 +4970,7 @@ namespace ts { * and if none of the base interfaces have a "this" type. */ function isThislessInterface(symbol: Symbol): boolean { - for (const declaration of symbol.declarations) { + for (const declaration of symbol.declarations!) { if (declaration.kind === SyntaxKind.InterfaceDeclaration) { if (declaration.flags & NodeFlags.ContainsThis) { return false; @@ -5012,7 +5030,7 @@ namespace ts { return unknownType; } - const declaration = find(symbol.declarations, d => + const declaration = find(symbol.declarations!, d => d.kind === SyntaxKind.JSDocTypedefTag || d.kind === SyntaxKind.TypeAliasDeclaration); const typeNode = declaration.kind === SyntaxKind.JSDocTypedefTag ? declaration.typeExpression : declaration.type; // If typeNode is missing, we will error in checkJSDocTypedefTag. @@ -5050,7 +5068,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); default: return false; } @@ -5062,7 +5080,7 @@ namespace ts { return links.enumKind; } let hasNonLiteralMember = false; - for (const declaration of symbol.declarations) { + for (const declaration of symbol.declarations!) { if (declaration.kind === SyntaxKind.EnumDeclaration) { for (const member of (declaration).members) { if (member.initializer && member.initializer.kind === SyntaxKind.StringLiteral) { @@ -5078,7 +5096,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 { @@ -5089,11 +5107,11 @@ namespace ts { if (getEnumKind(symbol) === EnumKind.Literal) { enumCount++; const memberTypeList: Type[] = []; - for (const declaration of symbol.declarations) { + 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)); - getSymbolLinks(getSymbolOfNode(member)).declaredType = memberType; + const memberType = getLiteralType(getEnumMemberValue(member)!, enumCount, getSymbolOfNode(member)); // TODO: GH#18217 + getSymbolLinks(getSymbolOfNode(member)!).declaredType = memberType; memberTypeList.push(memberType); } } @@ -5115,7 +5133,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; } @@ -5189,7 +5207,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; } @@ -5215,7 +5233,7 @@ namespace ts { */ function isThislessFunctionLikeDeclaration(node: FunctionLikeDeclaration): boolean { const returnType = getEffectiveReturnTypeNode(node); - return (node.kind === SyntaxKind.Constructor || (returnType && isThislessType(returnType))) && + return (node.kind === SyntaxKind.Constructor || (!!returnType && isThislessType(returnType))) && node.parameters.every(isThislessVariableLikeDeclaration) && (!node.typeParameters || node.typeParameters.every(isThislessTypeParameter)); } @@ -5265,7 +5283,7 @@ namespace ts { function resolveDeclaredMembers(type: InterfaceType): InterfaceTypeWithDeclaredMembers { if (!(type).declaredProperties) { - const symbol = type.symbol; + const symbol = type.symbol!; const members = getMembersOfSymbol(symbol); (type).declaredProperties = getNamedMembers(members); (type).declaredCallSignatures = getSignaturesOfSymbol(members.get(InternalSymbolName.Call)); @@ -5302,7 +5320,7 @@ namespace ts { */ function hasLateBindableName(node: Declaration): node is LateBoundDeclaration { const name = getNameOfDeclaration(node); - return name && isLateBindableName(name); + return !!name && isLateBindableName(name); } /** @@ -5324,7 +5342,7 @@ namespace ts { */ function getLateBoundNameFromType(type: LiteralType | UniqueESSymbolType) { if (type.flags & TypeFlags.UniqueESSymbol) { - return `__@${type.symbol.escapedName}@${getSymbolId(type.symbol)}` as __String; + return `__@${type.symbol!.escapedName}@${getSymbolId(type.symbol!)}` as __String; } if (type.flags & TypeFlags.StringOrNumberLiteral) { return escapeLeadingUnderscores("" + (type).value); @@ -5339,7 +5357,7 @@ namespace ts { function addDeclarationToLateBoundSymbol(symbol: Symbol, member: LateBoundDeclaration, symbolFlags: SymbolFlags) { Debug.assert(!!(getCheckFlags(symbol) & CheckFlags.Late), "Expected a late-bound symbol."); symbol.flags |= symbolFlags; - getSymbolLinks(member.symbol).lateSymbol = symbol; + getSymbolLinks(member.symbol!).lateSymbol = symbol; if (!symbol.declarations) { symbol.declarations = [member]; } @@ -5391,8 +5409,8 @@ namespace ts { links.resolvedSymbol = decl.symbol; const type = checkComputedPropertyName(decl.name); if (isTypeUsableAsLateBoundName(type)) { - const memberName = getLateBoundNameFromType(type); - const symbolFlags = decl.symbol.flags; + const memberName = getLateBoundNameFromType(type)!; // TODO: GH#18217 + const symbolFlags = decl.symbol!.flags; // Get or add a late-bound symbol for the member. This allows us to merge late-bound accessor declarations. let lateSymbol = lateSymbols.get(memberName); @@ -5420,7 +5438,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; @@ -5435,7 +5453,7 @@ namespace ts { // fill in any as-yet-unresolved late-bound members. const lateSymbols = createSymbolTable(); - for (const decl of symbol.declarations) { + for (const decl of symbol.declarations!) { const members = getMembersOfDeclaration(decl); if (members) { for (const member of members) { @@ -5449,7 +5467,7 @@ namespace ts { links[resolutionKind] = combineSymbolTables(earlySymbols, lateSymbols) || emptySymbols; } - return links[resolutionKind]; + return links[resolutionKind]!; } /** @@ -5475,10 +5493,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); @@ -5491,7 +5509,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; } } @@ -5505,9 +5523,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); @@ -5553,7 +5571,7 @@ 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); @@ -5561,7 +5579,7 @@ namespace ts { function createSignature( declaration: SignatureDeclaration, - typeParameters: TypeParameter[], + typeParameters: TypeParameter[] | undefined, thisParameter: Symbol | undefined, parameters: Symbol[], resolvedReturnType: Type | undefined, @@ -5594,9 +5612,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); @@ -5614,7 +5632,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; @@ -5622,7 +5640,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. @@ -5636,7 +5654,7 @@ namespace ts { } return [signature]; } - let result: Signature[] = undefined; + 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); @@ -5654,7 +5672,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[] = undefined; + 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 @@ -5666,8 +5684,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; @@ -5681,7 +5700,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) { @@ -5705,16 +5724,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); } @@ -5737,8 +5758,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++) { @@ -5770,13 +5791,13 @@ namespace ts { * Converts an AnonymousType to a ResolvedType. */ function resolveAnonymousTypeMembers(type: AnonymousType) { - const symbol = type.symbol; + 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) { @@ -5790,7 +5811,7 @@ namespace ts { else { // Combinations of function, class, enum and module let members = emptySymbols; - let stringIndexInfo: IndexInfo = undefined; + let stringIndexInfo: IndexInfo | undefined; if (symbol.exports) { members = getExportsOfSymbol(symbol); } @@ -5818,7 +5839,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); } @@ -5848,7 +5869,7 @@ 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 stringIndexInfo: 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, @@ -5858,7 +5879,7 @@ namespace ts { const templateType = getTemplateTypeFromMappedType(type.target || type); const modifiersType = getApparentType(getModifiersTypeFromMappedType(type)); // The 'T' in 'keyof T' const templateModifiers = getMappedTypeModifiers(type); - const constraintDeclaration = type.declaration.typeParameter.constraint; + const constraintDeclaration = type.declaration.typeParameter.constraint!; if (constraintDeclaration.kind === SyntaxKind.TypeOperator && (constraintDeclaration).operator === SyntaxKind.KeyOfKeyword) { // We have a { [P in keyof T]: X } @@ -5880,7 +5901,7 @@ namespace ts { setStructuredTypeMembers(type, members, emptyArray, emptyArray, stringIndexInfo, undefined); function addMemberForKeyType(t: Type, propertySymbolOrIndex?: Symbol | number) { - let propertySymbol: Symbol; + let propertySymbol: Symbol | undefined; // forEachType delegates to forEach, which calls with a numeric second argument // the type system currently doesn't catch this incompatibility, so we annotate // the function ourselves to indicate the runtime behavior and deal with it here @@ -5924,7 +5945,7 @@ namespace ts { function getTypeParameterFromMappedType(type: MappedType) { return type.typeParameter || - (type.typeParameter = getDeclaredTypeOfTypeParameter(getSymbolOfNode(type.declaration.typeParameter))); + (type.typeParameter = getDeclaredTypeOfTypeParameter(getSymbolOfNode(type.declaration.typeParameter)!)); } function getConstraintTypeFromMappedType(type: MappedType) { @@ -5941,7 +5962,7 @@ namespace ts { function getModifiersTypeFromMappedType(type: MappedType) { if (!type.modifiersType) { - const constraintDeclaration = type.declaration.typeParameter.constraint; + const constraintDeclaration = type.declaration.typeParameter.constraint!; if (constraintDeclaration.kind === SyntaxKind.TypeOperator && (constraintDeclaration).operator === SyntaxKind.KeyOfKeyword) { // If the constraint declaration is a 'keyof T' node, the modifiers type is T. We check @@ -5984,7 +6005,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 { @@ -6027,7 +6048,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); @@ -6086,14 +6107,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; } @@ -6138,7 +6159,7 @@ namespace ts { return getConstraintOfDistributiveConditionalType(type) || getDefaultConstraintOfConditionalType(type); } - function getBaseConstraintOfType(type: Type): Type { + function getBaseConstraintOfType(type: Type): Type | undefined { if (type.flags & (TypeFlags.InstantiableNonPrimitive | TypeFlags.UnionOrIntersection)) { const constraint = getResolvedBaseConstraint(type); if (constraint !== noConstraintType && constraint !== circularConstraintType) { @@ -6161,14 +6182,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; @@ -6181,7 +6202,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 ? @@ -6235,7 +6256,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. @@ -6295,7 +6316,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 @@ -6332,7 +6353,7 @@ namespace ts { } const propTypes: Type[] = []; const declarations: Declaration[] = []; - let commonType: Type = undefined; + let commonType: Type | undefined; for (const prop of props) { if (prop.declarations) { addRange(declarations, prop.declarations); @@ -6358,7 +6379,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) { @@ -6370,7 +6391,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; @@ -6436,17 +6457,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)) { @@ -6463,10 +6484,10 @@ namespace ts { // Return list of type parameters with duplicates removed (duplicate identifier errors are generated in the actual // type checking functions). - function getTypeParametersFromDeclaration(declaration: DeclarationWithTypeParameters): TypeParameter[] { - let result: TypeParameter[]; + function getTypeParametersFromDeclaration(declaration: DeclarationWithTypeParameters): TypeParameter[] | undefined { + let result: TypeParameter[] | undefined; forEach(getEffectiveTypeParameterDeclarations(declaration), node => { - const tp = getDeclaredTypeOfTypeParameter(node.symbol); + const tp = getDeclaredTypeOfTypeParameter(node.symbol!); result = appendIfUnique(result, tp); }); return result; @@ -6546,7 +6567,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 }; } @@ -6578,6 +6599,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) { @@ -6594,14 +6617,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 (defaultType && isTypeIdenticalTo(defaultType, emptyObjectType) && isJavaScriptImplicitAny) { defaultType = anyType; } typeArguments[i] = defaultType ? instantiateType(defaultType, mapper) : getDefaultTypeArgumentType(isJavaScriptImplicitAny); } - typeArguments.length = typeParameters.length; + typeArguments.length = typeParameters!.length; } } return typeArguments; @@ -6613,8 +6636,8 @@ namespace ts { const parameters: Symbol[] = []; let hasLiteralTypes = false; let minArgumentCount = 0; - let thisParameter: Symbol = undefined; - let hasThisParameter: boolean; + let thisParameter: Symbol | undefined; + let hasThisParameter = false; const iife = getImmediatelyInvokedFunctionExpression(declaration); const isJSConstructSignature = isJSDocConstructSignature(declaration); const isUntypedSignatureInJSFile = !iife && !isJSConstructSignature && isInJavaScriptFile(declaration) && !hasJSDocParameterTags(declaration); @@ -6631,12 +6654,12 @@ namespace ts { const resolvedSymbol = resolveName(param, paramSymbol.escapedName, SymbolFlags.Value, undefined, undefined, /*isUse*/ false); paramSymbol = resolvedSymbol; } - if (i === 0 && paramSymbol.escapedName === "this") { + if (i === 0 && paramSymbol!.escapedName === "this") { // TODO: GH#18217 hasThisParameter = true; thisParameter = param.symbol; } else { - parameters.push(paramSymbol); + parameters.push(paramSymbol!); } if (param.type && param.type.kind === SyntaxKind.LiteralType) { @@ -6658,14 +6681,14 @@ namespace ts { !hasNonBindableDynamicName(declaration) && (!hasThisParameter || !thisParameter)) { const otherKind = declaration.kind === SyntaxKind.GetAccessor ? SyntaxKind.SetAccessor : SyntaxKind.GetAccessor; - const other = getDeclarationOfKind(getSymbolOfNode(declaration), otherKind); + const other = getDeclarationOfKind(getSymbolOfNode(declaration)!, otherKind); if (other) { thisParameter = getAnnotatedAccessorThisParameter(other); } } const classType = declaration.kind === SyntaxKind.Constructor ? - getDeclaredTypeOfClassOrInterface(getMergedSymbol((declaration.parent).symbol)) + getDeclaredTypeOfClassOrInterface(getMergedSymbol((declaration.parent).symbol!)) : undefined; const typeParameters = classType ? classType.localTypeParameters : getTypeParametersFromDeclaration(declaration); const returnType = getSignatureReturnTypeFromDeclaration(declaration, isJSConstructSignature, classType); @@ -6698,9 +6721,9 @@ namespace ts { return true; } - function getSignatureReturnTypeFromDeclaration(declaration: SignatureDeclaration, isJSConstructSignature: boolean, classType: Type) { + function getSignatureReturnTypeFromDeclaration(declaration: SignatureDeclaration, isJSConstructSignature: boolean, classType: Type | undefined) { if (isJSConstructSignature) { - return getTypeFromTypeNode(declaration.parameters[0].type); + return getTypeFromTypeNode(declaration.parameters[0].type!); } else if (classType) { return classType; @@ -6714,7 +6737,7 @@ namespace ts { // TypeScript 1.0 spec (April 2014): // If only one accessor includes a type annotation, the other behaves as if it had the same type annotation. if (declaration.kind === SyntaxKind.GetAccessor && !hasNonBindableDynamicName(declaration)) { - const setter = getDeclarationOfKind(getSymbolOfNode(declaration), SyntaxKind.SetAccessor); + const setter = getDeclarationOfKind(getSymbolOfNode(declaration)!, SyntaxKind.SetAccessor); return getAnnotatedAccessorType(setter); } @@ -6726,11 +6749,11 @@ namespace ts { function containsArgumentsReference(declaration: SignatureDeclaration): boolean { const links = getNodeLinks(declaration); if (links.containsArgumentsReference === undefined) { - if (links.flags & NodeCheckFlags.CaptureArguments) { + if (links.flags! & NodeCheckFlags.CaptureArguments) { links.containsArgumentsReference = true; } else { - links.containsArgumentsReference = traverse((declaration as FunctionLikeDeclaration).body); + links.containsArgumentsReference = traverse((declaration as FunctionLikeDeclaration).body!); } } return links.containsArgumentsReference; @@ -6745,20 +6768,20 @@ 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 node = symbol.declarations[i]; + for (let i = 0; i < symbol.declarations!.length; i++) { + const node = symbol.declarations![i]; switch (node.kind) { case SyntaxKind.FunctionType: case SyntaxKind.ConstructorType: @@ -6778,7 +6801,7 @@ namespace ts { // an implementation node if it has a body and the previous node is of the same kind and immediately // precedes the implementation node (i.e. has the same parent and ends where the implementation starts). if (i > 0 && (node).body) { - const previous = symbol.declarations[i - 1]; + const previous = symbol.declarations![i - 1]; if (node.parent === previous.parent && node.kind === previous.kind && node.pos === previous.end) { break; } @@ -6815,7 +6838,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; @@ -6838,7 +6861,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); @@ -6870,15 +6893,15 @@ 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 { + 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); @@ -6889,8 +6912,8 @@ namespace ts { return instantiation; } - function createSignatureInstantiation(signature: Signature, typeArguments: Type[]): Signature { - return instantiateSignature(signature, createTypeMapper(signature.typeParameters, typeArguments), /*eraseTypeParameters*/ true); + function createSignatureInstantiation(signature: Signature, typeArguments: Type[] | undefined): Signature { + return instantiateSignature(signature, createTypeMapper(signature.typeParameters!, typeArguments), /*eraseTypeParameters*/ true); } function getErasedSignature(signature: Signature): Signature { @@ -6901,7 +6924,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 { @@ -6951,15 +6974,15 @@ 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): SignatureDeclaration { + function getIndexDeclarationOfSymbol(symbol: Symbol, kind: IndexKind): SignatureDeclaration | undefined { const syntaxKind = kind === IndexKind.Number ? SyntaxKind.NumberKeyword : SyntaxKind.StringKeyword; const indexSymbol = getIndexSymbol(symbol); if (indexSymbol) { - for (const decl of indexSymbol.declarations) { + for (const decl of indexSymbol.declarations!) { const node = decl; if (node.parameters.length === 1) { const parameter = node.parameters[0]; @@ -6977,7 +7000,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, @@ -6987,13 +7010,13 @@ namespace ts { } function getConstraintDeclaration(type: TypeParameter) { - return type.symbol && getDeclarationOfKind(type.symbol, SyntaxKind.TypeParameter).constraint; + return type.symbol && getDeclarationOfKind(type.symbol, SyntaxKind.TypeParameter)!.constraint; } function getInferredTypeParameterConstraint(typeParameter: TypeParameter) { - let inferences: Type[]; + let inferences: Type[] | undefined; if (typeParameter.symbol) { - for (const declaration of typeParameter.symbol.declarations) { + for (const declaration of typeParameter.symbol.declarations!) { // When an 'infer T' declaration is immediately contained in a type reference node // (such as 'Foo'), T's constraint is inferred from the constraint of the // corresponding type parameter in 'Foo'. When multiple 'infer T' declarations are @@ -7002,7 +7025,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) { @@ -7026,11 +7049,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); @@ -7041,11 +7064,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; @@ -7083,7 +7106,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) { @@ -7112,7 +7135,7 @@ namespace ts { /** * Get type from type-reference that reference to class or interface */ - function getTypeFromClassOrInterfaceReference(node: TypeReferenceType, symbol: Symbol, typeArgs: Type[]): Type { + function getTypeFromClassOrInterfaceReference(node: TypeReferenceType, symbol: Symbol, typeArgs: Type[] | undefined): Type { const type = getDeclaredTypeOfSymbol(getMergedSymbol(symbol)); const typeParameters = type.localTypeParameters; if (typeParameters) { @@ -7145,14 +7168,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; } @@ -7162,7 +7185,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: TypeReferenceType, symbol: Symbol, typeArguments: Type[]): Type { + function getTypeFromTypeAliasReference(node: TypeReferenceType, symbol: Symbol, typeArguments: Type[] | undefined): Type { const type = getDeclaredTypeOfSymbol(symbol); const typeParameters = getSymbolLinks(symbol).typeParameters; if (typeParameters) { @@ -7200,7 +7223,7 @@ namespace ts { return undefined; } - function resolveTypeReferenceName(typeReferenceName: EntityNameExpression | EntityName, meaning: SymbolFlags) { + function resolveTypeReferenceName(typeReferenceName: EntityNameExpression | EntityName | undefined, meaning: SymbolFlags) { if (!typeReferenceName) { return unknownSymbol; } @@ -7247,7 +7270,7 @@ namespace ts { return valueType; } - function getTypeReferenceTypeWorker(node: TypeReferenceType, symbol: Symbol, typeArguments: Type[]): Type | undefined { + function getTypeReferenceTypeWorker(node: TypeReferenceType, symbol: Symbol, typeArguments: Type[] | undefined): Type | undefined { if (symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) { return getTypeFromClassOrInterfaceReference(node, symbol, typeArguments); } @@ -7258,7 +7281,7 @@ namespace ts { if (symbol.flags & SymbolFlags.Function && isJSDocTypeReference(node) && - (symbol.members || getJSDocClassTag(symbol.valueDeclaration))) { + (symbol.members || getJSDocClassTag(symbol.valueDeclaration!))) { return getInferredClassType(symbol); } } @@ -7271,7 +7294,7 @@ namespace ts { } function getConstrainedTypeParameter(typeParameter: TypeParameter, node: Node) { - let constraints: Type[]; + let constraints: Type[] | undefined; while (isPartOfTypeNode(node)) { const parent = node.parent; if (parent.kind === SyntaxKind.ConditionalType && node === (parent).trueType) { @@ -7285,7 +7308,7 @@ namespace ts { } function isJSDocTypeReference(node: TypeReferenceType): node is TypeReferenceNode { - return node.flags & NodeFlags.JSDoc && node.kind === SyntaxKind.TypeReference; + return !!(node.flags & NodeFlags.JSDoc) && node.kind === SyntaxKind.TypeReference; } function checkNoTypeArguments(node: TypeReferenceType, symbol?: Symbol) { @@ -7296,7 +7319,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) { @@ -7334,7 +7357,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; } @@ -7352,8 +7375,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); @@ -7371,7 +7394,7 @@ namespace ts { return links.resolvedType; } - function typeArgumentsFromTypeReferenceNode(node: TypeReferenceType): Type[] { + function typeArgumentsFromTypeReferenceNode(node: TypeReferenceType): Type[] | undefined { return map(node.typeArguments, getTypeFromTypeNode); } @@ -7387,10 +7410,10 @@ 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 { - const declarations = symbol.declarations; + function getTypeDeclaration(symbol: Symbol): Declaration | undefined { + const declarations = symbol.declarations!; for (const declaration of declarations) { switch (declaration.kind) { case SyntaxKind.ClassDeclaration: @@ -7416,22 +7439,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; } @@ -7488,7 +7511,7 @@ 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); } @@ -7497,9 +7520,9 @@ namespace ts { * Returns a type that is inside a namespace at the global scope, e.g. * getExportedTypeFromNamespace('JSX', 'Element') returns the JSX.Element type */ - function getExportedTypeFromNamespace(namespace: __String, name: __String): Type { + function getExportedTypeFromNamespace(namespace: __String, name: __String): Type | undefined { const namespaceSymbol = getGlobalSymbol(namespace, SymbolFlags.Namespace, /*diagnosticMessage*/ undefined); - const typeSymbol = namespaceSymbol && getSymbol(namespaceSymbol.exports, name, SymbolFlags.Type); + const typeSymbol = namespaceSymbol && getSymbol(namespaceSymbol.exports!, name, SymbolFlags.Type); return typeSymbol && getDeclaredTypeOfSymbol(typeSymbol); } @@ -7688,10 +7711,10 @@ namespace ts { function isSetOfLiteralsFromSameEnum(types: Type[]): boolean { const first = types[0]; if (first.flags & TypeFlags.EnumLiteral) { - const firstEnum = getParentOfSymbol(first.symbol); + const firstEnum = getParentOfSymbol(first.symbol!); for (let i = 1; i < types.length; i++) { const other = types[i]; - if (!(other.flags & TypeFlags.EnumLiteral) || (firstEnum !== getParentOfSymbol(other.symbol))) { + if (!(other.flags & TypeFlags.EnumLiteral) || (firstEnum !== getParentOfSymbol(other.symbol!))) { return false; } } @@ -7723,7 +7746,7 @@ namespace ts { t.flags & TypeFlags.StringLiteral && includes & TypeIncludes.String || t.flags & TypeFlags.NumberLiteral && includes & TypeIncludes.Number || t.flags & TypeFlags.UniqueESSymbol && includes & TypeIncludes.ESSymbol || - t.flags & TypeFlags.StringOrNumberLiteral && t.flags & TypeFlags.FreshLiteral && containsType(types, (t).regularType); + t.flags & TypeFlags.StringOrNumberLiteral && t.flags & TypeFlags.FreshLiteral && containsType(types, (t).regularType!); if (remove) { orderedRemoveItemAt(types, i); } @@ -7767,7 +7790,7 @@ namespace ts { return getUnionTypeFromSortedList(typeSet, 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) { @@ -7966,7 +7989,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) { @@ -7980,7 +8003,7 @@ namespace ts { break; } } - return links.resolvedType; + return links.resolvedType!; // TODO: GH#18217 } function createIndexedAccessType(objectType: Type, indexType: Type) { @@ -7990,10 +8013,10 @@ 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) ? + accessExpression && checkThatExpressionIsProperSymbolReference(accessExpression.argumentExpression!, indexType, /*reportError*/ false) ? getPropertyNameForKnownSymbolName(idText((accessExpression.argumentExpression).name)) : undefined; if (propName !== undefined) { @@ -8006,7 +8029,7 @@ namespace ts { return unknownType; } if (cacheSymbol) { - getNodeLinks(accessNode).resolvedSymbol = prop; + getNodeLinks(accessNode!).resolvedSymbol = prop; } } return getTypeOfSymbol(prop); @@ -8063,23 +8086,23 @@ 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; } // Transform an indexed access to a simpler form, if possible. Return the simpler form, or return // undefined if no transformation is possible. - function getSimplifiedIndexedAccessType(type: IndexedAccessType): Type { + function getSimplifiedIndexedAccessType(type: IndexedAccessType): Type | undefined { const objectType = type.objectType; if (objectType.flags & TypeFlags.Intersection && isGenericObjectType(objectType)) { // Given an indexed access type T[K], if T is an intersection containing one or more generic types and one or @@ -8091,7 +8114,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)!); // TODO: GH#18217 } else { regularTypes.push(t); @@ -8196,7 +8219,7 @@ namespace ts { return type.flags & TypeFlags.Substitution ? (type).typeParameter : type; } - function createConditionalType(checkType: Type, extendsType: Type, trueType: Type, falseType: Type, inferTypeParameters: TypeParameter[], target: ConditionalType, mapper: TypeMapper, aliasSymbol: Symbol, aliasTypeArguments: Type[]) { + function createConditionalType(checkType: Type, extendsType: Type, trueType: Type, falseType: Type, inferTypeParameters: TypeParameter[] | undefined, target: ConditionalType | undefined, mapper: TypeMapper, aliasSymbol: Symbol | undefined, aliasTypeArguments: Type[] | undefined) { const type = createType(TypeFlags.Conditional); type.checkType = checkType; type.extendsType = extendsType; @@ -8210,7 +8233,7 @@ namespace ts { return type; } - function getConditionalType(checkType: Type, baseExtendsType: Type, baseTrueType: Type, baseFalseType: Type, inferTypeParameters: TypeParameter[], target: ConditionalType, mapper: TypeMapper, aliasSymbol?: Symbol, baseAliasTypeArguments?: Type[]): Type { + function getConditionalType(checkType: Type, baseExtendsType: Type, baseTrueType: Type, baseFalseType: Type, inferTypeParameters: TypeParameter[] | undefined, target: ConditionalType | undefined, mapper: TypeMapper, aliasSymbol?: Symbol, baseAliasTypeArguments?: Type[]): Type { // Instantiate extends type without instantiating any 'infer T' type parameters const extendsType = instantiateType(baseExtendsType, mapper); // Return falseType for a definitely false extends check. We check an instantations of the two @@ -8221,7 +8244,7 @@ namespace ts { return instantiateType(baseFalseType, mapper); } // The check could be true for some instantiation - let combinedMapper: TypeMapper; + let combinedMapper: TypeMapper | undefined; if (inferTypeParameters) { const inferences = map(inferTypeParameters, createInferenceInfo); // We don't want inferences from constraints as they may cause us to eagerly resolve the @@ -8268,8 +8291,8 @@ namespace ts { return !!((type.target || type).checkType.flags & TypeFlags.TypeParameter); } - 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) { @@ -8286,7 +8309,7 @@ namespace ts { links.resolvedType = getConditionalType( getTypeFromTypeNode(node.checkType), getTypeFromTypeNode(node.extendsType), getTypeFromTypeNode(node.trueType), getTypeFromTypeNode(node.falseType), - getInferTypeParameters(node), /*target*/ undefined, /*mapper*/ undefined, + getInferTypeParameters(node), /*target*/ undefined, /*mapper*/ undefined!, // TODO: GH#18217 getAliasSymbolForTypeNode(node), getAliasTypeArgumentsForTypeNode(node)); } return links.resolvedType; @@ -8295,7 +8318,7 @@ namespace ts { function getTypeFromInferTypeNode(node: InferTypeNode): Type { const links = getNodeLinks(node); if (!links.resolvedType) { - links.resolvedType = getDeclaredTypeOfTypeParameter(getSymbolOfNode(node.typeParameter)); + links.resolvedType = getDeclaredTypeOfTypeParameter(getSymbolOfNode(node.typeParameter)!); } return links.resolvedType; } @@ -8305,7 +8328,7 @@ namespace ts { if (!links.resolvedType) { // Deferred resolution of members is handled by resolveObjectTypeMembers const aliasSymbol = getAliasSymbolForTypeNode(node); - if (getMembersOfSymbol(node.symbol).size === 0 && !aliasSymbol) { + if (getMembersOfSymbol(node.symbol!).size === 0 && !aliasSymbol) { links.resolvedType = emptyTypeLiteralType; } else { @@ -8335,7 +8358,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; } @@ -8357,8 +8380,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); @@ -8387,10 +8410,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)]); @@ -8429,7 +8452,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); } @@ -8437,30 +8460,30 @@ namespace ts { } function isClassMethod(prop: Symbol) { - return prop.flags & SymbolFlags.Method && find(prop.declarations, decl => isClassLike(decl.parent)); + 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.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); freshType.regularType = type; (type).freshType = freshType; } - return (type).freshType; + return (type).freshType!; } return type; } - function getRegularTypeOfLiteralType(type: Type) { - return type.flags & TypeFlags.StringOrNumberLiteral && type.flags & TypeFlags.FreshLiteral ? (type).regularType : type; + function getRegularTypeOfLiteralType(type: Type): Type { + return type.flags & TypeFlags.StringOrNumberLiteral && type.flags & TypeFlags.FreshLiteral ? (type).regularType! : type; } function getLiteralType(value: string | number, enumId?: number, symbol?: Symbol) { @@ -8494,7 +8517,7 @@ namespace ts { function getESSymbolLikeTypeForNode(node: Node) { if (isValidESSymbolDeclaration(node)) { - const symbol = getSymbolOfNode(node); + const symbol = getSymbolOfNode(node)!; const links = getSymbolLinks(symbol); return links.uniqueESSymbolType || (links.uniqueESSymbolType = createUniqueESSymbolType(symbol)); } @@ -8506,8 +8529,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)!).thisType!; } } error(node, Diagnostics.A_this_type_is_available_only_in_a_non_static_member_of_a_class_or_interface); @@ -8597,13 +8620,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]; @@ -8621,11 +8646,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); } @@ -8637,7 +8664,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]) { @@ -8648,7 +8675,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) : @@ -8714,7 +8741,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 @@ -8752,8 +8779,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. @@ -8772,8 +8799,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.symbol!; const links = getSymbolLinks(symbol); let typeParameters = links.outerTypeParameters; if (!typeParameters) { @@ -8781,7 +8808,7 @@ namespace ts { // parameters that are in scope (and therefore potentially referenced). For type literals that // aren't the right hand side of a generic type alias declaration we optimize by reducing the // set of type parameters to those that are possibly referenced in the literal. - const declaration = symbol.declarations[0]; + const declaration = symbol.declarations![0]; const outerTypeParameters = getOuterTypeParameters(declaration, /*includeThisTypes*/ true) || emptyArray; typeParameters = symbol.flags & SymbolFlags.TypeLiteral && !target.aliasTypeArguments ? filter(outerTypeParameters, tp => isTypeParameterPossiblyReferenced(tp, declaration)) : @@ -8796,41 +8823,41 @@ 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; } return type; } - function isTypeParameterPossiblyReferenced(tp: TypeParameter, node: Node) { + function isTypeParameterPossiblyReferenced(tp: TypeParameter, node: Node): boolean { // If the type parameter doesn't have exactly one declaration, if there are invening statement blocks // between the node and the type parameter declaration, if the node contains actual references to the // type parameter, or if the node contains type queries, we consider the type parameter possibly referenced. 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) && getTypeFromTypeNode(node) === tp; case SyntaxKind.TypeQuery: return true; } - return forEachChild(node, containsReference); + return !!forEachChild(node, containsReference); } } @@ -8895,7 +8922,9 @@ namespace ts { type.inferTypeParameters, type, mapper, type.aliasSymbol, type.aliasTypeArguments); } - function instantiateType(type: Type, mapper: TypeMapper): Type { + function instantiateType(type: Type, mapper: TypeMapper): Type; + function instantiateType(type: Type | undefined, mapper: TypeMapper): Type | undefined; + function instantiateType(type: Type | undefined, mapper: TypeMapper): Type | undefined { if (type && mapper && mapper !== identityMapper) { if (type.flags & TypeFlags.TypeParameter) { return mapper(type); @@ -8948,7 +8977,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); } @@ -8962,9 +8991,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); @@ -8972,29 +9001,33 @@ namespace ts { return (node).operatorToken.kind === SyntaxKind.BarBarToken && (isContextSensitive((node).left) || isContextSensitive((node).right)); case SyntaxKind.PropertyAssignment: - return isContextSensitive((node).initializer); + return isContextSensitive((node).initializer!); 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) { @@ -9007,7 +9040,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 { @@ -9088,7 +9122,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); } @@ -9117,7 +9151,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) { @@ -9146,7 +9180,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; } @@ -9175,11 +9209,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])); } @@ -9204,7 +9239,7 @@ namespace ts { } 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; } @@ -9228,12 +9263,12 @@ namespace ts { sourceDeclaration: SignatureDeclaration, targetDeclaration: SignatureDeclaration, 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; } @@ -9244,8 +9279,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; } @@ -9253,7 +9288,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; } @@ -9312,8 +9347,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; } @@ -9363,12 +9398,12 @@ namespace ts { (source).value === (target).value) return true; if (s & TypeFlags.BooleanLike && t & TypeFlags.Boolean) return true; if (s & TypeFlags.ESSymbolLike && t & TypeFlags.ESSymbol) return true; - if (s & TypeFlags.Enum && t & TypeFlags.Enum && isEnumTypeRelatedTo(source.symbol, target.symbol, errorReporter)) return true; + if (s & TypeFlags.Enum && t & TypeFlags.Enum && isEnumTypeRelatedTo(source.symbol!, target.symbol!, errorReporter)) return true; if (s & TypeFlags.EnumLiteral && t & TypeFlags.EnumLiteral) { - if (s & TypeFlags.Union && t & TypeFlags.Union && isEnumTypeRelatedTo(source.symbol, target.symbol, errorReporter)) return true; + 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; @@ -9387,10 +9422,10 @@ namespace ts { function isTypeRelatedTo(source: Type, target: Type, relation: Map) { if (source.flags & TypeFlags.StringOrNumberLiteral && source.flags & TypeFlags.FreshLiteral) { - source = (source).regularType; + source = (source).regularType!; } if (target.flags & TypeFlags.StringOrNumberLiteral && target.flags & TypeFlags.FreshLiteral) { - target = (target).regularType; + target = (target).regularType!; } if (source === target || relation === comparableRelation && !(target.flags & TypeFlags.Never) && isSimpleTypeRelatedTo(target, source, relation) || @@ -9427,11 +9462,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[]; @@ -9455,13 +9490,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)); @@ -9475,7 +9510,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) { @@ -9535,12 +9570,12 @@ 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; + source = (source).regularType!; } if (target.flags & TypeFlags.StringOrNumberLiteral && target.flags & TypeFlags.FreshLiteral) { - target = (target).regularType; + target = (target).regularType!; } if (source.flags & TypeFlags.Substitution) { source = relation === definitelyAssignableRelation ? (source).typeParameter : (source).substitute; @@ -9716,14 +9751,14 @@ namespace ts { // Use this property as the error node as this will be more helpful in // reasoning about what went wrong. Debug.assert(!!errorNode); - if (isJsxAttributes(errorNode) || isJsxOpeningLikeElement(errorNode)) { + 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. reportError(Diagnostics.Property_0_does_not_exist_on_type_1, symbolToString(prop), typeToString(target)); } else { // use the property's value declaration if the property is assigned inside the literal itself - const objectLiteralDeclaration = source.symbol && firstOrUndefined(source.symbol.declarations); + const objectLiteralDeclaration = source.symbol && firstOrUndefined(source.symbol.declarations!); let suggestion; if (prop.valueDeclaration && findAncestor(prop.valueDeclaration, d => d === objectLiteralDeclaration)) { const propDeclaration = prop.valueDeclaration as ObjectLiteralElementLike; @@ -9731,8 +9766,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); } } @@ -9786,7 +9822,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); @@ -9976,7 +10012,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]. @@ -10399,7 +10435,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 { @@ -10480,7 +10516,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); } @@ -10497,7 +10533,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; @@ -10617,7 +10653,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; } } @@ -10629,7 +10665,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)); } /** @@ -10638,7 +10674,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) { @@ -10676,9 +10712,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) { @@ -10692,12 +10728,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; @@ -10862,7 +10898,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) { @@ -10881,7 +10917,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 { @@ -10896,11 +10932,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 { @@ -10911,7 +10947,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; } @@ -10953,7 +10989,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)); } @@ -11038,7 +11074,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; @@ -11088,16 +11124,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, resolvedPropertyNames: 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); @@ -11125,7 +11161,7 @@ namespace ts { return context.resolvedPropertyNames; } - 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); @@ -11143,7 +11179,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 @@ -11168,7 +11204,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; @@ -11218,7 +11254,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; } @@ -11274,7 +11310,7 @@ namespace ts { default: diagnostic = Diagnostics.Variable_0_implicitly_has_an_1_type; } - error(declaration, diagnostic, declarationNameToString(getNameOfDeclaration(declaration)), typeAsString); + error(declaration, diagnostic, declarationNameToString(getNameOfDeclaration(declaration)!), typeAsString); } function reportErrorsFromWidening(declaration: Declaration, type: Type) { @@ -11308,7 +11344,7 @@ namespace ts { } function createInferenceContext(signature: Signature, flags: InferenceFlags, compareTypes?: TypeComparer, baseInferences?: InferenceInfo[]): InferenceContext { - const inferences = baseInferences ? map(baseInferences, cloneInferenceInfo) : map(signature.typeParameters, createInferenceInfo); + const inferences = baseInferences ? map(baseInferences, cloneInferenceInfo) : map(signature.typeParameters!, createInferenceInfo); const context = mapper as InferenceContext; context.signature = signature; context.inferences = inferences; @@ -11365,13 +11401,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` */ @@ -11400,7 +11436,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); @@ -11474,7 +11510,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]); } @@ -11496,7 +11532,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); @@ -11590,7 +11626,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)) { @@ -11607,7 +11643,7 @@ namespace ts { if (typeVariableCount === 1) { const savePriority = priority; priority |= InferencePriority.NakedTypeVariable; - inferFromTypes(source, typeVariable); + inferFromTypes(source, typeVariable!); priority = savePriority; } } @@ -11796,7 +11832,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) { @@ -11833,7 +11869,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.ReturnType ? + const unwidenedType = context.flags & InferenceFlags.InferUnionTypes || inference.priority! & InferencePriority.ReturnType ? getUnionType(baseCandidates, UnionReduction.Subtype) : getCommonSupertype(baseCandidates); inferredType = getWidenedType(unwidenedType); @@ -11863,7 +11899,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 { @@ -11874,7 +11910,7 @@ namespace ts { inferredType = getWidenedUniqueESSymbolType(inferredType); inference.inferredType = inferredType; - const constraint = getConstraintOfTypeParameter(context.signature.typeParameters[index]); + const constraint = getConstraintOfTypeParameter(context.signature.typeParameters![index]); if (constraint) { const instantiatedConstraint = instantiateType(constraint, context); if (!context.compareTypes(inferredType, getTypeWithThisArgument(instantiatedConstraint, inferredType))) { @@ -11955,7 +11991,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: @@ -11971,7 +12008,7 @@ namespace ts { } } else { - return "" + element.parent.elements.indexOf(element); + return "" + parent.elements.indexOf(element); } } @@ -11998,7 +12035,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; @@ -12024,7 +12061,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)); } @@ -12035,12 +12072,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; } @@ -12049,7 +12086,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) { @@ -12244,11 +12281,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; @@ -12278,7 +12315,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) { @@ -12316,7 +12353,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); } @@ -12337,7 +12374,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 ? @@ -12392,7 +12429,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); } @@ -12408,13 +12445,15 @@ 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.Union)) { 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) { @@ -12541,7 +12580,7 @@ namespace ts { (parent.parent).operatorToken.kind === SyntaxKind.EqualsToken && (parent.parent).left === parent && !isAssignmentTarget(parent.parent) && - isTypeAssignableToKind(getTypeOfExpression((parent).argumentExpression), TypeFlags.NumberLike); + isTypeAssignableToKind(getTypeOfExpression((parent).argumentExpression!), TypeFlags.NumberLike); return isLengthPushOrUnshift || isElementAssignment; } @@ -12572,7 +12611,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; @@ -12615,7 +12654,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; @@ -12642,8 +12681,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 ? @@ -12661,7 +12700,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. @@ -12715,7 +12754,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 ? @@ -12732,7 +12771,7 @@ namespace ts { } } else { - const indexType = getTypeOfExpression((node.left).argumentExpression); + const indexType = getTypeOfExpression((node.left).argumentExpression!); if (isTypeAssignableToKind(indexType, TypeFlags.NumberLike)) { evolvedType = addEvolvingArrayElementType(evolvedType, node.right); } @@ -12786,7 +12825,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. @@ -12849,11 +12888,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--; @@ -12885,7 +12924,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); @@ -12903,7 +12942,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 { @@ -13092,7 +13131,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 @@ -13109,7 +13148,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; } @@ -13249,15 +13288,15 @@ 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. function isParameterAssigned(symbol: Symbol) { - const func = getRootDeclaration(symbol.valueDeclaration).parent; + const func = getRootDeclaration(symbol.valueDeclaration!).parent; const links = getNodeLinks(func); - if (!(links.flags & NodeCheckFlags.AssignmentsMarked)) { - links.flags |= NodeCheckFlags.AssignmentsMarked; + if (!(links.flags! & NodeCheckFlags.AssignmentsMarked)) { + links.flags! |= NodeCheckFlags.AssignmentsMarked; if (!hasParentWithAssignmentsMarked(func)) { markParameterAssignments(func); } @@ -13266,7 +13305,7 @@ namespace ts { } function hasParentWithAssignmentsMarked(node: Node) { - return !!findAncestor(node.parent, node => isFunctionLike(node) && !!(getNodeLinks(node).flags & NodeCheckFlags.AssignmentsMarked)); + return !!findAncestor(node.parent, node => isFunctionLike(node) && !!(getNodeLinks(node).flags! & NodeCheckFlags.AssignmentsMarked)); } function markParameterAssignments(node: Node) { @@ -13298,7 +13337,7 @@ namespace ts { } function isApparentTypePosition(node: Node) { - const parent = node.parent; + const { parent } = node; return parent.kind === SyntaxKind.PropertyAccessExpression || parent.kind === SyntaxKind.CallExpression && (parent).expression === node || parent.kind === SyntaxKind.ElementAccessExpression && (parent).expression === node || @@ -13340,7 +13379,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); @@ -13350,7 +13389,7 @@ namespace ts { } } - getNodeLinks(container).flags |= NodeCheckFlags.CaptureArguments; + getNodeLinks(container).flags! |= NodeCheckFlags.CaptureArguments; return getTypeOfSymbol(symbol); } @@ -13367,29 +13406,29 @@ namespace ts { // Due to the emit for class decorators, any reference to the class from inside of the class body // must instead be rewritten to point to a temporary variable to avoid issues with the double-bind // behavior of class names in ES6. - if (declaration.kind === SyntaxKind.ClassDeclaration + if (declaration!.kind === SyntaxKind.ClassDeclaration && nodeIsDecorated(declaration as ClassDeclaration)) { let container = getContainingClass(node); while (container !== undefined) { if (container === declaration && container.name !== node) { - getNodeLinks(declaration).flags |= NodeCheckFlags.ClassWithConstructorReference; - getNodeLinks(node).flags |= NodeCheckFlags.ConstructorReferenceInClass; + getNodeLinks(declaration).flags! |= NodeCheckFlags.ClassWithConstructorReference; + getNodeLinks(node).flags! |= NodeCheckFlags.ConstructorReferenceInClass; break; } container = getContainingClass(container); } } - else if (declaration.kind === SyntaxKind.ClassExpression) { + else if (declaration!.kind === SyntaxKind.ClassExpression) { // When we emit a class expression with static members that contain a reference // 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; - getNodeLinks(node).flags |= NodeCheckFlags.ConstructorReferenceInClass; + getNodeLinks(declaration).flags! |= NodeCheckFlags.ClassWithConstructorReference; + getNodeLinks(node).flags! |= NodeCheckFlags.ConstructorReferenceInClass; } break; } @@ -13428,7 +13467,7 @@ namespace ts { } } else if (isAlias) { - declaration = find(symbol.declarations, isSomeImportDeclaration); + declaration = find(symbol.declarations!, isSomeImportDeclaration); } else { return type; @@ -13494,7 +13533,7 @@ namespace ts { function checkNestedBlockScopedBinding(node: Identifier, symbol: Symbol): void { if (languageVersion >= ScriptTarget.ES2015 || (symbol.flags & (SymbolFlags.BlockScopedVariable | SymbolFlags.Class)) === 0 || - symbol.valueDeclaration.parent.kind === SyntaxKind.CatchClause) { + symbol.valueDeclaration!.parent.kind === SyntaxKind.CatchClause) { return; } @@ -13503,7 +13542,7 @@ namespace ts { // 2. walk from the declaration up to the boundary of lexical environment and check // if there is an iteration statement in between declaration and boundary (is binding/class declared inside iteration statement) - const container = getEnclosingBlockScopeContainer(symbol.valueDeclaration); + const container = getEnclosingBlockScopeContainer(symbol.valueDeclaration!); const usedInFunction = isInsideFunction(node.parent, container); let current = container; @@ -13519,23 +13558,23 @@ namespace ts { if (containedInIterationStatement) { if (usedInFunction) { // mark iteration statement as containing block-scoped binding captured in some function - getNodeLinks(current).flags |= NodeCheckFlags.LoopWithCapturedBlockScopedBinding; + getNodeLinks(current).flags! |= NodeCheckFlags.LoopWithCapturedBlockScopedBinding; } // 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; + getNodeLinks(symbol.valueDeclaration!).flags! |= NodeCheckFlags.NeedsLoopOutParameter; } // set 'declared inside loop' bit on the block-scoped binding - getNodeLinks(symbol.valueDeclaration).flags |= NodeCheckFlags.BlockScopedBindingInLoop; + getNodeLinks(symbol.valueDeclaration!).flags! |= NodeCheckFlags.BlockScopedBindingInLoop; } if (usedInFunction) { - getNodeLinks(symbol.valueDeclaration).flags |= NodeCheckFlags.CapturedBlockScopedBinding; + getNodeLinks(symbol.valueDeclaration!).flags! |= NodeCheckFlags.CapturedBlockScopedBinding; } } @@ -13566,13 +13605,13 @@ namespace ts { } function captureLexicalThis(node: Node, container: Node): void { - getNodeLinks(node).flags |= NodeCheckFlags.LexicalThis; + getNodeLinks(node).flags! |= NodeCheckFlags.LexicalThis; if (container.kind === SyntaxKind.PropertyDeclaration || container.kind === SyntaxKind.Constructor) { const classNode = container.parent; - getNodeLinks(classNode).flags |= NodeCheckFlags.CaptureThis; + getNodeLinks(classNode).flags! |= NodeCheckFlags.CaptureThis; } else { - getNodeLinks(container).flags |= NodeCheckFlags.CaptureThis; + getNodeLinks(container).flags! |= NodeCheckFlags.CaptureThis; } } @@ -13597,10 +13636,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!; } /** @@ -13609,7 +13648,7 @@ namespace ts { * @param classDecl a class declaration to check if it extends null */ function classDeclarationExtendsNull(classDecl: ClassDeclaration): boolean { - const classSymbol = getSymbolOfNode(classDecl); + const classSymbol = getSymbolOfNode(classDecl)!; const classInstanceType = getDeclaredTypeOfSymbol(classSymbol); const baseConstructorType = getBaseConstructorTypeOfClass(classInstanceType); @@ -13724,8 +13763,8 @@ namespace ts { } if (isClassLike(container.parent)) { - const symbol = getSymbolOfNode(container.parent); - const type = hasModifier(container, ModifierFlags.Static) ? getTypeOfSymbol(symbol) : (getDeclaredTypeOfSymbol(symbol)).thisType; + const symbol = getSymbolOfNode(container.parent)!; + const type = hasModifier(container, ModifierFlags.Static) ? getTypeOfSymbol(symbol) : (getDeclaredTypeOfSymbol(symbol)).thisType!; return getFlowTypeOfReference(node, type); } @@ -13744,7 +13783,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!); } } } @@ -13803,7 +13842,7 @@ namespace ts { nodeCheckFlag = NodeCheckFlags.SuperInstance; } - getNodeLinks(node).flags |= nodeCheckFlag; + getNodeLinks(node).flags! |= nodeCheckFlag; // Due to how we emit async functions, we need to specialize the emit for an async method that contains a `super` reference. // This is due to the fact that we emit the body of an async function inside of a generator function. As generator @@ -13863,10 +13902,10 @@ namespace ts { // while a property access can. if (container.kind === SyntaxKind.MethodDeclaration && hasModifier(container, ModifierFlags.Async)) { if (isSuperProperty(node.parent) && isAssignmentTarget(node.parent)) { - getNodeLinks(container).flags |= NodeCheckFlags.AsyncMethodWithSuperBinding; + getNodeLinks(container).flags! |= NodeCheckFlags.AsyncMethodWithSuperBinding; } else { - getNodeLinks(container).flags |= NodeCheckFlags.AsyncMethodWithSuper; + getNodeLinks(container).flags! |= NodeCheckFlags.AsyncMethodWithSuper; } } @@ -13895,7 +13934,7 @@ namespace ts { return unknownType; } - const classType = getDeclaredTypeOfSymbol(getSymbolOfNode(classLikeDeclaration)); + const classType = getDeclaredTypeOfSymbol(getSymbolOfNode(classLikeDeclaration)!); const baseClassType = classType && getBaseTypes(classType)[0]; if (!baseClassType) { return unknownType; @@ -13959,17 +13998,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: FunctionLike): Type { + function getContextualThisParameterType(func: FunctionLike): Type | undefined { if (func.kind === SyntaxKind.ArrowFunction) { return undefined; } @@ -14010,7 +14049,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) { @@ -14071,7 +14110,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)); } } } @@ -14086,7 +14125,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); @@ -14119,7 +14158,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); @@ -14135,7 +14174,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); @@ -14166,7 +14205,7 @@ namespace ts { return false; } - function getContextualReturnType(functionDecl: FunctionLike): Type { + function getContextualReturnType(functionDecl: FunctionLike): 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 || @@ -14186,8 +14225,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); } @@ -14242,7 +14281,7 @@ namespace ts { case SpecialPropertyAssignmentKind.ThisProperty: return false; default: - Debug.assertNever(kind); + return Debug.assertNever(kind); } } @@ -14265,7 +14304,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 @@ -14283,14 +14322,14 @@ namespace ts { // For a (non-symbol) computed property, there is no reason to look up the name // in the type. It will just be "__computed", which does not appear in any // SymbolTable. - const symbolName = getSymbolOfNode(element).escapedName; + const symbolName = getSymbolOfNode(element)!.escapedName; const propertyType = getTypeOfPropertyOfContextualType(type, symbolName); if (propertyType) { return propertyType; } } - return isNumericName(element.name) && getIndexTypeOfContextualType(type, IndexKind.Number) || + return isNumericName(element.name!) && getIndexTypeOfContextualType(type, IndexKind.Number) || getIndexTypeOfContextualType(type, IndexKind.String); } @@ -14309,7 +14348,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; } @@ -14321,7 +14360,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) @@ -14348,7 +14387,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))) { @@ -14359,10 +14398,10 @@ namespace ts { propLoop: for (const prop of node.properties) { if (!prop.symbol) continue; if (prop.kind !== SyntaxKind.PropertyAssignment) continue; - if (isDiscriminantProperty(contextualType, prop.symbol.escapedName)) { - const discriminatingType = getTypeOfNode(prop.initializer); + if (isDiscriminantProperty(contextualType, prop.symbol!.escapedName)) { + const discriminatingType = getTypeOfNode(prop.initializer!)!; // TODO: GH#18217 for (const type of (contextualType as UnionType).types) { - const targetType = getTypeOfPropertyOfType(type, prop.symbol.escapedName); + const targetType = getTypeOfPropertyOfType(type, prop.symbol!.escapedName); if (targetType && checkTypeAssignableTo(discriminatingType, targetType, /*errorNode*/ undefined)) { if (match) { if (type === match) continue; // Finding multiple fields which discriminate to the same type is fine @@ -14402,7 +14441,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: @@ -14441,7 +14480,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); @@ -14456,8 +14495,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) { @@ -14562,7 +14601,7 @@ namespace ts { let apparentAttributesType = attributesType; const intrinsicClassAttribs = getJsxType(JsxNames.IntrinsicClassAttributes); if (intrinsicClassAttribs !== unknownType) { - const typeParams = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(intrinsicClassAttribs.symbol); + const typeParams = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(intrinsicClassAttribs.symbol!); apparentAttributesType = intersectTypes( typeParams ? createTypeReference(intrinsicClassAttribs, fillMissingTypeArguments([hostClassType], typeParams, getMinTypeArgumentCount(typeParams), isJs)) @@ -14601,7 +14640,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]; @@ -14631,7 +14670,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) @@ -14649,7 +14688,7 @@ 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)); const type = getContextualTypeForFunctionLikeDeclaration(node); if (!type) { @@ -14658,7 +14697,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); @@ -14679,7 +14718,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; @@ -14753,7 +14792,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) { @@ -14844,7 +14883,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])); } } @@ -14875,12 +14914,12 @@ namespace ts { let offset = 0; for (let i = 0; i < node.properties.length; i++) { const memberDecl = node.properties[i]; - let member = getSymbolOfNode(memberDecl); + let member = getSymbolOfNode(memberDecl)!; let literalName: __String | undefined; if (memberDecl.kind === SyntaxKind.PropertyAssignment || memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment || isObjectLiteralMethod(memberDecl)) { - let jsdocType: Type; + let jsdocType: Type | undefined; if (isInJSFile) { jsdocType = getTypeForDeclarationFromJSDocComment(memberDecl); } @@ -14912,14 +14951,14 @@ namespace ts { const nameType = hasLateBindableName(memberDecl) ? checkComputedPropertyName(memberDecl.name) : undefined; const prop = nameType && isTypeUsableAsLateBoundName(nameType) - ? createSymbol(SymbolFlags.Property | member.flags, getLateBoundNameFromType(nameType), CheckFlags.Late) + ? createSymbol(SymbolFlags.Property | member.flags, getLateBoundNameFromType(nameType)!, CheckFlags.Late) // TODO: GH#18217 : createSymbol(SymbolFlags.Property | member.flags, literalName || member.escapedName); if (inDestructuringPattern) { // If object literal is an assignment pattern and if the assignment pattern specifies a default value // for the property, make the property optional. const isOptional = - (memberDecl.kind === SyntaxKind.PropertyAssignment && hasDefaultValue(memberDecl.initializer)) || + (memberDecl.kind === SyntaxKind.PropertyAssignment && hasDefaultValue(memberDecl.initializer!)) || (memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment && memberDecl.objectAssignmentInitializer); if (isOptional) { prop.flags |= SymbolFlags.Optional; @@ -14928,17 +14967,17 @@ namespace ts { patternWithComputedProperties = true; } } - 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; @@ -14999,7 +15038,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, @@ -15047,12 +15086,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 getJsxGlobalElementType() || anyType; } - function checkJsxElement(node: JsxElement, checkMode: CheckMode): Type { + function checkJsxElement(node: JsxElement, checkMode: CheckMode | undefined): Type { // Check attributes checkJsxOpeningLikeElementOrOpeningFragment(node.openingElement, checkMode); @@ -15067,7 +15106,7 @@ namespace ts { return getJsxGlobalElementType() || 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) { @@ -15088,7 +15127,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: @@ -15097,7 +15136,7 @@ namespace ts { case SyntaxKind.Identifier: return isIntrinsicJsxName((tagName).escapedText); default: - Debug.fail(); + return Debug.fail(); } } @@ -15116,17 +15155,17 @@ 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(); for (const attributeDecl of attributes.properties) { - const member = attributeDecl.symbol; + const member = attributeDecl.symbol!; if (isJsxAttribute(attributeDecl)) { const exprType = checkJsxAttribute(attributeDecl, checkMode); @@ -15235,7 +15274,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); } @@ -15259,18 +15298,18 @@ namespace ts { const intrinsicElementsType = getJsxType(JsxNames.IntrinsicElements); if (intrinsicElementsType !== unknownType) { // Property case - if (!isIdentifier(node.tagName)) throw Debug.fail(); + if (!isIdentifier(node.tagName)) return Debug.fail(); const intrinsicProp = getPropertyOfType(intrinsicElementsType, node.tagName.escapedText); if (intrinsicProp) { - links.jsxFlags |= JsxFlags.IntrinsicNamedElement; + links.jsxFlags! |= JsxFlags.IntrinsicNamedElement; return links.resolvedSymbol = intrinsicProp; } // Intrinsic string indexer case const indexSignatureType = getIndexTypeOfType(intrinsicElementsType, IndexKind.String); if (indexSignatureType) { - links.jsxFlags |= JsxFlags.IntrinsicIndexedElement; - return links.resolvedSymbol = intrinsicElementsType.symbol; + links.jsxFlags! |= JsxFlags.IntrinsicIndexedElement; + return links.resolvedSymbol = intrinsicElementsType.symbol!; } // Wasn't found @@ -15335,11 +15374,11 @@ 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): __String { + function getNameFromJsxElementAttributesContainer(nameOfAttribPropContainer: __String): __String | undefined { // JSX const jsxNamespace = getGlobalSymbol(JsxNames.JSX, SymbolFlags.Namespace, /*diagnosticMessage*/ 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 @@ -15356,7 +15395,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; @@ -15367,7 +15406,7 @@ namespace ts { /// non-intrinsic elements' attributes type is 'any'), /// or '' if it has 0 properties (which means every /// non-intrinsic elements' attributes type is the element instance type) - function getJsxElementPropertiesName() { + function getJsxElementPropertiesName(): __String | undefined { if (!_hasComputedJsxElementPropertiesName) { _hasComputedJsxElementPropertiesName = true; _jsxElementPropertiesName = getNameFromJsxElementAttributesContainer(JsxNames.ElementAttributesPropertyNameContainer); @@ -15376,7 +15415,7 @@ namespace ts { return _jsxElementPropertiesName; } - function getJsxElementChildrenPropertyName(): __String { + function getJsxElementChildrenPropertyName(): __String | undefined { if (!_hasComputedJsxElementChildrenPropertyName) { _hasComputedJsxElementChildrenPropertyName = true; _jsxElementChildrenPropertyName = getNameFromJsxElementAttributesContainer(JsxNames.ElementChildrenAttributeNameContainer); @@ -15385,7 +15424,7 @@ namespace ts { return _jsxElementChildrenPropertyName; } - function getApparentTypeOfJsxPropsType(propsType: Type): Type { + function getApparentTypeOfJsxPropsType(propsType: Type | undefined): Type | undefined { if (!propsType) { return undefined; } @@ -15409,7 +15448,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 = getJsxGlobalStatelessElementType(); @@ -15418,7 +15457,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 @@ -15444,7 +15483,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 @@ -15453,18 +15492,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; } @@ -15578,11 +15618,11 @@ namespace ts { const links = getNodeLinks(node); if (!links.resolvedJsxElementAttributesType) { const symbol = getIntrinsicTagSymbol(node); - if (links.jsxFlags & JsxFlags.IntrinsicNamedElement) { + if (links.jsxFlags! & JsxFlags.IntrinsicNamedElement) { return links.resolvedJsxElementAttributesType = getTypeOfSymbol(symbol); } - else if (links.jsxFlags & JsxFlags.IntrinsicIndexedElement) { - return links.resolvedJsxElementAttributesType = getIndexInfoOfSymbol(symbol, IndexKind.String).type; + else if (links.jsxFlags! & JsxFlags.IntrinsicIndexedElement) { + return links.resolvedJsxElementAttributesType = getIndexInfoOfSymbol(symbol, IndexKind.String)!.type; } else { return links.resolvedJsxElementAttributesType = unknownType; @@ -15642,14 +15682,14 @@ namespace ts { return prop || unknownSymbol; } - function getJsxGlobalElementClassType(): Type { + function getJsxGlobalElementClassType(): Type | undefined { if (!deferredJsxElementClassType) { deferredJsxElementClassType = getExportedTypeFromNamespace(JsxNames.JSX, JsxNames.ElementClass); } return deferredJsxElementClassType; } - function getJsxGlobalElementType(): Type { + function getJsxGlobalElementType(): Type | undefined { if (!deferredJsxElementType) { deferredJsxElementType = getExportedTypeFromNamespace(JsxNames.JSX, JsxNames.Element); } @@ -15687,7 +15727,7 @@ namespace ts { } } - function checkJsxOpeningLikeElementOrOpeningFragment(node: JsxOpeningLikeElement | JsxOpeningFragment, checkMode: CheckMode) { + function checkJsxOpeningLikeElementOrOpeningFragment(node: JsxOpeningLikeElement | JsxOpeningFragment, checkMode: CheckMode | undefined) { const isNodeOpeningLikeElement = isJsxOpeningLikeElement(node); if (isNodeOpeningLikeElement) { @@ -15759,7 +15799,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) @@ -15780,7 +15820,7 @@ namespace ts { // If the targetAttributesType is an emptyObjectType, indicating that there is no property named 'props' on this instance type. // but there exists a sourceAttributesType, we need to explicitly give an error as normal assignability check allow excess properties and will pass. if (targetAttributesType === emptyObjectType && (isTypeAny(sourceAttributesType) || getPropertiesOfType(sourceAttributesType).length > 0)) { - error(openingLikeElement, Diagnostics.JSX_element_class_does_not_support_attributes_because_it_does_not_have_a_0_property, unescapeLeadingUnderscores(getJsxElementPropertiesName())); + error(openingLikeElement, Diagnostics.JSX_element_class_does_not_support_attributes_because_it_does_not_have_a_0_property, unescapeLeadingUnderscores(getJsxElementPropertiesName()!)); // TODO: GH#18217 } else { // Check if sourceAttributesType assignable to targetAttributesType though this check will allow excess properties @@ -15870,16 +15910,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; } } @@ -15893,9 +15933,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; @@ -15911,7 +15951,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 @@ -15925,7 +15965,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)); @@ -16050,7 +16090,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; } @@ -16095,10 +16135,10 @@ 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) as InterfaceType; + let classType: InterfaceType | undefined = getTypeOfSymbol(prop.parent!) as InterfaceType; while (true) { classType = getSuperClass(classType); if (!classType) { @@ -16121,7 +16161,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)) { @@ -16145,7 +16185,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"); @@ -16273,7 +16313,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, propertyName: __String): boolean { @@ -16307,13 +16347,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]; @@ -16472,10 +16512,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); @@ -16484,7 +16524,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; @@ -16528,9 +16568,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)) { @@ -16547,8 +16587,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 { @@ -16562,7 +16601,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) { @@ -16608,7 +16647,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 && @@ -16646,7 +16685,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 @@ -16709,7 +16748,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); @@ -16736,15 +16775,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); @@ -16801,7 +16840,7 @@ namespace ts { args: ReadonlyArray, signature: Signature, relation: Map, - excludeArgument: boolean[], + excludeArgument: boolean[] | undefined, reportErrors: boolean) { if (isJsxOpeningLikeElement(node)) { return checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation); @@ -16815,7 +16854,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; } } @@ -16830,7 +16869,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). @@ -16849,7 +16888,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 = node.expression; if (callee.kind === SyntaxKind.PropertyAccessExpression) { @@ -16870,10 +16909,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); @@ -16940,8 +16979,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 { @@ -16966,7 +17007,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)!; return getTypeOfSymbol(classSymbol); } @@ -16975,7 +17016,7 @@ namespace ts { // parameter's containing method. node = node.parent; if (node.kind === SyntaxKind.Constructor) { - const classSymbol = getSymbolOfNode(node); + const classSymbol = getSymbolOfNode(node)!; return getTypeOfSymbol(classSymbol); } } @@ -17037,15 +17078,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; } @@ -17093,7 +17135,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); } @@ -17122,7 +17164,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 @@ -17154,7 +17196,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; @@ -17168,12 +17210,12 @@ namespace ts { } } - 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 (!isTaggedTemplate && !isDecorator && !isJsxOpeningOrSelfClosingElement) { typeArguments = (node).typeArguments; @@ -17209,15 +17251,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++; @@ -17246,9 +17288,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. @@ -17289,12 +17331,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).typeArguments, /*reportErrors*/ true, fallbackError); + checkTypeArguments(candidateForTypeArgumentError, (node as CallExpression).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)) { let min = Number.POSITIVE_INFINITY; let max = Number.NEGATIVE_INFINITY; for (const sig of signatures) { @@ -17340,12 +17382,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(); } @@ -17369,10 +17411,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; } @@ -17381,7 +17423,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; } @@ -17405,12 +17447,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; } @@ -17420,7 +17462,7 @@ namespace ts { } excludeCount--; if (excludeCount > 0) { - excludeArgument[excludeArgument.indexOf(/*value*/ true)] = false; + excludeArgument![excludeArgument!.indexOf(/*value*/ true)] = false; } else { excludeArgument = undefined; @@ -17450,13 +17492,13 @@ 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 (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); @@ -17526,7 +17568,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) { @@ -17615,8 +17657,8 @@ namespace ts { return true; } - const declaringClassDeclaration = getClassLikeDeclarationOfSymbol(declaration.parent.symbol); - const declaringClass = getDeclaredTypeOfSymbol(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) if (!isNodeWithinClass(node, declaringClassDeclaration)) { @@ -17661,13 +17703,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); @@ -17710,13 +17752,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) { @@ -17737,8 +17782,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); @@ -17757,7 +17801,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)); } /** @@ -17770,7 +17814,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)); return resolveStatelessJsxOpeningLikeElement(openingLikeElement, elementType, candidatesOutArray); } @@ -17784,11 +17828,11 @@ namespace ts { * @return a resolved signature if we can find function matching function signature through resolve call or a first signature in the list of functions. * otherwise return undefined if tag-name of the opening-like element doesn't have call signatures */ - function resolveStatelessJsxOpeningLikeElement(openingLikeElement: JsxOpeningLikeElement, elementType: Type, candidatesOutArray: Signature[]): Signature | undefined { + function resolveStatelessJsxOpeningLikeElement(openingLikeElement: JsxOpeningLikeElement, elementType: Type, candidatesOutArray: Signature[] | undefined): Signature | undefined { // If this function is called from language service, elementType can be a union type. This is not possible if the function is called from compiler (see: resolveCustomJsxElementAttributesType) if (elementType.flags & TypeFlags.Union) { const types = (elementType as UnionType).types; - let result: Signature; + let result: Signature | undefined; for (const type of types) { result = result || resolveStatelessJsxOpeningLikeElement(openingLikeElement, type, candidatesOutArray); } @@ -17819,7 +17863,7 @@ namespace ts { // This code-path is called by language service return resolveStatelessJsxOpeningLikeElement(node, checkExpression(node.tagName), candidatesOutArray) || unknownSignature; } - Debug.assertNever(node, "Branch in 'resolveSignature' should be unreachable."); + throw Debug.assertNever(node, "Branch in 'resolveSignature' should be unreachable."); } /** @@ -17862,7 +17906,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; @@ -17870,7 +17914,7 @@ namespace ts { function getJavaScriptClassType(symbol: Symbol): Type | undefined { if (isDeclarationOfFunctionOrClassExpression(symbol)) { - symbol = getSymbolOfNode((symbol.valueDeclaration).initializer); + symbol = getSymbolOfNode((symbol.valueDeclaration).initializer!)!; } if (isJavaScriptConstructor(symbol.valueDeclaration)) { return getInferredClassType(symbol); @@ -17942,7 +17986,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]); + return resolveExternalModuleTypeByLiteral(node.arguments![0]); } const returnType = getReturnTypeOfSignature(signature); @@ -18006,7 +18050,7 @@ namespace ts { if (allowSyntheticDefaultImports && type && type !== unknownType) { const synthType = type as SyntheticDefaultModuleType; if (!synthType.syntheticType) { - const file = find(originalSymbol.declarations, isSourceFile); + const file = find(originalSymbol.declarations!, isSourceFile); const hasSyntheticDefault = canHaveSyntheticDefault(file, originalSymbol, /*dontResolveAlias*/ false); if (hasSyntheticDefault) { const memberTable = createSymbolTable(); @@ -18033,7 +18077,7 @@ namespace ts { } // Make sure require is not a local function - if (!isIdentifier(node.expression)) throw Debug.fail(); + if (!isIdentifier(node.expression)) return Debug.fail(); const resolvedRequire = resolveName(node.expression, node.expression.escapedText, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true); if (!resolvedRequire) { // project does not contain symbol named 'require' - assume commonjs require @@ -18050,7 +18094,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); } @@ -18095,11 +18139,11 @@ namespace ts { return unknownType; } else if (container.kind === SyntaxKind.Constructor) { - const symbol = getSymbolOfNode(container.parent); + const symbol = getSymbolOfNode(container.parent)!; return getTypeOfSymbol(symbol); } else { - const symbol = getSymbolOfNode(container); + const symbol = getSymbolOfNode(container)!; return getTypeOfSymbol(symbol); } } @@ -18146,7 +18190,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); @@ -18159,9 +18203,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); } } @@ -18173,7 +18217,7 @@ namespace ts { for (const element of pattern.elements) { if (!isOmittedExpression(element)) { if (element.name.kind === SyntaxKind.Identifier) { - getSymbolLinks(getSymbolOfNode(element)).type = getTypeForBindingElement(element); + getSymbolLinks(getSymbolOfNode(element)!).type = getTypeForBindingElement(element); } else { assignBindingElementTypes(element.name); @@ -18318,7 +18362,7 @@ namespace ts { } } - function checkAndAggregateYieldOperandTypes(func: FunctionLikeDeclaration, checkMode: CheckMode): Type[] { + function checkAndAggregateYieldOperandTypes(func: FunctionLikeDeclaration, checkMode: CheckMode | undefined): Type[] { const aggregatedTypes: Type[] = []; const functionFlags = getFunctionFlags(func); forEachYieldExpression(func.body, yieldExpression => { @@ -18368,7 +18412,7 @@ namespace ts { } /** NOTE: Return value of `[]` means a different thing than `undefined`. `[]` means return `void`, `undefined` means return `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); @@ -18422,7 +18466,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; } @@ -18434,7 +18478,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; } @@ -18485,16 +18529,16 @@ namespace ts { } const links = getNodeLinks(node); - const type = getTypeOfSymbol(node.symbol); + const type = getTypeOfSymbol(node.symbol!); // Check if function expression is contextually typed and assign parameter types if so. - if (!(links.flags & NodeCheckFlags.ContextChecked)) { + if (!(links.flags! & NodeCheckFlags.ContextChecked)) { const contextualSignature = getContextualSignature(node); // If a type check is started at a function expression that is an argument of a function call, obtaining the // contextual type may recursively get back to here during overload resolution of the call. If so, we will have // already assigned contextual types. - if (!(links.flags & NodeCheckFlags.ContextChecked)) { - links.flags |= NodeCheckFlags.ContextChecked; + if (!(links.flags! & NodeCheckFlags.ContextChecked)) { + links.flags! |= NodeCheckFlags.ContextChecked; if (contextualSignature) { const signature = getSignaturesOfType(type, SignatureKind.Call)[0]; if (isContextSensitive(node)) { @@ -18612,7 +18656,7 @@ namespace ts { // If func.parent is a class and symbol is a (readonly) property of that class, or // if func is a constructor and symbol is a (readonly) parameter property declared in it, // then symbol is writeable here. - return !(func.parent === symbol.valueDeclaration.parent || func === symbol.valueDeclaration.parent); + return !(func.parent === symbol.valueDeclaration!.parent || func === symbol.valueDeclaration!.parent); } return true; } @@ -18623,10 +18667,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; } } } @@ -18764,15 +18808,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 { @@ -18782,7 +18826,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 { @@ -18862,7 +18906,7 @@ namespace ts { } else { // non-shorthand property assignments should always have initializers - return checkDestructuringAssignment(property.initializer, type); + return checkDestructuringAssignment(property.initializer!, type); } } else { @@ -18876,7 +18920,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); @@ -18959,7 +19003,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; } @@ -19065,7 +19109,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); @@ -19102,7 +19146,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) && @@ -19131,7 +19175,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. @@ -19207,6 +19251,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 isEvalNode(node: Expression) { @@ -19227,7 +19274,7 @@ namespace ts { return true; } - function getSuggestedBooleanOperator(operator: SyntaxKind): SyntaxKind { + function getSuggestedBooleanOperator(operator: SyntaxKind): SyntaxKind | undefined { switch (operator) { case SyntaxKind.BarToken: case SyntaxKind.BarEqualsToken: @@ -19297,7 +19344,7 @@ namespace ts { const func = getContainingFunction(node); // If the user's code is syntactically correct, the func should always have a star. After all, // we are in a yield context. - const functionFlags = func && getFunctionFlags(func); + const functionFlags = func ? getFunctionFlags(func) : 0; if (node.asteriskToken) { // Async generator functions prior to ESNext require the __await, __asyncDelegator, // and __asyncValues helpers @@ -19315,7 +19362,7 @@ namespace ts { if (functionFlags & FunctionFlags.Generator) { const expressionType = checkExpressionCached(node.expression); - let expressionElementType: Type; + let expressionElementType: Type | undefined; const nodeIsYieldStar = !!node.asteriskToken; if (nodeIsYieldStar) { expressionElementType = checkIteratedTypeOrElementType(expressionType, node.expression, /*allowStringInput*/ false, (functionFlags & FunctionFlags.Async) !== 0); @@ -19324,14 +19371,15 @@ namespace ts { // 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. - const returnType = getEffectiveReturnTypeNode(func); + const returnType = getEffectiveReturnTypeNode(func!); if (returnType) { const signatureElementType = getIteratedTypeOfGenerator(getTypeFromTypeNode(returnType), (functionFlags & FunctionFlags.Async) !== 0) || anyType; if (nodeIsYieldStar) { checkTypeAssignableTo( functionFlags & FunctionFlags.Async - ? getAwaitedType(expressionElementType, node.expression, Diagnostics.Type_of_iterated_elements_of_a_yield_Asterisk_operand_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member) - : expressionElementType, + // TODO: GH#18217 getAwaitedType may return undefined + ? getAwaitedType(expressionElementType!, node.expression, Diagnostics.Type_of_iterated_elements_of_a_yield_Asterisk_operand_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member)! + : expressionElementType!, signatureElementType, node.expression, /*headMessage*/ undefined); @@ -19339,7 +19387,7 @@ namespace ts { else { checkTypeAssignableTo( functionFlags & FunctionFlags.Async - ? getAwaitedType(expressionType, node.expression, Diagnostics.Type_of_yield_operand_in_an_async_generator_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member) + ? getAwaitedType(expressionType, node.expression, Diagnostics.Type_of_yield_operand_in_an_async_generator_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member)! : expressionType, signatureElementType, node.expression, @@ -19417,13 +19465,13 @@ namespace ts { } function checkDeclarationInitializer(declaration: HasExpressionInitializer) { - const type = getTypeOfExpression(declaration.initializer, /*cache*/ true); + const type = getTypeOfExpression(declaration.initializer!, /*cache*/ true); return getCombinedNodeFlags(declaration) & NodeFlags.Const || (getCombinedModifierFlags(declaration) & ModifierFlags.Readonly && !isParameterPropertyDeclaration(declaration)) || - isTypeAssertion(declaration.initializer) ? type : getWidenedLiteralType(type); + isTypeAssertion(declaration.initializer!) ? type : getWidenedLiteralType(type); } - 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; @@ -19442,15 +19490,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); } @@ -19467,7 +19515,7 @@ namespace ts { checkComputedPropertyName(node.name); } - return checkExpressionForMutableLocation(node.initializer, checkMode); + return checkExpressionForMutableLocation(node.initializer!, checkMode); } function checkObjectLiteralMethod(node: MethodDeclaration, checkMode?: CheckMode): Type { @@ -19577,12 +19625,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); @@ -19685,7 +19733,7 @@ namespace ts { checkSourceElement(node.constraint); checkSourceElement(node.default); - const typeParameter = getDeclaredTypeOfTypeParameter(getSymbolOfNode(node)); + const typeParameter = getDeclaredTypeOfTypeParameter(getSymbolOfNode(node)!); if (!hasNonCircularBaseConstraint(typeParameter)) { error(node.constraint, Diagnostics.Type_parameter_0_has_a_circular_constraint, typeToString(typeParameter)); } @@ -19710,7 +19758,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); @@ -19730,7 +19778,7 @@ namespace ts { // Only check rest parameter type if it's not a binding pattern. Since binding patterns are // not allowed in a rest parameter, we already have an error from checkGrammarParameterList. - if (node.dotDotDotToken && !isBindingPattern(node.name) && !isArrayType(getTypeOfSymbol(node.symbol))) { + if (node.dotDotDotToken && !isBindingPattern(node.name) && !isArrayType(getTypeOfSymbol(node.symbol!))) { error(node, Diagnostics.A_rest_parameter_must_be_of_an_array_type); } } @@ -19775,7 +19823,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); @@ -19797,7 +19845,7 @@ namespace ts { } } - function getTypePredicateParent(node: Node): SignatureDeclaration { + function getTypePredicateParent(node: Node): SignatureDeclaration | undefined { switch (node.parent.kind) { case SyntaxKind.ArrowFunction: case SyntaxKind.CallSignature: @@ -19948,23 +19996,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; } } @@ -20016,7 +20065,7 @@ namespace ts { case "arguments": case "prototype": const message = Diagnostics.Static_property_0_conflicts_with_built_in_property_Function_0_of_constructor_function_1; - const className = getNameOfSymbolAsWritten(getSymbolOfNode(node)); + const className = getNameOfSymbolAsWritten(getSymbolOfNode(node)!); error(memberNameNode, message, memberName, className); break; } @@ -20029,20 +20078,21 @@ 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; } if (names.get(memberName)) { - error(getNameOfDeclaration(member.symbol.valueDeclaration), Diagnostics.Duplicate_identifier_0, memberName); + error(getNameOfDeclaration(member.symbol!.valueDeclaration!), Diagnostics.Duplicate_identifier_0, memberName); error(member.name, Diagnostics.Duplicate_identifier_0, memberName); } else { @@ -20054,10 +20104,10 @@ namespace ts { function checkTypeForDuplicateIndexSignatures(node: Node) { if (node.kind === SyntaxKind.InterfaceDeclaration) { - const nodeSymbol = getSymbolOfNode(node); + const nodeSymbol = getSymbolOfNode(node)!; // 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) { + if (nodeSymbol.declarations!.length > 0 && nodeSymbol.declarations![0] !== node) { return; } } @@ -20065,14 +20115,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) { + 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; @@ -20124,7 +20174,7 @@ namespace ts { checkSourceElement(node.body); registerForUnusedIdentifiersCheck(node); - const symbol = getSymbolOfNode(node); + const symbol = getSymbolOfNode(node)!; const firstDeclaration = getDeclarationOfKind(symbol, node.kind); // Only type check the symbol once @@ -20172,8 +20222,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)) { @@ -20219,7 +20269,7 @@ namespace ts { // TypeScript 1.0 spec (April 2014): 8.4.3 // Accessors for the same member name must specify the same accessibility. const otherKind = node.kind === SyntaxKind.GetAccessor ? SyntaxKind.SetAccessor : SyntaxKind.GetAccessor; - const otherAccessor = getDeclarationOfKind(getSymbolOfNode(node), otherKind); + const otherAccessor = getDeclarationOfKind(getSymbolOfNode(node)!, otherKind); if (otherAccessor) { const nodeFlags = getModifierFlags(node); const otherFlags = getModifierFlags(otherAccessor); @@ -20236,7 +20286,7 @@ namespace ts { checkAccessorDeclarationTypesIdentical(node, otherAccessor, getThisTypeOfDeclaration, Diagnostics.get_and_set_accessor_must_have_the_same_this_type); } } - const returnType = getTypeOfAccessors(getSymbolOfNode(node)); + const returnType = getTypeOfAccessors(getSymbolOfNode(node)!); if (node.kind === SyntaxKind.GetAccessor) { checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnType); } @@ -20245,7 +20295,7 @@ namespace ts { registerForUnusedIdentifiersCheck(node); } - 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)) { @@ -20257,14 +20307,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]); @@ -20275,8 +20325,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); } } @@ -20312,7 +20362,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)); } } @@ -20321,8 +20371,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))); } @@ -20444,17 +20494,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; @@ -20479,7 +20529,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 => { @@ -20497,11 +20547,11 @@ namespace ts { let someHaveQuestionToken = false; let allHaveQuestionToken = true; let hasOverloads = false; - let bodyDeclaration: FunctionLikeDeclaration; - let lastSeenNonAmbientDeclaration: FunctionLikeDeclaration; - let previousDeclaration: FunctionLike; + let bodyDeclaration: FunctionLikeDeclaration | undefined; + let lastSeenNonAmbientDeclaration: FunctionLikeDeclaration | undefined; + let previousDeclaration: FunctionLike | undefined; - const declarations = symbol.declarations; + const declarations = symbol.declarations!; const isConstructor = (symbol.flags & SymbolFlags.Constructor) !== 0; function reportImplementationExpectedError(node: FunctionLike): void { @@ -20542,7 +20592,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; } } @@ -20661,7 +20711,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; @@ -20676,7 +20726,7 @@ namespace ts { let exportedDeclarationSpaces = DeclarationSpaces.None; let nonExportedDeclarationSpaces = DeclarationSpaces.None; let defaultExportedDeclarationSpaces = DeclarationSpaces.None; - for (const d of symbol.declarations) { + for (const d of symbol.declarations!) { const declarationSpaces = getDeclarationSpaces(d); const effectiveDeclarationFlags = getEffectiveDeclarationFlags(d, ModifierFlags.Export | ModifierFlags.Default); @@ -20701,10 +20751,10 @@ namespace ts { if (commonDeclarationSpacesForExportsAndLocals || commonDeclarationSpacesForDefaultAndNonDefault) { // declaration spaces for exported and non-exported declarations intersect - for (const d of symbol.declarations) { + for (const d of symbol.declarations!) { const declarationSpaces = getDeclarationSpaces(d); - const name = getNameOfDeclaration(d); + const name = getNameOfDeclaration(d)!; // Only error on the declarations that contributed to the intersecting spaces. if (declarationSpaces & commonDeclarationSpacesForDefaultAndNonDefault) { error(name, Diagnostics.Merged_declaration_0_cannot_include_a_default_export_declaration_Consider_adding_a_separate_export_default_0_declaration_instead, declarationNameToString(name)); @@ -20742,7 +20792,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: @@ -20751,7 +20801,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)); } } } @@ -20766,7 +20816,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 @@ -20787,10 +20837,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; } @@ -20841,9 +20891,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) { @@ -20926,7 +20976,7 @@ namespace ts { if (thenFunction && getSignaturesOfType(thenFunction, SignatureKind.Call).length > 0) { if (errorNode) { Debug.assert(!!diagnosticMessage); - error(errorNode, diagnosticMessage); + error(errorNode, diagnosticMessage!); } return undefined; } @@ -20972,7 +21022,7 @@ namespace ts { // then(...): Promise; // } // - const returnTypeNode = getEffectiveReturnTypeNode(node); + const returnTypeNode = getEffectiveReturnTypeNode(node)!; // TODO: GH#18217 const returnType = getTypeFromTypeNode(returnTypeNode); if (languageVersion >= ScriptTarget.ES2015) { @@ -21028,7 +21078,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), @@ -21051,10 +21101,10 @@ 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); + const classSymbol = getSymbolOfNode(node.parent)!; const classConstructorType = getTypeOfSymbol(classSymbol); expectedReturnType = getUnionType([classConstructorType, voidType]); break; @@ -21062,7 +21112,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; @@ -21070,17 +21120,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( @@ -21099,7 +21152,7 @@ namespace ts { markEntityNameOrEntityExpressionAsReference(node && getEntityNameFromTypeNode(node)); } - function markEntityNameOrEntityExpressionAsReference(typeName: EntityNameOrEntityNameExpression) { + function markEntityNameOrEntityExpressionAsReference(typeName: EntityNameOrEntityNameExpression | undefined) { if (!typeName) return; const rootName = getFirstIdentifier(typeName); @@ -21120,19 +21173,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 @@ -21177,7 +21230,7 @@ namespace ts { } } - function getParameterTypeNodeForDecoratorCheck(node: ParameterDeclaration): TypeNode { + function getParameterTypeNodeForDecoratorCheck(node: ParameterDeclaration): TypeNode | undefined { const typeNode = getEffectiveTypeAnnotationNode(node); return isRestParameter(node) ? getRestParameterElementType(typeNode) : typeNode; } @@ -21252,8 +21305,8 @@ namespace ts { checkCollisionWithCapturedSuperVariable(node, node.name); checkCollisionWithCapturedThisVariable(node, node.name); checkCollisionWithCapturedNewTargetVariable(node, node.name); - checkCollisionWithRequireExportsInGeneratedCode(node, node.name); - checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name); + checkCollisionWithRequireExportsInGeneratedCode(node, node.name!); + checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name!); } } @@ -21280,7 +21333,7 @@ namespace ts { return; } - const augmentsTags = getAllJSDocTagsOfKind(classLike, SyntaxKind.JSDocAugmentsTag); + const augmentsTags = getAllJSDocTagsOfKind(classLike, SyntaxKind.JSDocAugmentsTag)!; Debug.assert(augmentsTags.length > 0); if (augmentsTags.length > 1) { error(augmentsTags[1], Diagnostics.Class_declarations_cannot_have_more_than_one_augments_or_extends_tag); @@ -21327,13 +21380,13 @@ namespace ts { // first we want to check the local symbol that contain this declaration // - if node.localSymbol !== undefined - this is current declaration is exported and localSymbol points to the local symbol // - if node.localSymbol === undefined - this node is non-exported so we can just pick the result of getSymbolOfNode - const symbol = getSymbolOfNode(node); + const symbol = getSymbolOfNode(node)!; const localSymbol = node.localSymbol || symbol; // Since the javascript won't do semantic analysis like typescript, // if the javascript file comes before the typescript file and both contain same name functions, // checkFunctionOrConstructorSymbol wouldn't be called if we didnt ignore javascript function. - const firstDeclaration = find(localSymbol.declarations, + const firstDeclaration = find(localSymbol.declarations!, // Get first non javascript function declaration declaration => declaration.kind === node.kind && !(declaration.flags & NodeFlags.JavaScriptFile)); @@ -21438,13 +21491,13 @@ namespace ts { function checkUnusedLocalsAndParameters(node: Node): void { if (noUnusedIdentifiers && !(node.flags & NodeFlags.Ambient)) { - node.locals.forEach(local => { + node.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) { + if (local.flags & SymbolFlags.TypeParameter ? (local.flags & SymbolFlags.Variable && !(local.isReferenced! & SymbolFlags.Variable)) : !local.isReferenced) { if (local.valueDeclaration && getRootDeclaration(local.valueDeclaration).kind === SyntaxKind.Parameter) { const parameter = getRootDeclaration(local.valueDeclaration); - const name = getNameOfDeclaration(local.valueDeclaration); + const name = getNameOfDeclaration(local.valueDeclaration)!; if (compilerOptions.noUnusedParameters && !isParameterPropertyDeclaration(parameter) && !parameterIsThisKeyword(parameter) && @@ -21462,7 +21515,7 @@ namespace ts { function isRemovedPropertyFromObjectSpread(node: Node) { if (isBindingElement(node) && isObjectBindingPattern(node.parent)) { - const lastElement = lastOrUndefined(node.parent.elements); + const lastElement = last(node.parent.elements); return lastElement !== node && !!lastElement.dotDotDotToken; } return false; @@ -21499,19 +21552,19 @@ namespace ts { case SyntaxKind.PropertyDeclaration: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: - if (member.kind === SyntaxKind.SetAccessor && member.symbol.flags & SymbolFlags.GetAccessor) { + if (member.kind === SyntaxKind.SetAccessor && member.symbol!.flags & SymbolFlags.GetAccessor) { // Already would have reported an error on the getter. break; } - const symbol = getSymbolOfNode(member); + const symbol = getSymbolOfNode(member)!; if (!symbol.isReferenced && hasModifier(member, ModifierFlags.Private)) { error(member.name, Diagnostics._0_is_declared_but_its_value_is_never_read, symbolToString(symbol)); } break; case SyntaxKind.Constructor: for (const parameter of (member).parameters) { - if (!parameter.symbol.isReferenced && hasModifier(parameter, ModifierFlags.Private)) { - error(parameter.name, Diagnostics.Property_0_is_declared_but_its_value_is_never_read, symbolName(parameter.symbol)); + if (!parameter.symbol!.isReferenced && hasModifier(parameter, ModifierFlags.Private)) { + error(parameter.name, Diagnostics.Property_0_is_declared_but_its_value_is_never_read, symbolName(parameter.symbol!)); } } break; @@ -21537,8 +21590,8 @@ namespace ts { return; } for (const typeParameter of node.typeParameters) { - if (!(getMergedSymbol(typeParameter.symbol).isReferenced & SymbolFlags.TypeParameter) && !isIdentifierThatStartsWithUnderScore(typeParameter.name)) { - error(typeParameter.name, Diagnostics._0_is_declared_but_its_value_is_never_read, symbolName(typeParameter.symbol)); + if (!(getMergedSymbol(typeParameter.symbol)!.isReferenced! & SymbolFlags.TypeParameter) && !isIdentifierThatStartsWithUnderScore(typeParameter.name)) { + error(typeParameter.name, Diagnostics._0_is_declared_but_its_value_is_never_read, symbolName(typeParameter.symbol!)); } } } @@ -21547,9 +21600,9 @@ namespace ts { function checkUnusedModuleMembers(node: ModuleDeclaration | SourceFile): void { if (compilerOptions.noUnusedLocals && !(node.flags & NodeFlags.Ambient)) { - node.locals.forEach(local => { + node.locals!.forEach(local => { if (!local.isReferenced && !local.exportSymbol) { - for (const declaration of local.declarations) { + for (const declaration of local.declarations!) { if (!isAmbientModule(declaration)) { errorUnusedLocal(declaration, symbolName(local)); } @@ -21590,7 +21643,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; } @@ -21619,13 +21672,13 @@ namespace ts { return true; } - function checkCollisionWithCapturedThisVariable(node: Node, name: Identifier): void { + function checkCollisionWithCapturedThisVariable(node: Node, name: Identifier | undefined): void { if (needCollisionCheckForIdentifier(node, name, "_this")) { potentialThisCollisions.push(node); } } - function checkCollisionWithCapturedNewTargetVariable(node: Node, name: Identifier): void { + function checkCollisionWithCapturedNewTargetVariable(node: Node, name: Identifier | undefined): void { if (needCollisionCheckForIdentifier(node, name, "_newTarget")) { potentialNewTargetCollisions.push(node); } @@ -21644,6 +21697,7 @@ namespace ts { } return true; } + return false; }); } @@ -21659,10 +21713,11 @@ namespace ts { } return true; } + return false; }); } - function checkCollisionWithCapturedSuperVariable(node: Node, name: Identifier) { + function checkCollisionWithCapturedSuperVariable(node: Node, name: Identifier | undefined) { if (!needCollisionCheckForIdentifier(node, name, "_super")) { return; } @@ -21766,15 +21821,15 @@ namespace ts { return; } - const symbol = getSymbolOfNode(node); + const symbol = getSymbolOfNode(node)!; if (symbol.flags & SymbolFlags.FunctionScopedVariable) { - if (!isIdentifier(node.name)) throw Debug.fail(); + if (!isIdentifier(node.name)) return Debug.fail(); const localDeclarationSymbol = resolveName(node, node.name.escapedText, SymbolFlags.Variable, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false); if (localDeclarationSymbol && 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 @@ -21809,7 +21864,7 @@ namespace ts { } const func = getContainingFunction(node); - visit(node.initializer); + visit(node.initializer!); function visit(n: Node): void { if (isTypeNode(n) || isDeclarationName(n)) { @@ -21910,10 +21965,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); } } } @@ -21946,7 +22001,7 @@ namespace ts { } return; } - const symbol = getSymbolOfNode(node); + const symbol = getSymbolOfNode(node)!; const type = convertAutoToAny(getTypeOfSymbol(symbol)); if (node === symbol.valueDeclaration) { // Node is the primary declaration of the symbol, just validate the initializer @@ -21969,8 +22024,8 @@ namespace ts { if (node.initializer) { checkTypeAssignableTo(checkExpressionCached(node.initializer), declarationType, node, /*headMessage*/ undefined); } - if (!areDeclarationFlagsIdentical(node, symbol.valueDeclaration)) { - error(getNameOfDeclaration(symbol.valueDeclaration), Diagnostics.All_declarations_of_0_must_have_identical_modifiers, declarationNameToString(node.name)); + if (!areDeclarationFlagsIdentical(node, symbol.valueDeclaration!)) { + error(getNameOfDeclaration(symbol.valueDeclaration!), Diagnostics.All_declarations_of_0_must_have_identical_modifiers, declarationNameToString(node.name)); error(node.name, Diagnostics.All_declarations_of_0_must_have_identical_modifiers, declarationNameToString(node.name)); } } @@ -21989,7 +22044,7 @@ namespace ts { } function errorNextVariableOrPropertyDeclarationMustHaveSameType(firstType: Type, nextDeclaration: Declaration, nextType: Type): void { - const nextDeclarationName = getNameOfDeclaration(nextDeclaration); + const nextDeclarationName = getNameOfDeclaration(nextDeclaration)!; const message = nextDeclaration.kind === SyntaxKind.PropertyDeclaration || nextDeclaration.kind === SyntaxKind.PropertySignature ? Diagnostics.Subsequent_property_declarations_must_have_the_same_type_Property_0_must_be_of_type_1_but_here_has_type_2 : Diagnostics.Subsequent_variable_declarations_must_have_the_same_type_Variable_0_must_be_of_type_1_but_here_has_type_2; @@ -22218,7 +22273,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; } @@ -22231,7 +22286,7 @@ 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 { + function getIteratedTypeOrElementType(inputType: Type, errorNode: Node | undefined, allowStringInput: boolean, allowAsyncIterables: boolean, checkAssignability: boolean): Type | undefined { const uplevelIteration = languageVersion >= ScriptTarget.ES2015; const downlevelIteration = !uplevelIteration && compilerOptions.downlevelIteration; @@ -22372,7 +22427,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]; } } @@ -22385,17 +22440,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) { error(errorNode, @@ -22408,7 +22463,7 @@ namespace ts { return undefined; } - const returnType = getUnionType(map(signatures, getReturnTypeOfSignature), UnionReduction.Subtype); + const returnType = getUnionType(map(signatures!, getReturnTypeOfSignature), UnionReduction.Subtype); const iteratedType = getIteratedTypeOfIterator(returnType, errorNode, /*isAsyncIterator*/ !!asyncMethodType); if (checkAssignability && errorNode && iteratedType) { // If `checkAssignability` was specified, we were called from @@ -22463,8 +22518,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. @@ -22483,7 +22538,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; } @@ -22517,7 +22572,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; } @@ -22535,14 +22590,14 @@ namespace ts { function isGetAccessorWithAnnotatedSetAccessor(node: FunctionLike) { return node.kind === SyntaxKind.GetAccessor - && getEffectiveSetAccessorTypeAnnotationNode(getDeclarationOfKind(node.symbol, SyntaxKind.SetAccessor)) !== undefined; + && getEffectiveSetAccessorTypeAnnotationNode(getDeclarationOfKind(node.symbol!, SyntaxKind.SetAccessor)!) !== undefined; } function isUnwrappedReturnTypeVoidOrAny(func: FunctionLike, 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) { @@ -22680,6 +22735,7 @@ namespace ts { grammarErrorOnNode(node.label, Diagnostics.Duplicate_label_0, getTextOfNodeFromSourceText(sourceFile.text, node.label)); return true; } + return false; }); } @@ -22718,10 +22774,10 @@ 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); + grammarErrorOnNode(blockLocal.valueDeclaration!, Diagnostics.Cannot_redeclare_identifier_0_in_catch_clause, caughtName); } }); } @@ -22737,8 +22793,8 @@ namespace ts { } function checkIndexConstraints(type: Type) { - const declaredNumberIndexer = getIndexDeclarationOfSymbol(type.symbol, IndexKind.Number); - const declaredStringIndexer = getIndexDeclarationOfSymbol(type.symbol, IndexKind.String); + const declaredNumberIndexer = getIndexDeclarationOfSymbol(type.symbol!, IndexKind.Number); + const declaredStringIndexer = getIndexDeclarationOfSymbol(type.symbol!, IndexKind.String); const stringIndexType = getIndexTypeOfType(type, IndexKind.String); const numberIndexType = getIndexTypeOfType(type, IndexKind.Number); @@ -22750,14 +22806,14 @@ 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, // and properties with literal names were already checked. if (!hasModifier(member, ModifierFlags.Static) && hasNonBindableDynamicName(member)) { - const symbol = getSymbolOfNode(member); + const symbol = getSymbolOfNode(member)!; const propType = getTypeOfSymbol(symbol); checkIndexConstraintForProperty(symbol, propType, type, declaredStringIndexer, stringIndexType, IndexKind.String); checkIndexConstraintForProperty(symbol, propType, type, declaredNumberIndexer, numberIndexType, IndexKind.Number); @@ -22766,27 +22822,27 @@ 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 if (!errorNode && (getObjectFlags(type) & ObjectFlags.Interface)) { const someBaseTypeHasBothIndexers = forEach(getBaseTypes(type), base => getIndexTypeOfType(base, IndexKind.String) && getIndexTypeOfType(base, IndexKind.Number)); - errorNode = someBaseTypeHasBothIndexers ? undefined : type.symbol.declarations[0]; + errorNode = someBaseTypeHasBothIndexers ? undefined : type.symbol!.declarations![0]; } } - 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. @@ -22797,16 +22853,16 @@ namespace ts { const propDeclaration = prop.valueDeclaration; // index is numeric and property name is not valid numeric literal - if (indexKind === IndexKind.Number && !(propDeclaration ? isNumericName(getNameOfDeclaration(propDeclaration)) : isNumericLiteralName(prop.escapedName))) { + if (indexKind === IndexKind.Number && !(propDeclaration ? isNumericName(getNameOfDeclaration(propDeclaration)!) : isNumericLiteralName(prop.escapedName))) { return; } // 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 || + getNameOfDeclaration(propDeclaration)!.kind === SyntaxKind.ComputedPropertyName || prop.parent === containingType.symbol)) { errorNode = propDeclaration; } @@ -22818,7 +22874,7 @@ namespace ts { // check if any base class already has both property and indexer. // check should be performed only if 'type' is the first type that brings property\indexer together const someBaseClassHasBothPropertyAndIndexer = forEach(getBaseTypes(containingType), base => getPropertyOfObjectType(base, prop.escapedName) && getIndexTypeOfType(base, indexKind)); - errorNode = someBaseClassHasBothPropertyAndIndexer ? undefined : containingType.symbol.declarations[0]; + errorNode = someBaseClassHasBothPropertyAndIndexer ? undefined : containingType.symbol!.declarations![0]; } if (errorNode && !isTypeAssignableTo(propertyType, indexType)) { @@ -22849,7 +22905,7 @@ namespace ts { /** * Check each type parameter and check that type parameters have no duplicate type parameter declarations */ - function checkTypeParameters(typeParameterDeclarations: ReadonlyArray) { + function checkTypeParameters(typeParameterDeclarations: ReadonlyArray | undefined) { if (typeParameterDeclarations) { let seenDefault = false; for (let i = 0; i < typeParameterDeclarations.length; i++) { @@ -22875,7 +22931,7 @@ namespace ts { /** Check that type parameter lists are identical across multiple declarations */ function checkTypeParameterListsIdentical(symbol: Symbol) { - if (symbol.declarations.length === 1) { + if (symbol.declarations!.length === 1) { return; } @@ -22888,7 +22944,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) { @@ -22910,12 +22966,12 @@ namespace ts { } for (let i = 0; i < numTypeParameters; i++) { - const source = declaration.typeParameters[i]; + const source = declaration.typeParameters![i]; const target = typeParameters[i]; // If the type parameter node does not have the same as the resolved type // parameter at this position, we report an error. - if (source.name.escapedText !== target.symbol.escapedName) { + if (source.name.escapedText !== target.symbol!.escapedName) { return false; } @@ -22946,7 +23002,7 @@ namespace ts { function checkClassExpression(node: ClassExpression): Type { checkClassLikeDeclaration(node); checkNodeDeferred(node); - return getTypeOfSymbol(getSymbolOfNode(node)); + return getTypeOfSymbol(getSymbolOfNode(node)!); } function checkClassExpressionDeferred(node: ClassExpression) { @@ -22976,7 +23032,7 @@ namespace ts { } checkTypeParameters(node.typeParameters); checkExportsOnMergedDeclarations(node); - const symbol = getSymbolOfNode(node); + const symbol = getSymbolOfNode(node)!; const type = getDeclaredTypeOfSymbol(symbol); const typeWithThis = getTypeWithThisArgument(type); const staticType = getTypeOfSymbol(symbol); @@ -23004,7 +23060,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; } } @@ -23103,9 +23159,9 @@ 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)); + error(node, Diagnostics.Cannot_extend_a_class_0_Class_constructor_is_marked_as_private, getFullyQualifiedName(type.symbol!)); } } } @@ -23114,11 +23170,11 @@ 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) { - return filter(symbol.declarations, (d: Declaration): d is ClassDeclaration | InterfaceDeclaration => + return filter(symbol.declarations!, (d: Declaration): d is ClassDeclaration | InterfaceDeclaration => d.kind === SyntaxKind.ClassDeclaration || d.kind === SyntaxKind.InterfaceDeclaration); } @@ -23147,7 +23203,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."); @@ -23159,7 +23215,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), @@ -23204,7 +23260,7 @@ namespace ts { errorMessage = Diagnostics.Class_0_defines_instance_member_accessor_1_but_extended_class_2_defines_it_as_instance_member_function; } - error(getNameOfDeclaration(derived.valueDeclaration) || derived.valueDeclaration, errorMessage, typeToString(baseType), symbolToString(base), typeToString(type)); + error(getNameOfDeclaration(derived.valueDeclaration!) || derived.valueDeclaration, errorMessage, typeToString(baseType), symbolToString(base), typeToString(type)); } } } @@ -23256,7 +23312,7 @@ namespace ts { if (isInstancePropertyWithoutInitializer(member)) { const propName = (member).name; if (isIdentifier(propName)) { - const type = getTypeOfSymbol(getSymbolOfNode(member)); + const type = getTypeOfSymbol(getSymbolOfNode(member)!); // TODO: GH#18217 if (!(type.flags & TypeFlags.Any || getFalsyFlags(type) & TypeFlags.Undefined)) { if (!constructor || !isPropertyInitializedInConstructor(propName, type, constructor)) { error(member.name, Diagnostics.Property_0_has_no_initializer_and_is_not_definitely_assigned_in_the_constructor, declarationNameToString(propName)); @@ -23290,7 +23346,7 @@ namespace ts { checkTypeNameIsReserved(node.name, Diagnostics.Interface_name_cannot_be_0); checkExportsOnMergedDeclarations(node); - const symbol = getSymbolOfNode(node); + const symbol = getSymbolOfNode(node)!; checkTypeParameterListsIdentical(symbol); // Only check this symbol once @@ -23335,9 +23391,9 @@ namespace ts { function computeEnumMemberValues(node: EnumDeclaration) { const nodeLinks = getNodeLinks(node); - if (!(nodeLinks.flags & NodeCheckFlags.EnumValuesComputed)) { - nodeLinks.flags |= NodeCheckFlags.EnumValuesComputed; - let autoValue = 0; + if (!(nodeLinks.flags! & NodeCheckFlags.EnumValuesComputed)) { + nodeLinks.flags! |= NodeCheckFlags.EnumValuesComputed; + let autoValue: number | undefined = 0; for (const member of node.members) { const value = computeMemberValue(member, autoValue); getNodeLinks(member).enumMemberValue = value; @@ -23346,7 +23402,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); } @@ -23375,10 +23431,10 @@ namespace ts { return undefined; } - function computeConstantValue(member: EnumMember): string | number { - const enumKind = getEnumKind(getSymbolOfNode(member.parent)); + 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)) { @@ -23399,11 +23455,11 @@ namespace ts { } else { // Only here do we need to check that the initializer is assignable to the enum type. - checkTypeAssignableTo(checkExpression(initializer), getDeclaredTypeOfSymbol(getSymbolOfNode(member.parent)), initializer, /*headMessage*/ undefined); + checkTypeAssignableTo(checkExpression(initializer), getDeclaredTypeOfSymbol(getSymbolOfNode(member.parent)!), initializer, /*headMessage*/ undefined); } 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); @@ -23443,7 +23499,7 @@ namespace ts { case SyntaxKind.ParenthesizedExpression: return evaluate((expr).expression); case SyntaxKind.Identifier: - return nodeIsMissing(expr) ? 0 : evaluateEnumMember(expr, getSymbolOfNode(member.parent), (expr).escapedText); + return nodeIsMissing(expr) ? 0 : evaluateEnumMember(expr, getSymbolOfNode(member.parent)!, (expr).escapedText); case SyntaxKind.ElementAccessExpression: case SyntaxKind.PropertyAccessExpression: const ex = expr; @@ -23455,7 +23511,7 @@ namespace ts { name = ex.name.escapedText; } else { - const argument = ex.argumentExpression; + const argument = ex.argumentExpression!; Debug.assert(isLiteralExpression(argument)); name = escapeLeadingUnderscores((argument as LiteralExpression).text); } @@ -23468,9 +23524,9 @@ 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; + const declaration = memberSymbol.valueDeclaration!; if (declaration !== member) { if (isBlockScopedNameDeclaredBeforeUse(declaration, member)) { return getEnumMemberValue(declaration as EnumMember); @@ -23487,7 +23543,7 @@ namespace ts { return node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.PropertyAccessExpression && isConstantMemberAccess((node).expression) || node.kind === SyntaxKind.ElementAccessExpression && isConstantMemberAccess((node).expression) && - (node).argumentExpression.kind === SyntaxKind.StringLiteral; + (node).argumentExpression!.kind === SyntaxKind.StringLiteral; } function checkEnumDeclaration(node: EnumDeclaration) { @@ -23518,10 +23574,10 @@ namespace ts { // for the first member. // // Only perform this check once per symbol - const enumSymbol = getSymbolOfNode(node); + const enumSymbol = getSymbolOfNode(node)!; const firstDeclaration = getDeclarationOfKind(enumSymbol, node.kind); if (node === firstDeclaration) { - if (enumSymbol.declarations.length > 1) { + if (enumSymbol.declarations!.length > 1) { // check that const is placed\omitted on all enum declarations forEach(enumSymbol.declarations, decl => { if (isConstEnumDeclaration(decl) !== enumIsConst) { @@ -23555,8 +23611,8 @@ namespace ts { } } - function getFirstNonAmbientClassOrFunctionDeclaration(symbol: Symbol): Declaration { - const declarations = symbol.declarations; + function getFirstNonAmbientClassOrFunctionDeclaration(symbol: Symbol): Declaration | undefined { + const declarations = symbol.declarations!; for (const declaration of declarations) { if ((declaration.kind === SyntaxKind.ClassDeclaration || (declaration.kind === SyntaxKind.FunctionDeclaration && nodeIsPresent((declaration).body))) && @@ -23612,13 +23668,13 @@ namespace ts { } checkExportsOnMergedDeclarations(node); - const symbol = getSymbolOfNode(node); + const symbol = getSymbolOfNode(node)!; // The following checks only apply on a non-ambient instantiated module declaration. if (symbol.flags & SymbolFlags.ValueModule - && symbol.declarations.length > 1 + && 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)) { @@ -23634,7 +23690,7 @@ namespace ts { const mergedClass = getDeclarationOfKind(symbol, SyntaxKind.ClassDeclaration); if (mergedClass && inSameLexicalScope(node, mergedClass)) { - getNodeLinks(node).flags |= NodeCheckFlags.LexicalModuleMergesWithClass; + getNodeLinks(node).flags! |= NodeCheckFlags.LexicalModuleMergesWithClass; } } @@ -23645,7 +23701,7 @@ namespace ts { // We can detect if augmentation was applied using following rules: // - augmentation for a global scope is always applied // - augmentation for some external module is applied if symbol for augmentation is merged (it was combined with target module). - const checkBody = isGlobalAugmentation || (getSymbolOfNode(node).flags & SymbolFlags.Transient); + const checkBody = isGlobalAugmentation || (getSymbolOfNode(node)!.flags & SymbolFlags.Transient); if (checkBody && node.body) { // body of ambient external module is always a module block for (const statement of (node.body).statements) { @@ -23727,7 +23783,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; @@ -23753,7 +23809,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; } @@ -23784,7 +23840,7 @@ namespace ts { } function checkAliasSymbol(node: ImportEqualsDeclaration | ImportClause | NamespaceImport | ImportSpecifier | ExportSpecifier) { - const symbol = getSymbolOfNode(node); + const symbol = getSymbolOfNode(node)!; const target = resolveAlias(symbol); if (target !== unknownSymbol) { // For external modules symbol represent local symbol for an alias. @@ -23816,8 +23872,8 @@ namespace ts { function checkImportBinding(node: ImportEqualsDeclaration | ImportClause | NamespaceImport | ImportSpecifier) { checkCollisionWithCapturedThisVariable(node, node.name); - checkCollisionWithRequireExportsInGeneratedCode(node, node.name); - checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name); + checkCollisionWithRequireExportsInGeneratedCode(node, node.name!); + checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name!); checkAliasSymbol(node); } @@ -23860,12 +23916,12 @@ namespace ts { markExportAsReferenced(node); } if (node.moduleReference.kind !== SyntaxKind.ExternalModuleReference) { - const target = resolveAlias(getSymbolOfNode(node)); + const target = resolveAlias(getSymbolOfNode(node)!); if (target !== unknownSymbol) { 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)); } } @@ -23908,7 +23964,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)); } @@ -23938,7 +23994,7 @@ namespace ts { // find immediate value referenced by exported name (SymbolFlags.Alias is set so we don't chase down aliases) const symbol = resolveName(exportedName, exportedName.escapedText, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true); - if (symbol && (symbol === undefinedSymbol || isGlobalSourceFile(getDeclarationContainer(symbol.declarations[0])))) { + if (symbol && (symbol === undefinedSymbol || isGlobalSourceFile(getDeclarationContainer(symbol.declarations![0])))) { error(exportedName, Diagnostics.Cannot_export_0_Only_local_declarations_can_be_exported_from_a_module, idText(exportedName)); } else { @@ -23998,16 +24054,16 @@ 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 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; + const declaration = getDeclarationOfAliasSymbol(exportEqualsSymbol) || exportEqualsSymbol.valueDeclaration!; if (!isTopLevelInExternalModuleAugmentation(declaration)) { error(declaration, Diagnostics.An_export_assignment_cannot_be_used_in_a_module_with_other_exported_elements); } @@ -24024,14 +24080,14 @@ namespace ts { if (flags & (SymbolFlags.Namespace | SymbolFlags.Interface | SymbolFlags.Enum)) { return; } - const exportedDeclarationsCount = countWhere(declarations, isNotOverloadAndNotAccessor); + const exportedDeclarationsCount = countWhere(declarations!, isNotOverloadAndNotAccessor); if (flags & SymbolFlags.TypeAlias && exportedDeclarationsCount <= 2) { // it is legal to merge type alias with other values // so count should be either 1 (just type alias) or 2 (type alias + merged value) return; } if (exportedDeclarationsCount > 1) { - for (const declaration of declarations) { + for (const declaration of declarations!) { if (isNotOverload(declaration)) { diagnostics.add(createDiagnosticForNode(declaration, Diagnostics.Cannot_redeclare_exported_variable_0, unescapeLeadingUnderscores(id))); } @@ -24053,15 +24109,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; @@ -24228,12 +24282,11 @@ namespace ts { checkSourceElement(node.type); // Only legal location is in the *last* parameter tag. - const { parent } = node; - if (!isJSDocTypeExpression(parent)) { + if (!isJSDocTypeExpression(node.parent)) { 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; @@ -24253,9 +24306,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 param = getParameterSymbolFromJSDoc(paramTag); if (param) { @@ -24267,7 +24319,7 @@ namespace ts { function f(a) {} Because `a` will just be of type `number | undefined`. A synthetic `...args` will also be added, which *will* get an array type. */ - const lastParamDeclaration = host && last(host.parameters); + const lastParamDeclaration = (host && last(host.parameters))!; // TODO: GH#18217 if (lastParamDeclaration.symbol === param && isRestParameter(lastParamDeclaration)) { return createArrayType(type); } @@ -24292,7 +24344,7 @@ namespace ts { } function checkDeferredNodes() { - for (const node of deferredNodes) { + for (const node of deferredNodes!) { switch (node.kind) { case SyntaxKind.FunctionExpression: case SyntaxKind.ArrowFunction: @@ -24321,7 +24373,7 @@ namespace ts { // Fully type check a source file and collect the relevant diagnostics. function checkSourceFileWorker(node: SourceFile) { const links = getNodeLinks(node); - if (!(links.flags & NodeCheckFlags.TypeChecked)) { + if (!(links.flags! & NodeCheckFlags.TypeChecked)) { // If skipLibCheck is enabled, skip type checking if file is a declaration file. // If skipDefaultLibCheck is enabled, skip type checking if file contains a // '/// ' directive. @@ -24368,7 +24420,7 @@ namespace ts { clear(potentialNewTargetCollisions); } - links.flags |= NodeCheckFlags.TypeChecked; + links.flags! |= NodeCheckFlags.TypeChecked; } } @@ -24453,15 +24505,15 @@ namespace ts { switch (location.kind) { case SyntaxKind.ModuleDeclaration: - copySymbols(getSymbolOfNode(location).exports, meaning & SymbolFlags.ModuleMember); + copySymbols(getSymbolOfNode(location)!.exports!, meaning & SymbolFlags.ModuleMember); break; case SyntaxKind.EnumDeclaration: - copySymbols(getSymbolOfNode(location).exports, meaning & SymbolFlags.EnumMember); + copySymbols(getSymbolOfNode(location)!.exports!, meaning & SymbolFlags.EnumMember); break; case SyntaxKind.ClassExpression: const className = (location).name; if (className) { - copySymbol(location.symbol, meaning); + copySymbol(location.symbol!, meaning); } // falls through // this fall-through is necessary because we would like to handle @@ -24473,13 +24525,13 @@ 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)!), meaning & SymbolFlags.Type); } break; case SyntaxKind.FunctionExpression: const funcName = (location).name; if (funcName) { - copySymbol(location.symbol, meaning); + copySymbol(location.symbol!, meaning); } break; } @@ -24537,33 +24589,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; } @@ -24588,17 +24640,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; @@ -24674,7 +24726,7 @@ namespace ts { } } - if (entityName.parent!.kind === SyntaxKind.JSDocParameterTag) { + if (entityName.parent.kind === SyntaxKind.JSDocParameterTag) { return getParameterSymbolFromJSDoc(entityName.parent as JSDocParameterTag); } @@ -24733,6 +24785,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 @@ -24741,20 +24795,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) { @@ -24801,33 +24855,33 @@ namespace ts { // 1). import x = require("./mo/*gotToDefinitionHere*/d") // 2). External module name in an import declaration // 3). Dynamic import call or require in javascript - if ((isExternalModuleImportEqualsDeclaration(node.parent.parent) && getExternalModuleImportEqualsDeclarationExpression(node.parent.parent) === node) || - ((node.parent.kind === SyntaxKind.ImportDeclaration || node.parent.kind === SyntaxKind.ExportDeclaration) && (node.parent).moduleSpecifier === node) || - ((isInJavaScriptFile(node) && isRequireCall(node.parent, /*checkArgumentIsStringLiteral*/ false)) || isImportCall(node.parent))) { + if ((isExternalModuleImportEqualsDeclaration(grandParent) && getExternalModuleImportEqualsDeclarationExpression(grandParent) === node) || + ((parent.kind === SyntaxKind.ImportDeclaration || parent.kind === SyntaxKind.ExportDeclaration) && (parent).moduleSpecifier === node) || + ((isInJavaScriptFile(node) && isRequireCall(parent, /*checkArgumentIsStringLiteral*/ false)) || isImportCall(parent))) { return resolveExternalModuleName(node, node); } // falls through 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)); case SyntaxKind.DefaultKeyword: case SyntaxKind.FunctionKeyword: case SyntaxKind.EqualsGreaterThanToken: - return getSymbolOfNode(node.parent); + return getSymbolOfNode(parent); default: return undefined; } } - function getShorthandAssignmentValueSymbol(location: Node): Symbol { + function getShorthandAssignmentValueSymbol(location: Node): Symbol | undefined { // The function returns a value symbol of an identifier in the short-hand property assignment. // This is necessary as an identifier in short-hand property assignment can contains two meaning: // property name and property value. @@ -24838,13 +24892,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; @@ -24854,7 +24908,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); } @@ -24869,15 +24923,15 @@ 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 classType = getDeclaredTypeOfSymbol(getSymbolOfNode(classNode)) as InterfaceType; + const classNode = getContainingClass(node)!; + const classType = getDeclaredTypeOfSymbol(getSymbolOfNode(classNode)!) as InterfaceType; const baseType = getBaseTypes(classType)[0]; return baseType && getTypeWithThisArgument(baseType, classType.thisType); } if (isTypeDeclaration(node)) { // In this case, we call getSymbolOfNode instead of getSymbolAtLocation because it is a declaration - const symbol = getSymbolOfNode(node); + const symbol = getSymbolOfNode(node)!; return getDeclaredTypeOfSymbol(symbol); } @@ -24888,7 +24942,7 @@ namespace ts { if (isDeclaration(node)) { // In this case, we call getSymbolOfNode instead of getSymbolAtLocation because it is a declaration - const symbol = getSymbolOfNode(node); + const symbol = getSymbolOfNode(node)!; return getTypeOfSymbol(symbol); } @@ -24937,7 +24991,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); @@ -24945,7 +24999,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 @@ -24972,7 +25026,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); @@ -25003,11 +25057,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)); } @@ -25015,7 +25069,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; } @@ -25024,9 +25078,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; @@ -25057,7 +25111,7 @@ namespace ts { : forEachEntry(getExportsOfModule(moduleSymbol), isValue); } - return symbolLinks.exportsSomeValue; + return symbolLinks.exportsSomeValue!; function isValue(s: Symbol): boolean { s = resolveSymbol(s); @@ -25066,14 +25120,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. @@ -25085,7 +25138,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; } @@ -25093,7 +25146,7 @@ namespace ts { } const parentSymbol = getParentOfSymbol(symbol); if (parentSymbol) { - if (parentSymbol.flags & SymbolFlags.ValueModule && parentSymbol.valueDeclaration.kind === SyntaxKind.SourceFile) { + if (parentSymbol.flags & SymbolFlags.ValueModule && parentSymbol.valueDeclaration!.kind === SyntaxKind.SourceFile) { const symbolFile = parentSymbol.valueDeclaration; const referenceFile = getSourceFileOfNode(node); // If `node` accesses an export and that export isn't in the same file, then symbol is a namespace export, so return undefined. @@ -25108,14 +25161,14 @@ 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 // declaration for the symbol if (isNonLocalAlias(symbol, /*excludes*/ SymbolFlags.Value)) { - return getDeclarationOfAliasSymbol(symbol); + return getDeclarationOfAliasSymbol(symbol!); } } @@ -25126,14 +25179,14 @@ namespace ts { if (symbol.flags & SymbolFlags.BlockScoped) { const links = getSymbolLinks(symbol); if (links.isDeclarationWithCollidingName === undefined) { - const container = getEnclosingBlockScopeContainer(symbol.valueDeclaration); + const container = getEnclosingBlockScopeContainer(symbol.valueDeclaration!); if (isStatementWithLocals(container)) { - const nodeLinks = getNodeLinks(symbol.valueDeclaration); + const nodeLinks = getNodeLinks(symbol.valueDeclaration!); if (resolveName(container.parent, symbol.escapedName, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false)) { // redeclaration - always should be renamed links.isDeclarationWithCollidingName = true; } - else if (nodeLinks.flags & NodeCheckFlags.CapturedBlockScopedBinding) { + else if (nodeLinks.flags! & NodeCheckFlags.CapturedBlockScopedBinding) { // binding is captured in the function // should be renamed if: // - binding is not top level - top level bindings never collide with anything @@ -25149,7 +25202,7 @@ namespace ts { // * variables from initializer are passed to rewritten loop body as parameters so they are not captured directly // * variables that are declared immediately in loop body will become top level variable after loop is rewritten and thus // they will not collide with anything - const isDeclaredInLoop = nodeLinks.flags & NodeCheckFlags.BlockScopedBindingInLoop; + const isDeclaredInLoop = nodeLinks.flags! & NodeCheckFlags.BlockScopedBindingInLoop; const inLoopInitializer = isIterationStatement(container, /*lookInLabeledStatements*/ false); const inLoopBodyBlock = container.kind === SyntaxKind.Block && isIterationStatement(container.parent, /*lookInLabeledStatements*/ false); @@ -25160,7 +25213,7 @@ namespace ts { } } } - return links.isDeclarationWithCollidingName; + return links.isDeclarationWithCollidingName!; } return false; } @@ -25168,9 +25221,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)) { @@ -25184,8 +25237,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) { @@ -25206,7 +25259,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 @@ -25216,14 +25269,14 @@ 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; } - const isValue = isAliasResolvedToValue(getSymbolOfNode(node)); + const isValue = isAliasResolvedToValue(getSymbolOfNode(node)!); return isValue && node.moduleReference && !nodeIsMissing(node.moduleReference); } @@ -25234,12 +25287,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 { @@ -25248,7 +25301,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; @@ -25256,7 +25309,7 @@ namespace ts { } if (checkChildren) { - return forEachChild(node, node => isReferencedAliasDeclaration(node, checkChildren)); + return !!forEachChild(node, node => isReferencedAliasDeclaration(node, checkChildren)); } return false; } @@ -25282,10 +25335,10 @@ namespace ts { return false; } - function isRequiredInitializedParameter(parameter: ParameterDeclaration) { + function isRequiredInitializedParameter(parameter: ParameterDeclaration): boolean { return strictNullChecks && !isOptionalParameter(parameter) && - parameter.initializer && + !!parameter.initializer && !hasModifier(parameter, ModifierFlags.ParameterPropertyModifier); } @@ -25297,10 +25350,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; } @@ -25315,7 +25368,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); } @@ -25323,7 +25376,7 @@ namespace ts { const symbol = getNodeLinks(node).resolvedSymbol; if (symbol && (symbol.flags & SymbolFlags.EnumMember)) { // inline property\index accesses only for const enums - if (isConstEnumDeclaration(symbol.valueDeclaration.parent)) { + if (isConstEnumDeclaration(symbol.valueDeclaration!.parent)) { return getEnumMemberValue(symbol.valueDeclaration); } } @@ -25332,12 +25385,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) { @@ -25432,7 +25485,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; @@ -25451,9 +25504,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) { @@ -25467,14 +25520,14 @@ namespace ts { function isLiteralConstDeclaration(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration): boolean { if (isConst(node)) { - const type = getTypeOfSymbol(getSymbolOfNode(node)); + const type = getTypeOfSymbol(getSymbolOfNode(node)!); return !!(type.flags & TypeFlags.StringOrNumberLiteral && type.flags & TypeFlags.FreshLiteral); } return false; } function writeLiteralConstValue(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration, writer: EmitTextWriter) { - const type = getTypeOfSymbol(getSymbolOfNode(node)); + const type = getTypeOfSymbol(getSymbolOfNode(node)!); writer.writeStringLiteral(literalTypeToString(type)); } @@ -25490,7 +25543,7 @@ namespace ts { if (!resolvedDirective) { return; } - const file = host.getSourceFile(resolvedDirective.resolvedFileName); + const file = host.getSourceFile(resolvedDirective.resolvedFileName!)!; // TODO: GH#18217 fileToDirective.set(file.path, key); }); } @@ -25512,7 +25565,7 @@ namespace ts { }, getNodeCheckFlags: node => { node = getParseTreeNode(node); - return node ? getNodeCheckFlags(node) : undefined; + return node ? getNodeCheckFlags(node) : 0; }, isTopLevelValueImportEqualsWithEntityName, isDeclarationVisible, @@ -25524,8 +25577,8 @@ namespace ts { writeTypeOfExpression, isSymbolAccessible, isEntityNameVisible, - getConstantValue: node => { - node = getParseTreeNode(node, canHaveConstantValue); + getConstantValue: nodeIn => { + const node = getParseTreeNode(nodeIn, canHaveConstantValue); return node ? getConstantValue(node) : undefined; }, collectLinkedAliases, @@ -25538,17 +25591,17 @@ 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); }, writeLiteralConstValue, - getJsxFactoryEntity: () => _jsxFactoryEntity + getJsxFactoryEntity: () => _jsxFactoryEntity!, // TODO: GH#18217 }; // 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; @@ -25565,7 +25618,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; @@ -25574,10 +25627,10 @@ namespace ts { return undefined; } // check what declarations in the symbol can contribute to the target meaning - let typeReferenceDirectives: string[]; - for (const decl of symbol.declarations) { + 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) { @@ -25626,8 +25679,8 @@ namespace ts { } } - function getExternalModuleFileFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration): SourceFile { - const specifier = getExternalModuleName(declaration); + function getExternalModuleFileFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration): SourceFile | undefined { + const specifier = getExternalModuleName(declaration)!; // TODO: GH#18217 const moduleSymbol = resolveExternalModuleNameWorker(specifier, specifier, /*moduleNotFoundError*/ undefined); if (!moduleSymbol) { return undefined; @@ -25642,10 +25695,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); @@ -25730,7 +25783,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); } @@ -25761,7 +25814,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"); } } @@ -25791,7 +25844,7 @@ namespace ts { } else if (node.kind === SyntaxKind.GetAccessor || node.kind === SyntaxKind.SetAccessor) { const accessors = getAllAccessorDeclarations((node.parent).members, node); - if (accessors.firstAccessor.decorators && node === accessors.secondAccessor) { + if (accessors.firstAccessor!.decorators && node === accessors.secondAccessor) { return grammarErrorOnFirstToken(node, Diagnostics.Decorators_cannot_be_applied_to_multiple_get_Slashset_accessors_of_the_same_name); } } @@ -25804,9 +25857,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)); @@ -25979,21 +26032,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); @@ -26002,8 +26055,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; } /** @@ -26058,7 +26112,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 { @@ -26073,20 +26127,22 @@ namespace ts { return grammarErrorOnNode(asyncModifier, Diagnostics._0_modifier_cannot_be_used_here, "async"); } - function checkGrammarForDisallowedTrailingComma(list: NodeArray): boolean { + function checkGrammarForDisallowedTrailingComma(list: NodeArray | undefined): boolean { if (list && list.hasTrailingComma) { const start = list.end - ",".length; const end = list.end; return grammarErrorAtPos(list[0], start, end - start, Diagnostics.Trailing_comma_not_allowed); } + return false; } - function checkGrammarTypeParameterList(typeParameters: NodeArray, file: SourceFile): boolean { + function checkGrammarTypeParameterList(typeParameters: NodeArray | undefined, file: SourceFile): boolean { if (typeParameters && typeParameters.length === 0) { const start = typeParameters.pos - "<".length; 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) { @@ -26181,7 +26237,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 (allTypesAssignableToKind(type, TypeFlags.StringLiteral, /*strict*/ true)) { @@ -26194,6 +26250,7 @@ namespace ts { if (!node.type) { return grammarErrorOnNode(node, Diagnostics.An_index_signature_must_have_a_type_annotation); } + return false; } function checkGrammarIndexSignature(node: SignatureDeclaration) { @@ -26201,21 +26258,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) { @@ -26223,9 +26281,10 @@ namespace ts { } } } + return false; } - function checkGrammarArguments(args: NodeArray): boolean { + function checkGrammarArguments(args: NodeArray | undefined): boolean { return checkGrammarForOmittedArgument(args); } @@ -26238,7 +26297,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) { @@ -26315,6 +26374,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) { @@ -26324,18 +26384,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) { @@ -26360,12 +26418,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)); } @@ -26400,7 +26458,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); @@ -26546,6 +26604,7 @@ namespace ts { } } } + return false; } /** Does the accessor have the right number of parameters? @@ -26556,7 +26615,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); } @@ -26800,6 +26859,7 @@ namespace ts { } } } + return false; } function checkGrammarNameInLetOrConstDeclarations(name: Identifier | BindingPattern): boolean { @@ -26816,6 +26876,7 @@ namespace ts { } } } + return false; } function checkGrammarVariableDeclarationList(declarationList: VariableDeclarationList): boolean { @@ -26827,6 +26888,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 { @@ -26876,6 +26938,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 { @@ -26884,6 +26947,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 { @@ -26892,6 +26956,7 @@ namespace ts { diagnostics.add(createDiagnosticForNode(node, message, arg0, arg1, arg2)); return true; } + return false; } function checkGrammarConstructorTypeParameters(node: ConstructorDeclaration) { @@ -26977,6 +27042,7 @@ namespace ts { } } } + return false; } function checkGrammarSourceFile(node: SourceFile): boolean { @@ -27014,11 +27080,12 @@ namespace ts { // Debug.assert(isStatement(node.parent)); } } + return false; } function checkGrammarNumericLiteral(node: NumericLiteral): boolean { // Grammar checking - if (node.numericLiteralFlags & TokenFlags.Octal) { + if (node.numericLiteralFlags! & TokenFlags.Octal) { let diagnosticMessage: DiagnosticMessage | undefined; if (languageVersion >= ScriptTarget.ES5) { diagnosticMessage = Diagnostics.Octal_literals_are_not_available_when_targeting_ECMAScript_5_and_higher_Use_the_syntax_0; @@ -27035,6 +27102,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 { @@ -27044,6 +27112,7 @@ namespace ts { diagnostics.add(createFileDiagnostic(sourceFile, textSpanEnd(span), /*length*/ 0, message, arg0, arg1, arg2)); return true; } + return false; } function getAmbientModules(): Symbol[] { @@ -27052,7 +27121,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); } }); } @@ -27078,6 +27147,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 825f2c632e75d..360851d091723 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -785,7 +785,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)); } } @@ -1088,7 +1088,7 @@ namespace ts { if (extraKeyDiagnosticMessage && !option) { errors.push(createDiagnosticForNodeInSourceFile(sourceFile, element.name, extraKeyDiagnosticMessage, keyText)); } - const value = convertPropertyValueToJson(element.initializer, option); + const value = convertPropertyValueToJson(element.initializer!, option); // TODO: GH#18217 if (typeof keyText !== "undefined") { result[keyText] = value; // Notify key value set, if user asked for it @@ -1099,17 +1099,17 @@ 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 (knownOptions === knownRootOptions) { if (isValidOptionValue) { // Notify about the valid root key value being set - jsonConversionNotifier.onSetValidOptionKeyValueInRoot(keyText, element.name, value, element.initializer); + jsonConversionNotifier.onSetValidOptionKeyValueInRoot(keyText, element.name, value, element.initializer!); } else if (!option) { // Notify about the unknown root key value being set - jsonConversionNotifier.onSetUnknownOptionKeyValueInRoot(keyText, element.name, value, element.initializer); + jsonConversionNotifier.onSetUnknownOptionKeyValueInRoot(keyText, element.name, value, element.initializer!); } } } @@ -1125,7 +1125,7 @@ namespace ts { return elements.map(element => 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"); @@ -1208,9 +1208,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!))); } } } @@ -1226,7 +1226,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") { @@ -1235,6 +1235,7 @@ namespace ts { const expectedType = isString(option.type) ? option.type : "string"; return typeof value === expectedType; } + return false; } /** @@ -1278,7 +1279,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]; @@ -1292,7 +1293,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 @@ -1398,7 +1399,7 @@ namespace ts { * file to. e.g. outDir */ export function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string, resolutionStack?: Path[], extraFileExtensions?: ReadonlyArray): ParsedCommandLine { - return parseJsonConfigFileContentWorker(json, /*sourceFile*/ undefined, host, basePath, existingOptions, configFileName, resolutionStack, extraFileExtensions); + return parseJsonConfigFileContentWorker(json, /*sourceFile*/ undefined!, host, basePath, existingOptions, configFileName, resolutionStack, extraFileExtensions); // TODO: GH#18217 } /** @@ -1413,7 +1414,7 @@ namespace ts { } /*@internal*/ - export function setConfigFileInOptions(options: CompilerOptions, configFile: JsonSourceFile) { + export function setConfigFileInOptions(options: CompilerOptions, configFile: JsonSourceFile | undefined) { if (configFile) { Object.defineProperty(options, "configFile", { enumerable: false, writable: false, value: configFile }); } @@ -1470,7 +1471,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; @@ -1483,7 +1484,7 @@ namespace ts { } } - let includeSpecs: ReadonlyArray; + let includeSpecs: ReadonlyArray | undefined; if (hasProperty(raw, "include") && !isNullOrUndefined(raw.include)) { if (isArray(raw.include)) { includeSpecs = >raw.include; @@ -1493,7 +1494,7 @@ namespace ts { } } - let excludeSpecs: ReadonlyArray; + let excludeSpecs: ReadonlyArray | undefined; if (hasProperty(raw, "exclude") && !isNullOrUndefined(raw.exclude)) { if (isArray(raw.exclude)) { excludeSpecs = >raw.exclude; @@ -1565,7 +1566,7 @@ namespace ts { sourceFile: JsonSourceFile, host: ParseConfigHost, basePath: string, - configFileName: string, + configFileName: string | undefined, resolutionStack: string[], errors: Push, ): ParsedTsconfig { @@ -1624,7 +1625,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)) { @@ -1646,8 +1647,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) { @@ -1749,7 +1750,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)) { @@ -1773,13 +1774,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[] } { @@ -1973,9 +1971,9 @@ 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, @@ -1984,7 +1982,7 @@ namespace ts { jsonSourceFile: JsonSourceFile ): 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 @@ -2094,8 +2092,9 @@ namespace ts { function createDiagnostic(message: DiagnosticMessage, spec: string): Diagnostic { if (jsonSourceFile && jsonSourceFile.jsonObject) { for (const property of getPropertyAssignment(jsonSourceFile.jsonObject, specKey)) { - if (isArrayLiteralExpression(property.initializer)) { - for (const element of property.initializer.elements) { + const initializer = property.initializer!; + if (isArrayLiteralExpression(initializer)) { + for (const element of initializer.elements) { if (isStringLiteral(element) && element.text === spec) { return createDiagnosticForNodeInSourceFile(jsonSourceFile, element, message, spec); } @@ -2119,7 +2118,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: // @@ -2279,7 +2278,7 @@ namespace ts { if (optionEnumValue === value) { return optionStringValue; } - }); + })!; // TODO: GH#18217 } } } diff --git a/src/compiler/comments.ts b/src/compiler/comments.ts index 1fec1e9562fc1..8eb7755c9abaf 100644 --- a/src/compiler/comments.ts +++ b/src/compiler/comments.ts @@ -5,8 +5,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; @@ -22,9 +22,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, @@ -46,7 +46,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. @@ -116,7 +116,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) { @@ -172,7 +172,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) { @@ -357,9 +357,9 @@ namespace ts { } function reset() { - currentSourceFile = undefined; - currentText = undefined; - currentLineMap = undefined; + currentSourceFile = undefined!; + currentText = undefined!; + currentLineMap = undefined!; detachedCommentsInfo = undefined; } @@ -375,14 +375,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 ecf667237c50e..910b1037c3db0 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -63,9 +63,9 @@ namespace ts { // Copies keys/values from template. Note that for..in will not throw if // template is undefined, and instead will just exit the loop. - for (const key in template) { + for (const key in template!) { if (hasOwnProperty.call(template, key)) { - map.set(key, template[key]); + map.set(key, template![key]); } } @@ -106,7 +106,7 @@ namespace ts { private data = createDictionaryObject(); public size = 0; - get(key: string): T { + get(key: string): T | undefined { return this.data[key]; } @@ -137,15 +137,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]); } @@ -164,7 +164,7 @@ namespace ts { return getCanonicalFileName(nonCanonicalizedPath); } - export function length(array: ReadonlyArray) { + export function length(array: ReadonlyArray | undefined): number { return array ? array.length : 0; } @@ -219,9 +219,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") { @@ -330,10 +330,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)) { @@ -378,7 +378,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; @@ -414,8 +418,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++) { @@ -438,7 +444,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]; @@ -461,8 +469,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) { @@ -486,8 +496,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++) { @@ -543,7 +555,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]; @@ -623,7 +635,9 @@ namespace ts { * Computes the first matching span of elements and returns a tuple of the first span * and the remaining elements. */ - export function span(array: ReadonlyArray, f: (x: T, i: number) => boolean): [T[], T[]] { + export function span(array: ReadonlyArray, f: (x: T, i: number) => boolean): [T[], T[]]; + export function span(array: ReadonlyArray | undefined, f: (x: T, i: number) => boolean): [T[], T[]] | undefined; + export function span(array: ReadonlyArray | undefined, f: (x: T, i: number) => boolean): [T[], T[]] | undefined { if (array) { for (let i = 0; i < array.length; i++) { if (!f(array[i], i)) { @@ -643,13 +657,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) { @@ -667,7 +683,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); } @@ -683,7 +699,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; } @@ -696,7 +714,7 @@ namespace ts { return result; } - export function some(array: ReadonlyArray, 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) { @@ -712,11 +730,15 @@ namespace ts { return false; } - export function concatenate(array1: T[], array2: T[]): T[]; - export function concatenate(array1: ReadonlyArray, array2: ReadonlyArray): ReadonlyArray; - export function concatenate(array1: T[], array2: T[]): T[] { - if (!some(array2)) return array1; - if (!some(array1)) return array2; + export function concatenate(array1: T[], array2: T[] | undefined): T[]; + export function concatenate(array1: T[] | undefined, array2: T[]): T[]; + export function concatenate(array1: T[] | undefined, array2: T[] | undefined): T[] | undefined; + export function concatenate(array1: ReadonlyArray | undefined, array2: ReadonlyArray): ReadonlyArray; + export function concatenate(array1: ReadonlyArray, array2: ReadonlyArray | undefined): ReadonlyArray; + export function concatenate(array1: ReadonlyArray | undefined, array2: ReadonlyArray | undefined): ReadonlyArray | undefined; + export function concatenate(array1: ReadonlyArray | undefined, array2: ReadonlyArray | undefined): ReadonlyArray | undefined { + if (!array2 || !array2.length) return array1; + if (!array1 || !array1.length) return array2; return [...array1, ...array2]; } @@ -756,7 +778,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() : @@ -767,7 +791,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 []; @@ -810,7 +836,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; } @@ -853,7 +879,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]; @@ -930,6 +956,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]; @@ -955,6 +984,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); @@ -1002,7 +1033,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); } @@ -1084,7 +1115,7 @@ namespace ts { /** * Returns the last element of an array if non-empty, `undefined` otherwise. */ - export function lastOrUndefined(array: ReadonlyArray): T | undefined { + export function lastOrUndefined(array: ReadonlyArray | undefined): T | undefined { return elementAt(array, -1); } @@ -1096,7 +1127,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; @@ -1108,7 +1139,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; @@ -1157,9 +1190,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) { @@ -1171,7 +1204,7 @@ namespace ts { pos++; } else { - result = initial; + result = initial!; } while (pos <= end) { result = f(result, array[pos], pos); @@ -1302,7 +1335,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) { @@ -1480,10 +1513,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)}'.`); } } @@ -1512,7 +1545,7 @@ namespace ts { return () => { if (callback) { value = callback(); - callback = undefined; + callback = undefined!; } return value; }; @@ -1584,19 +1617,17 @@ namespace ts { } } - export function formatStringFromArgs(text: string, args: { [index: number]: string; }, baseIndex?: number): string { - baseIndex = baseIndex || 0; - + export function formatStringFromArgs(text: string, args: { [index: number]: string; }, baseIndex = 0): string { return text.replace(/{(\d+)}/g, (_match, index?) => args[+index + baseIndex]); } - export let localizedDiagnosticMessages: MapLike = undefined; + 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)[]): Diagnostic; + export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage, ...args: (string | number | undefined)[]): Diagnostic; export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage): Diagnostic { Debug.assertGreaterThanOrEqual(start, 0); Debug.assertGreaterThanOrEqual(length, 0); @@ -1634,7 +1665,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); @@ -1665,8 +1696,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) { @@ -1721,9 +1752,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 : @@ -1735,7 +1766,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); } @@ -1770,7 +1801,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); } @@ -1869,7 +1900,7 @@ namespace ts { return uiLocale; } - export function setUILocale(value: string) { + export function setUILocale(value: string | undefined) { if (uiLocale !== value) { uiLocale = value; uiComparerCaseSensitive = undefined; @@ -1891,14 +1922,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 getDiagnosticFileName(diagnostic: Diagnostic): string { + function getDiagnosticFileName(diagnostic: Diagnostic): string | undefined { return diagnostic.file ? diagnostic.file.fileName : undefined; } @@ -1916,7 +1947,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; @@ -2074,7 +2107,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 { @@ -2093,8 +2126,8 @@ namespace ts { return true; } - export function isRootedDiskPath(path: string) { - return path && getRootLength(path) !== 0; + export function isRootedDiskPath(path: string): boolean { + return path !== undefined && getRootLength(path) !== 0; } export function convertToRelativePath(absoluteOrRelativePath: string, basePath: string, getCanonicalFileName: (path: string) => string): string { @@ -2120,11 +2153,11 @@ namespace ts { return normalizedPathComponents(path, rootLength); } - export function getNormalizedAbsolutePath(fileName: string, currentDirectory: string) { - return getNormalizedPathFromPathComponents(getNormalizedPathComponents(fileName, currentDirectory)); + export function getNormalizedAbsolutePath(fileName: string, currentDirectory: string): string { + return getNormalizedPathFromPathComponents(getNormalizedPathComponents(fileName, currentDirectory))!; } - export function getNormalizedPathFromPathComponents(pathComponents: ReadonlyArray) { + export function getNormalizedPathFromPathComponents(pathComponents: ReadonlyArray | undefined): string | undefined { if (pathComponents && pathComponents.length) { return pathComponents[0] + pathComponents.slice(1).join(directorySeparator); } @@ -2212,7 +2245,7 @@ namespace ts { } // Cant find the relative path, get the absolute path - let absolutePath = getNormalizedPathFromPathComponents(pathComponents); + let absolutePath = getNormalizedPathFromPathComponents(pathComponents)!; if (isAbsolutePathAnUrl && isRootedDiskPath(absolutePath)) { absolutePath = "file:///" + absolutePath; } @@ -2220,6 +2253,8 @@ namespace ts { return absolutePath; } + export function getBaseFileName(path: string): string; + export function getBaseFileName(path: string | undefined): string | undefined; export function getBaseFileName(path: string) { if (path === undefined) { return undefined; @@ -2397,7 +2432,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; @@ -2409,7 +2444,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; } @@ -2430,7 +2465,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; } @@ -2513,15 +2548,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); @@ -2535,7 +2570,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); @@ -2560,7 +2595,7 @@ namespace ts { function visitDirectory(path: string, absolutePath: string, depth: number | undefined) { const { files, directories } = getFileSystemEntries(path); - for (const current of sort(files, comparer)) { + for (const current of sort(files, comparer)) { const name = combinePaths(path, current); const absoluteName = combinePaths(absolutePath, current); if (extensions && !fileExtensionIsOneOf(name, extensions)) continue; @@ -2583,7 +2618,7 @@ namespace ts { } } - for (const current of sort(directories, comparer)) { + for (const current of sort(directories, comparer)) { const name = combinePaths(path, current); const absoluteName = combinePaths(absolutePath, current); if ((!includeDirectoryRegex || includeDirectoryRegex.test(absoluteName)) && @@ -2597,7 +2632,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]; @@ -2680,19 +2715,19 @@ namespace ts { if (!extraFileExtensions || extraFileExtensions.length === 0 || !needAllExtensions) { return needAllExtensions ? allSupportedExtensions : supportedTypeScriptExtensions; } - return deduplicate( + return deduplicate( [...allSupportedExtensions, ...extraFileExtensions.map(e => e.extension)], equateStringsCaseSensitive, compareStringsCaseSensitive ); } - 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) { @@ -2830,7 +2865,7 @@ namespace ts { this.flags = NodeFlags.None; this.modifierFlagsCache = ModifierFlags.None; this.transformFlags = TransformFlags.None; - this.parent = undefined; + this.parent = undefined!; this.original = undefined; } @@ -2917,7 +2952,7 @@ namespace ts { export function assertDefined(value: T | null | undefined, message?: string): T { assert(value !== undefined && value !== null, message); - return value; + return value!; } export function assertEachDefined>(value: A, message: string): A { @@ -3097,10 +3132,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/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index a9b3568bfe67c..d01cecfe934db 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -18,7 +18,7 @@ namespace ts { referencesOutput: string; } - type GetSymbolAccessibilityDiagnostic = (symbolAccessibilityResult: SymbolAccessibilityResult) => SymbolAccessibilityDiagnostic; + type GetSymbolAccessibilityDiagnostic = (symbolAccessibilityResult: SymbolAccessibilityResult) => SymbolAccessibilityDiagnostic | undefined; interface EmitTextWriterWithSymbolWriter extends EmitTextWriter { getSymbolAccessibilityDiagnostic: GetSymbolAccessibilityDiagnostic; @@ -30,13 +30,13 @@ namespace ts { typeName?: DeclarationName | QualifiedName; } - export function getDeclarationDiagnostics(host: EmitHost, resolver: EmitResolver, targetSourceFile: SourceFile): Diagnostic[] { + export function getDeclarationDiagnostics(host: EmitHost, resolver: EmitResolver, targetSourceFile: SourceFile | undefined): Diagnostic[] { const declarationDiagnostics = createDiagnosticCollection(); forEachEmittedFile(host, getDeclarationDiagnosticsFromFile, targetSourceFile); return declarationDiagnostics.getDiagnostics(targetSourceFile ? targetSourceFile.fileName : undefined); function getDeclarationDiagnosticsFromFile({ declarationFilePath }: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle) { - emitDeclarations(host, resolver, declarationDiagnostics, declarationFilePath, sourceFileOrBundle, /*emitOnlyDtsFiles*/ false); + emitDeclarations(host, resolver, declarationDiagnostics, declarationFilePath!, sourceFileOrBundle, /*emitOnlyDtsFiles*/ false); // TODO: GH#18217 } } @@ -53,7 +53,7 @@ namespace ts { let decreaseIndent: () => void; let writeTextOfNode: (text: string, node: Node) => void; - let writer: EmitTextWriterWithSymbolWriter; + let writer!: EmitTextWriterWithSymbolWriter; createAndSetNewTextWriterWithSymbolWriter(); @@ -64,20 +64,20 @@ namespace ts { let currentIdentifiers: Map; let isCurrentFileExternalModule: boolean; let reportedDeclarationError = false; - let errorNameNode: DeclarationName | QualifiedName; + let errorNameNode: DeclarationName | QualifiedName | undefined; const emitJsDocComments = compilerOptions.removeComments ? noop : writeJsDocComments; const emit = compilerOptions.stripInternal ? stripInternal : emitNode; let needsDeclare = true; let moduleElementDeclarationEmitInfo: ModuleElementDeclarationEmitInfo[] = []; - let asynchronousSubModuleDeclarationEmitInfo: ModuleElementDeclarationEmitInfo[]; + let asynchronousSubModuleDeclarationEmitInfo: ModuleElementDeclarationEmitInfo[] | undefined; // Contains the reference paths that needs to go in the declaration file. // Collecting this separately because reference paths need to be first thing in the declaration file // and we could be collecting these paths from multiple files into single one with --out option let referencesOutput = ""; - let usedTypeDirectiveReferences: Map; + let usedTypeDirectiveReferences: Map | undefined; // Emit references corresponding to each file const emittedReferencedFiles: SourceFile[] = []; @@ -212,7 +212,7 @@ namespace ts { decreaseIndent = newWriter.decreaseIndent; } - function writeAsynchronousModuleElements(nodes: ReadonlyArray) { + function writeAsynchronousModuleElements(nodes: ReadonlyArray | undefined) { const oldWriter = writer; forEach(nodes, declaration => { let nodeToCheck: Node; @@ -220,7 +220,7 @@ namespace ts { nodeToCheck = declaration.parent.parent; } else if (declaration.kind === SyntaxKind.NamedImports || declaration.kind === SyntaxKind.ImportSpecifier || declaration.kind === SyntaxKind.ImportClause) { - Debug.fail("We should be getting ImportDeclaration instead to write"); + return Debug.fail("We should be getting ImportDeclaration instead to write"); } else { nodeToCheck = declaration; @@ -266,7 +266,7 @@ namespace ts { setWriter(oldWriter); } - function recordTypeReferenceDirectivesIfNecessary(typeReferenceDirectives: string[]): void { + function recordTypeReferenceDirectivesIfNecessary(typeReferenceDirectives: string[] | undefined): void { if (!typeReferenceDirectives) { return; } @@ -311,7 +311,7 @@ namespace ts { } function trackSymbol(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags) { - handleSymbolAccessibilityError(resolver.isSymbolAccessible(symbol, enclosingDeclaration, meaning, /*shouldComputeAliasesToMakeVisible*/ true)); + handleSymbolAccessibilityError(resolver.isSymbolAccessible(symbol, enclosingDeclaration!, meaning!, /*shouldComputeAliasesToMakeVisible*/ true)); // TODO: GH#18217 recordTypeReferenceDirectivesIfNecessary(resolver.getTypeReferenceDirectivesForSymbol(symbol, meaning)); } @@ -341,7 +341,7 @@ namespace ts { } } - function writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, type: TypeNode, getSymbolAccessibilityDiagnostic: GetSymbolAccessibilityDiagnostic) { + function writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, type: TypeNode | undefined, getSymbolAccessibilityDiagnostic: GetSymbolAccessibilityDiagnostic) { writer.getSymbolAccessibilityDiagnostic = getSymbolAccessibilityDiagnostic; write(": "); @@ -574,7 +574,7 @@ namespace ts { } function emitTypeOperator(type: TypeOperatorNode) { - write(tokenToString(type.operator)); + write(tokenToString(type.operator)!); write(" "); emitType(type.type); } @@ -600,7 +600,7 @@ namespace ts { write("["); writeEntityName(node.typeParameter.name); write(" in "); - emitType(node.typeParameter.constraint); + emitType(node.typeParameter.constraint!); write("]"); if (node.questionToken) { write(node.questionToken.kind === SyntaxKind.PlusToken ? "+?" : @@ -608,7 +608,7 @@ namespace ts { "?"); } write(": "); - emitType(node.type); + emitType(node.type!); write(";"); writeLine(); decreaseIndent(); @@ -715,17 +715,17 @@ namespace ts { // Import equals declaration in internal module can become visible as part of any emit so lets make sure we add these irrespective else if (node.kind === SyntaxKind.ImportEqualsDeclaration || (node.parent.kind === SyntaxKind.SourceFile && isCurrentFileExternalModule)) { - let isVisible: boolean; if (asynchronousSubModuleDeclarationEmitInfo && node.parent.kind !== SyntaxKind.SourceFile) { // Import declaration of another module that is visited async so lets put it in right spot asynchronousSubModuleDeclarationEmitInfo.push({ node, outputPos: writer.getTextPos(), indent: writer.getIndent(), - isVisible + isVisible: false }); } else { + let isVisible = false; if (node.kind === SyntaxKind.ImportDeclaration) { const importDeclaration = node; if (importDeclaration.importClause) { @@ -836,7 +836,7 @@ namespace ts { } } - function isVisibleNamedBinding(namedBindings: NamespaceImport | NamedImports): boolean { + function isVisibleNamedBinding(namedBindings: NamespaceImport | NamedImports | undefined): boolean { if (namedBindings) { if (namedBindings.kind === SyntaxKind.NamespaceImport) { return resolver.isDeclarationVisible(namedBindings); @@ -845,6 +845,7 @@ namespace ts { return namedBindings.elements.some(namedImport => resolver.isDeclarationVisible(namedImport)); } } + return false; } function writeImportDeclaration(node: ImportDeclaration) { @@ -887,7 +888,7 @@ namespace ts { // so compiler will treat them as external modules. resultHasExternalModuleIndicator = resultHasExternalModuleIndicator || parent.kind !== SyntaxKind.ModuleDeclaration; const moduleSpecifier = parent.kind === SyntaxKind.ImportEqualsDeclaration ? getExternalModuleImportEqualsDeclarationExpression(parent) : - parent.kind === SyntaxKind.ModuleDeclaration ? parent.name : parent.moduleSpecifier; + parent.kind === SyntaxKind.ModuleDeclaration ? parent.name : parent.moduleSpecifier!; if (moduleSpecifier.kind === SyntaxKind.StringLiteral && isBundledEmit && (compilerOptions.out || compilerOptions.outFile)) { const moduleName = getExternalModuleNameFromDeclaration(host, resolver, parent); @@ -971,7 +972,7 @@ namespace ts { write(" {"); writeLine(); increaseIndent(); - emitLines((node.body).statements); + emitLines((node.body as ts.ModuleBlock).statements); // tslint:disable-line no-unnecessary-type-assertion (TODO: GH#18217) decreaseIndent(); write("}"); writeLine(); @@ -1038,8 +1039,9 @@ namespace ts { return node.parent.kind === SyntaxKind.MethodDeclaration && hasModifier(node.parent, ModifierFlags.Private); } - function emitTypeParameters(typeParameters: ReadonlyArray) { + function emitTypeParameters(typeParameters: ReadonlyArray | undefined) { function emitTypeParameter(node: TypeParameterDeclaration) { + const { parent } = node; increaseIndent(); emitJsDocComments(node); decreaseIndent(); @@ -1047,15 +1049,15 @@ namespace ts { // If there is constraint present and this is not a type parameter of the private method emit the constraint if (node.constraint && !isPrivateMethodTypeParameter(node)) { write(" extends "); - if (node.parent.kind === SyntaxKind.FunctionType || - node.parent.kind === SyntaxKind.ConstructorType || - (node.parent.parent && node.parent.parent.kind === SyntaxKind.TypeLiteral)) { - Debug.assert(node.parent.kind === SyntaxKind.MethodDeclaration || - node.parent.kind === SyntaxKind.MethodSignature || - node.parent.kind === SyntaxKind.FunctionType || - node.parent.kind === SyntaxKind.ConstructorType || - node.parent.kind === SyntaxKind.CallSignature || - node.parent.kind === SyntaxKind.ConstructSignature); + if (parent.kind === SyntaxKind.FunctionType || + parent.kind === SyntaxKind.ConstructorType || + (parent.parent && parent.parent.kind === SyntaxKind.TypeLiteral)) { + Debug.assert(parent.kind === SyntaxKind.MethodDeclaration || + parent.kind === SyntaxKind.MethodSignature || + parent.kind === SyntaxKind.FunctionType || + parent.kind === SyntaxKind.ConstructorType || + parent.kind === SyntaxKind.CallSignature || + parent.kind === SyntaxKind.ConstructSignature); emitType(node.constraint); } else { @@ -1064,15 +1066,15 @@ namespace ts { } if (node.default && !isPrivateMethodTypeParameter(node)) { write(" = "); - if (node.parent.kind === SyntaxKind.FunctionType || - node.parent.kind === SyntaxKind.ConstructorType || - (node.parent.parent && node.parent.parent.kind === SyntaxKind.TypeLiteral)) { - Debug.assert(node.parent.kind === SyntaxKind.MethodDeclaration || - node.parent.kind === SyntaxKind.MethodSignature || - node.parent.kind === SyntaxKind.FunctionType || - node.parent.kind === SyntaxKind.ConstructorType || - node.parent.kind === SyntaxKind.CallSignature || - node.parent.kind === SyntaxKind.ConstructSignature); + if (parent.kind === SyntaxKind.FunctionType || + parent.kind === SyntaxKind.ConstructorType || + (parent.parent && parent.parent.kind === SyntaxKind.TypeLiteral)) { + Debug.assert(parent.kind === SyntaxKind.MethodDeclaration || + parent.kind === SyntaxKind.MethodSignature || + parent.kind === SyntaxKind.FunctionType || + parent.kind === SyntaxKind.ConstructorType || + parent.kind === SyntaxKind.CallSignature || + parent.kind === SyntaxKind.ConstructSignature); emitType(node.default); } else { @@ -1083,7 +1085,7 @@ namespace ts { function getTypeParameterConstraintVisibilityError(): SymbolAccessibilityDiagnostic { // Type parameter constraints are named by user so we should always be able to name it let diagnosticMessage: DiagnosticMessage; - switch (node.parent.kind) { + switch (parent.kind) { case SyntaxKind.ClassDeclaration: diagnosticMessage = Diagnostics.Type_parameter_0_of_exported_class_has_or_is_using_private_name_1; break; @@ -1102,10 +1104,10 @@ namespace ts { case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: - if (hasModifier(node.parent, ModifierFlags.Static)) { + if (hasModifier(parent, ModifierFlags.Static)) { diagnosticMessage = Diagnostics.Type_parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1; } - else if (node.parent.parent.kind === SyntaxKind.ClassDeclaration) { + else if (parent.parent.kind === SyntaxKind.ClassDeclaration) { diagnosticMessage = Diagnostics.Type_parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1; } else { @@ -1122,7 +1124,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: " + parent.kind); } return { @@ -1140,7 +1142,7 @@ namespace ts { } } - function emitHeritageClause(typeReferences: ReadonlyArray, isImplementsList: boolean) { + function emitHeritageClause(typeReferences: ReadonlyArray | undefined, isImplementsList: boolean) { if (typeReferences) { write(isImplementsList ? " implements " : " extends "); emitCommaList(typeReferences, emitTypeOfTypeReference); @@ -1178,7 +1180,7 @@ namespace ts { } function writeClassDeclaration(node: ClassDeclaration) { - function emitParameterProperties(constructorDeclaration: ConstructorDeclaration) { + function emitParameterProperties(constructorDeclaration: ConstructorDeclaration | undefined) { if (constructorDeclaration) { forEach(constructorDeclaration.parameters, param => { if (hasModifier(param, ModifierFlags.ParameterPropertyModifier)) { @@ -1191,11 +1193,11 @@ namespace ts { const prevEnclosingDeclaration = enclosingDeclaration; enclosingDeclaration = node; const baseTypeNode = getClassExtendsHeritageClauseElement(node); - let tempVarName: string; + let tempVarName: string | undefined; if (baseTypeNode && !isEntityNameExpression(baseTypeNode.expression)) { tempVarName = baseTypeNode.expression.kind === SyntaxKind.NullKeyword ? "null" : - emitTempVariableDeclaration(baseTypeNode.expression, `${node.name.escapedText}_base`, { + emitTempVariableDeclaration(baseTypeNode.expression, `${node.name!.escapedText}_base`, { diagnosticMessage: Diagnostics.extends_clause_of_exported_class_0_has_or_is_using_private_name_1, errorNode: baseTypeNode, typeName: node.name @@ -1208,12 +1210,12 @@ namespace ts { write("abstract "); } write("class "); - writeTextOfNode(currentText, node.name); + writeTextOfNode(currentText, node.name!); emitTypeParameters(node.typeParameters); if (baseTypeNode) { if (!isEntityNameExpression(baseTypeNode.expression)) { write(" extends "); - write(tempVarName); + write(tempVarName!); if (baseTypeNode.typeArguments) { write("<"); emitCommaList(baseTypeNode.typeArguments, emitType); @@ -1343,7 +1345,7 @@ namespace ts { } } - function getVariableDeclarationTypeVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic { + function getVariableDeclarationTypeVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic | undefined { const diagnosticMessage = getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult); return diagnosticMessage !== undefined ? { diagnosticMessage, @@ -1368,7 +1370,7 @@ namespace ts { } function emitBindingElement(bindingElement: BindingElement) { - function getBindingElementTypeVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic { + function getBindingElementTypeVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic | undefined { const diagnosticMessage = getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult); return diagnosticMessage !== undefined ? { diagnosticMessage, @@ -1395,12 +1397,12 @@ namespace ts { // emit only if type is specified if (hasType(node)) { write(": "); - emitType(node.type); + emitType(node.type!); } } - function isVariableStatementVisible(node: VariableStatement) { - return forEach(node.declarationList.declarations, varDeclaration => isVariableDeclarationVisible(varDeclaration)); + function isVariableStatementVisible(node: VariableStatement): boolean { + return some(node.declarationList.declarations, varDeclaration => isVariableDeclarationVisible(varDeclaration)); } function writeVariableStatement(node: VariableStatement) { @@ -1430,7 +1432,7 @@ namespace ts { } const accessors = getAllAccessorDeclarations((node.parent).members, node); - let accessorWithTypeAnnotation: AccessorDeclaration; + let accessorWithTypeAnnotation: AccessorDeclaration | undefined; if (node === accessors.firstAccessor) { emitJsDocComments(accessors.getAccessor); @@ -1454,7 +1456,7 @@ namespace ts { writeLine(); } - function getTypeAnnotationFromAccessor(accessor: AccessorDeclaration): TypeNode { + function getTypeAnnotationFromAccessor(accessor: AccessorDeclaration | undefined): TypeNode | undefined { if (accessor) { return accessor.kind === SyntaxKind.GetAccessor ? accessor.type // Getter - return type @@ -1497,10 +1499,10 @@ namespace ts { function getAccessorDeclarationTypeVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic { let diagnosticMessage: DiagnosticMessage; - if (accessorWithTypeAnnotation.kind === SyntaxKind.SetAccessor) { + if (accessorWithTypeAnnotation!.kind === SyntaxKind.SetAccessor) { // Getters can infer the return type from the returned expression, but setters cannot, so the // "_from_external_module_1_but_cannot_be_named" case cannot occur. - if (hasModifier(accessorWithTypeAnnotation, ModifierFlags.Static)) { + if (hasModifier(accessorWithTypeAnnotation!, ModifierFlags.Static)) { diagnosticMessage = symbolAccessibilityResult.errorModuleName ? Diagnostics.Parameter_type_of_public_static_setter_0_from_exported_class_has_or_is_using_name_1_from_private_module_2 : Diagnostics.Parameter_type_of_public_static_setter_0_from_exported_class_has_or_is_using_private_name_1; @@ -1512,7 +1514,7 @@ namespace ts { } } else { - if (hasModifier(accessorWithTypeAnnotation, ModifierFlags.Static)) { + if (hasModifier(accessorWithTypeAnnotation!, ModifierFlags.Static)) { diagnosticMessage = symbolAccessibilityResult.errorModuleName ? symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? Diagnostics.Return_type_of_public_static_getter_0_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : @@ -1529,8 +1531,8 @@ namespace ts { } return { diagnosticMessage, - errorNode: accessorWithTypeAnnotation.name, - typeName: accessorWithTypeAnnotation.name + errorNode: accessorWithTypeAnnotation!.name, + typeName: accessorWithTypeAnnotation!.name }; } } @@ -1552,7 +1554,7 @@ namespace ts { } if (node.kind === SyntaxKind.FunctionDeclaration) { write("function "); - writeTextOfNode(currentText, node.name); + writeTextOfNode(currentText, node.name!); } else if (node.kind === SyntaxKind.Constructor) { write("constructor"); @@ -1566,7 +1568,7 @@ namespace ts { emitSignatureDeclaration(node); } - function getMethodNameVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic { + function getMethodNameVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic | undefined { const diagnosticMessage = getMethodNameVisibilityDiagnosticMessage(symbolAccessibilityResult); return diagnosticMessage !== undefined ? { diagnosticMessage, @@ -1610,7 +1612,7 @@ namespace ts { // If this node is a computed name, it can only be a symbol, because we've already skipped // it if it's not a well known symbol. In that case, the text of the name will be exactly // what we want, namely the name expression enclosed in brackets. - writeTextOfNode(currentText, node.name); + writeTextOfNode(currentText, node.name!); } } @@ -1752,7 +1754,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 { @@ -1791,7 +1793,7 @@ namespace ts { writeTypeOfDeclaration(node, node.type, getParameterDeclarationTypeVisibilityError); } - function getParameterDeclarationTypeVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic { + function getParameterDeclarationTypeVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic | undefined { const diagnosticMessage: DiagnosticMessage = getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult); return diagnosticMessage !== undefined ? { diagnosticMessage, @@ -1858,7 +1860,7 @@ namespace ts { Diagnostics.Parameter_0_of_exported_function_has_or_is_using_private_name_1; default: - Debug.fail("This is unknown parent for parameter: " + node.parent.kind); + return Debug.fail("This is unknown parent for parameter: " + node.parent.kind); } } @@ -1975,7 +1977,7 @@ namespace ts { * @param addBundledFileReference Determines if global file reference corresponding to bundled file should be emitted or not */ function writeReferencePath(referencedFile: SourceFile, addBundledFileReference: boolean, emitOnlyDtsFiles: boolean): boolean { - let declFileName: string; + let declFileName: string | undefined; let addedBundledEmitReference = false; if (referencedFile.isDeclarationFile) { // Declaration file, use declaration file name @@ -2020,11 +2022,11 @@ namespace ts { const sourceFiles = sourceFileOrBundle.kind === SyntaxKind.Bundle ? sourceFileOrBundle.sourceFiles : [sourceFileOrBundle]; const declarationOutput = emitDeclarationResult.referencesOutput + getDeclarationOutput(emitDeclarationResult.synchronousDeclarationOutput, emitDeclarationResult.moduleElementDeclarationEmitInfo); - writeFile(host, emitterDiagnostics, declarationFilePath, declarationOutput, host.getCompilerOptions().emitBOM, sourceFiles); + writeFile(host, emitterDiagnostics, declarationFilePath, declarationOutput, !!host.getCompilerOptions().emitBOM, sourceFiles); } return emitSkipped; - function getDeclarationOutput(synchronousDeclarationOutput: string, moduleElementDeclarationEmitInfo: ModuleElementDeclarationEmitInfo[]) { + function getDeclarationOutput(synchronousDeclarationOutput: string, moduleElementDeclarationEmitInfo: ModuleElementDeclarationEmitInfo[] | undefined) { let appliedSyncOutputPos = 0; let declarationOutput = ""; // apply asynchronous additions to the synchronous output diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index df1394efd006e..f8f280fdfe42e 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -20,13 +20,13 @@ namespace ts { export function forEachEmittedFile( host: EmitHost, action: (emitFileNames: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle, emitOnlyDtsFiles: boolean) => T, sourceFilesOrTargetSourceFile?: SourceFile[] | SourceFile, - emitOnlyDtsFiles?: boolean) { + emitOnlyDtsFiles = false) { const sourceFiles = isArray(sourceFilesOrTargetSourceFile) ? sourceFilesOrTargetSourceFile : getSourceFilesToEmit(host, sourceFilesOrTargetSourceFile); const options = host.getCompilerOptions(); if (options.outFile || options.out) { if (sourceFiles.length) { - const jsFilePath = options.outFile || options.out; + const jsFilePath = (options.outFile || options.out)!; const sourceMapFilePath = getSourceMapFilePath(jsFilePath, options); const declarationFilePath = options.declaration ? removeFileExtension(jsFilePath) + Extension.Dts : ""; const result = action({ jsFilePath, sourceMapFilePath, declarationFilePath }, createBundle(sourceFiles), emitOnlyDtsFiles); @@ -79,11 +79,11 @@ namespace ts { /*@internal*/ // 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[]): EmitResult { + export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile | undefined, emitOnlyDtsFiles = false, transformers?: TransformerFactory[]): EmitResult { const compilerOptions = host.getCompilerOptions(); const moduleKind = getEmitModuleKind(compilerOptions); - const sourceMapDataList: SourceMapData[] = compilerOptions.sourceMap || compilerOptions.inlineSourceMap ? [] : undefined; - const emittedFilesList: string[] = compilerOptions.listEmittedFiles ? [] : undefined; + const sourceMapDataList: SourceMapData[] | undefined = compilerOptions.sourceMap || compilerOptions.inlineSourceMap ? [] : undefined; + const emittedFilesList: string[] | undefined = compilerOptions.listEmittedFiles ? [] : undefined; const emitterDiagnostics = createDiagnosticCollection(); const newLine = host.getNewLine(); const writer = createTextWriter(newLine); @@ -97,7 +97,7 @@ namespace ts { const sourceFiles = getSourceFilesToEmit(host, targetSourceFile); // Transform the source files - const transform = transformNodes(resolver, host, compilerOptions, sourceFiles, transformers, /*allowDtsFiles*/ false); + const transform = transformNodes(resolver, host, compilerOptions, sourceFiles, transformers!, /*allowDtsFiles*/ false); // TODO: GH#18217 // Create a printer to print the nodes const printer = createPrinter(compilerOptions, { @@ -129,8 +129,8 @@ namespace ts { return { emitSkipped, diagnostics: emitterDiagnostics.getDiagnostics(), - emittedFiles: emittedFilesList, - sourceMaps: sourceMapDataList + emittedFiles: emittedFilesList!, // TODO: GH#18217 + sourceMaps: sourceMapDataList!, // TODO: GH#18217 }; function emitSourceFileOrBundle({ jsFilePath, sourceMapFilePath, declarationFilePath }: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle) { @@ -161,10 +161,10 @@ namespace ts { } } - function printSourceFileOrBundle(jsFilePath: string, sourceMapFilePath: string, sourceFileOrBundle: SourceFile | Bundle) { + function printSourceFileOrBundle(jsFilePath: string, sourceMapFilePath: string | undefined, sourceFileOrBundle: SourceFile | Bundle) { 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!]; sourceMap.initialize(jsFilePath, sourceMapFilePath, sourceFileOrBundle); if (bundle) { @@ -174,7 +174,7 @@ namespace ts { } else { isOwnFileEmit = true; - printer.writeFile(sourceFile, writer); + printer.writeFile(sourceFile!, writer); } writer.writeLine(); @@ -186,7 +186,7 @@ namespace ts { // Write the source map if (compilerOptions.sourceMap && !compilerOptions.inlineSourceMap) { - writeFile(host, emitterDiagnostics, sourceMapFilePath, sourceMap.getText(), /*writeByteOrderMark*/ false, sourceFiles); + writeFile(host, emitterDiagnostics, sourceMapFilePath!, sourceMap.getText(), /*writeByteOrderMark*/ false, sourceFiles); // TODO: GH#18217 } // Record source map data for the test harness. @@ -195,14 +195,14 @@ namespace ts { } // Write the output file - writeFile(host, emitterDiagnostics, jsFilePath, writer.getText(), compilerOptions.emitBOM, sourceFiles); + writeFile(host, emitterDiagnostics, jsFilePath, writer.getText(), !!compilerOptions.emitBOM, sourceFiles); // Reset state sourceMap.reset(); writer.clear(); - currentSourceFile = undefined; - bundledHelpers = undefined; + currentSourceFile = undefined!; + bundledHelpers = undefined!; isOwnFileEmit = false; } @@ -283,7 +283,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. @@ -427,8 +427,8 @@ namespace ts { } function setWriter(output: EmitTextWriter | undefined) { - writer = output; - comments.setWriter(output); + writer = output!; // TODO: GH#18217 + comments.setWriter(output!); } function reset() { @@ -515,7 +515,7 @@ namespace ts { writeSpace(); writeKeyword("in"); writeSpace(); - emit(node.constraint); + emit(node.constraint!); } function pipelineEmitUnspecified(node: Node): void { @@ -935,8 +935,8 @@ namespace ts { function emitIdentifier(node: Identifier) { const writeText = node.symbol ? writeSymbol : write; - writeText(getTextOfNode(node, /*includeTrivia*/ false), node.symbol); - emitList(node, node.typeArguments, ListFormat.TypeParameters); // Call emitList directly since it could be an array of TypeParameterDeclarations _or_ type arguments + writeText(getTextOfNode(node, /*includeTrivia*/ false), node.symbol!); + emitList(node, node.typeArguments!, ListFormat.TypeParameters); // Call emitList directly since it could be an array of TypeParameterDeclarations _or_ type arguments } // @@ -993,7 +993,7 @@ namespace ts { } emitIfPresent(node.questionToken); if (node.parent && node.parent.kind === SyntaxKind.JSDocFunctionType && !node.name) { - emit(node.type); + emit(node.type!); } else { emitTypeAnnotation(node.type); @@ -1119,14 +1119,14 @@ namespace ts { writeSpace(); writePunctuation("=>"); writeSpace(); - emit(node.type); + emit(node.type!); // TODO: GH#18217 This should always be defined on FunctionTypeNode, so change that type } function emitJSDocFunctionType(node: JSDocFunctionType) { write("function"); emitParameters(node, node.parameters); write(":"); - emit(node.type); + emit(node.type!); } @@ -1153,7 +1153,7 @@ namespace ts { writeSpace(); writePunctuation("=>"); writeSpace(); - emit(node.type); + emit(node.type!); // TODO: GH#18217 This should always be defined on ConstructorTypeNode, so change that type } function emitTypeQuery(node: TypeQueryNode) { @@ -1267,7 +1267,7 @@ namespace ts { } writePunctuation(":"); writeSpace(); - emit(node.type); + emit(node.type!); // TODO: GH#18217 writeSemicolon(); if (emitFlags & EmitFlags.SingleLine) { writeSpace(); @@ -1367,7 +1367,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 @@ -1382,7 +1382,7 @@ namespace ts { function emitElementAccessExpression(node: ElementAccessExpression) { emitExpression(node.expression); writePunctuation("["); - emitExpression(node.argumentExpression); + emitExpression(node.argumentExpression!); // TODO: GH#18217 writePunctuation("]"); } @@ -1397,7 +1397,7 @@ namespace ts { writeSpace(); emitExpression(node.expression); emitTypeArguments(node, node.typeArguments); - emitExpressionList(node, node.arguments, ListFormat.NewExpressionArguments); + emitExpressionList(node, node.arguments!, ListFormat.NewExpressionArguments); } function emitTaggedTemplateExpression(node: TaggedTemplateExpression) { @@ -1535,7 +1535,7 @@ namespace ts { function emitYieldExpression(node: YieldExpression) { writeKeyword("yield"); - emit(node.asteriskToken); + emit(node.asteriskToken!); // TODO: GH#18217 emitExpressionWithLeadingSpace(node.expression); } @@ -1667,7 +1667,7 @@ namespace ts { const openParenPos = writeToken(SyntaxKind.ForKeyword, node.pos, writeKeyword); writeSpace(); writeToken(SyntaxKind.OpenParenToken, openParenPos, writePunctuation, /*contextNode*/ node); - emitForBinding(node.initializer); + emitForBinding(node.initializer!); // TODO: GH#18217 writeSemicolon(); emitExpressionWithLeadingSpace(node.condition); writeSemicolon(); @@ -1728,11 +1728,11 @@ namespace ts { function emitTokenWithComment(token: SyntaxKind, pos: number, writer: (s: string) => void, contextNode?: Node) { const node = contextNode && getParseTreeNode(contextNode); - if (node && node.kind === contextNode.kind) { + if (node && node.kind === contextNode!.kind) { pos = skipTrivia(currentSourceFile.text, pos); } pos = writeToken(token, pos, writer, /*contextNode*/ contextNode); - if (node && node.kind === contextNode.kind) { + if (node && node.kind === contextNode!.kind) { // TODO: GH#18217 emitTrailingCommentsOfPosition(pos, /*prefixSpace*/ true); } return pos; @@ -1823,7 +1823,7 @@ namespace ts { writeKeyword("function"); emitIfPresent(node.asteriskToken); writeSpace(); - emitIdentifierName(node.name); + emitIdentifierName(node.name!); // TODO: GH#18217 emitSignatureAndBody(node, emitSignatureHead); } @@ -1899,7 +1899,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; @@ -2029,11 +2029,11 @@ namespace ts { } emit(node.name); - let body = node.body; + let body = node.body!; while (body.kind === SyntaxKind.ModuleDeclaration) { writePunctuation("."); emit((body).name); - body = (body).body; + body = (body).body!; } writeSpace(); @@ -2090,12 +2090,12 @@ namespace ts { } function emitImportClause(node: ImportClause) { - emit(node.name); + emit(node.name!); if (node.name && node.namedBindings) { writePunctuation(","); writeSpace(); } - emit(node.namedBindings); + emit(node.namedBindings!); } function emitNamespaceImport(node: NamespaceImport) { @@ -2189,7 +2189,7 @@ namespace ts { function emitExternalModuleReference(node: ExternalModuleReference) { writeKeyword("require"); writePunctuation("("); - emitExpression(node.expression); + emitExpression(node.expression!); // TODO: GH#18217 writePunctuation(")"); } @@ -2254,7 +2254,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) { @@ -2368,7 +2368,7 @@ namespace ts { // } // "comment1" is not considered to be leading comment for node.initializer // but rather a trailing comment on the previous node. - const initializer = node.initializer; + const initializer = node.initializer!; if (emitTrailingCommentsOfPosition && (getEmitFlags(initializer) & EmitFlags.NoLeadingComments) === 0) { const commentRange = getCommentRange(initializer); emitTrailingCommentsOfPosition(commentRange.pos); @@ -2514,7 +2514,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(); @@ -2579,15 +2579,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); } @@ -2628,7 +2628,7 @@ 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); } @@ -2654,13 +2654,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); @@ -2692,7 +2692,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; } @@ -2706,10 +2706,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) { @@ -2763,7 +2763,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(","); } @@ -2785,7 +2785,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) { @@ -2892,16 +2892,16 @@ 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, 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) { @@ -2927,7 +2927,7 @@ namespace ts { } 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 (!isWhiteSpaceLike(line.charCodeAt(i))) { @@ -2990,7 +2990,7 @@ namespace ts { } } - function shouldWriteSeparatingLineTerminator(previousNode: Node, nextNode: Node, format: ListFormat) { + function shouldWriteSeparatingLineTerminator(previousNode: Node | undefined, nextNode: Node | undefined, format: ListFormat) { if (format & ListFormat.MultiLine) { return true; } @@ -3006,7 +3006,7 @@ namespace ts { } } else { - return getStartsOnNewLine(nextNode); + return getStartsOnNewLine(nextNode!); // TODO: GH#18217 } } @@ -3039,13 +3039,13 @@ namespace ts { if (nodeIsSynthesized(node)) { const startsOnNewLine = getStartsOnNewLine(node); if (startsOnNewLine === undefined) { - return (format & ListFormat.PreferNewLine) !== 0; + return (format! & ListFormat.PreferNewLine) !== 0; } return startsOnNewLine; } - return (format & ListFormat.PreferNewLine) !== 0; + return (format! & ListFormat.PreferNewLine) !== 0; } function needsIndentation(parent: Node, node1: Node, node2: Node): boolean { @@ -3085,7 +3085,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; @@ -3096,7 +3096,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))}"` : @@ -3129,8 +3129,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) { @@ -3162,7 +3162,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)); } } @@ -3187,7 +3187,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 @@ -3268,7 +3268,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); @@ -3336,7 +3336,7 @@ namespace ts { return makeUniqueName(idText(name)); } - Debug.fail("Unsupported GeneratedIdentifierKind."); + return Debug.fail("Unsupported GeneratedIdentifierKind."); } /** diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 92d353aeb0efa..044255c4f4764 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -44,13 +44,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); @@ -112,7 +112,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); @@ -667,7 +667,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; @@ -782,7 +782,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; } @@ -906,10 +906,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; } @@ -923,7 +923,7 @@ namespace ts { : node; } - export function createElementAccess(expression: Expression, index: number | Expression) { + export function createElementAccess(expression: Expression, index: number | Expression | undefined) { const node = createSynthesizedNode(SyntaxKind.ElementAccessExpression); node.expression = parenthesizeForAccess(expression); node.argumentExpression = asExpression(index); @@ -937,7 +937,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); @@ -1014,7 +1014,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); @@ -1209,7 +1209,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; } @@ -1281,8 +1281,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; @@ -1312,7 +1312,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; @@ -1329,7 +1329,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 @@ -1344,14 +1344,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) @@ -1541,7 +1541,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; @@ -1550,7 +1550,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 @@ -1687,7 +1687,7 @@ namespace ts { export function createVariableDeclarationList(declarations: ReadonlyArray, flags?: NodeFlags) { const node = createSynthesizedNode(SyntaxKind.VariableDeclarationList); - node.flags |= flags & NodeFlags.BlockScoped; + node.flags |= flags! & NodeFlags.BlockScoped; node.declarations = createNodeArray(declarations); return node; } @@ -1746,7 +1746,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); @@ -1764,7 +1764,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 @@ -1871,7 +1871,7 @@ namespace ts { export function createModuleDeclaration(decorators: ReadonlyArray | undefined, modifiers: ReadonlyArray | undefined, name: ModuleName, body: ModuleBody | undefined, flags?: NodeFlags) { const node = createSynthesizedNode(SyntaxKind.ModuleDeclaration); - node.flags |= flags & (NodeFlags.Namespace | NodeFlags.NestedNamespace | NodeFlags.GlobalAugmentation); + node.flags |= flags! & (NodeFlags.Namespace | NodeFlags.NestedNamespace | NodeFlags.GlobalAugmentation); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.name = name; @@ -1951,7 +1951,7 @@ namespace ts { node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.importClause = importClause; - node.moduleSpecifier = moduleSpecifier; + node.moduleSpecifier = moduleSpecifier!; // TODO: GH#18217 return node; } @@ -1960,7 +1960,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 @@ -2021,7 +2021,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); @@ -2314,7 +2314,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; } @@ -2589,19 +2589,16 @@ 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; } - function asExpression(value: string | number | Expression) { + function asExpression(value: string | number | Expression | undefined) { 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; } @@ -2647,7 +2644,7 @@ namespace ts { } const sourceFile = getSourceFileOfNode(node); - getOrCreateEmitNode(sourceFile).annotatedNodes.push(node); + getOrCreateEmitNode(sourceFile).annotatedNodes!.push(node); } node.emitNode = {}; @@ -2678,7 +2675,7 @@ namespace ts { /* @internal */ export function addEmitFlags(node: T, emitFlags: EmitFlags) { const emitNode = getOrCreateEmitNode(node); - emitNode.flags = emitNode.flags | emitFlags; + emitNode.flags = emitNode.flags! | emitFlags; return node; } @@ -2766,7 +2763,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; } @@ -2780,7 +2777,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; } @@ -2821,7 +2818,7 @@ namespace ts { export function addEmitHelpers(node: T, helpers: EmitHelper[] | undefined): T { if (some(helpers)) { const emitNode = getOrCreateEmitNode(node); - for (const helper of helpers) { + for (const helper of helpers!) { emitNode.helpers = appendIfUnique(emitNode.helpers, helper); } } @@ -2860,19 +2857,19 @@ namespace ts { const targetEmitNode = getOrCreateEmitNode(target); let helpersRemoved = 0; - for (let i = 0; i < sourceEmitHelpers.length; i++) { - const helper = sourceEmitHelpers[i]; + for (let i = 0; i < sourceEmitHelpers!.length; i++) { + const helper = sourceEmitHelpers![i]; if (predicate(helper)) { helpersRemoved++; targetEmitNode.helpers = appendIfUnique(targetEmitNode.helpers, helper); } else if (helpersRemoved > 0) { - sourceEmitHelpers[i - helpersRemoved] = helper; + sourceEmitHelpers![i - helpersRemoved] = helper; } } if (helpersRemoved > 0) { - sourceEmitHelpers.length -= helpersRemoved; + sourceEmitHelpers!.length -= helpersRemoved; } } @@ -2894,7 +2891,7 @@ namespace ts { return node; } - function mergeEmitNode(sourceEmitNode: EmitNode, destEmitNode: EmitNode) { + function mergeEmitNode(sourceEmitNode: EmitNode, destEmitNode: EmitNode | undefined) { const { flags, leadingComments, @@ -2913,14 +2910,14 @@ namespace ts { 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]; @@ -2972,7 +2969,7 @@ namespace ts { : createElementAccess(target, memberName), memberName ); - getOrCreateEmitNode(expression).flags |= EmitFlags.NoNestedSourceMaps; + getOrCreateEmitNode(expression).flags! |= EmitFlags.NoNestedSourceMaps; return expression; } } @@ -3056,7 +3053,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( @@ -3065,7 +3062,7 @@ namespace ts { ); } - export function createExpressionForJsxElement(jsxFactoryEntity: EntityName, reactNamespace: string, tagName: Expression, props: Expression, children: Expression[], parentElement: JsxOpeningLikeElement, location: TextRange): LeftHandSideExpression { + export function createExpressionForJsxElement(jsxFactoryEntity: EntityName | undefined, reactNamespace: string, tagName: Expression, props: Expression, children: Expression[], parentElement: JsxOpeningLikeElement, location: TextRange): LeftHandSideExpression { const argumentsList = [tagName]; if (props) { argumentsList.push(props); @@ -3097,7 +3094,7 @@ namespace ts { ); } - export function createExpressionForJsxFragment(jsxFactoryEntity: EntityName, reactNamespace: string, children: Expression[], parentElement: JsxOpeningFragment, location: TextRange): LeftHandSideExpression { + export function createExpressionForJsxFragment(jsxFactoryEntity: EntityName | undefined, reactNamespace: string, children: Expression[], parentElement: JsxOpeningFragment, location: TextRange): LeftHandSideExpression { const tagName = createPropertyAccess( createReactNamespace(reactNamespace, parentElement), "Fragment" @@ -3227,7 +3224,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, @@ -3257,7 +3254,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; } @@ -3301,7 +3298,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; @@ -3311,7 +3308,7 @@ namespace ts { } else if (callee.kind === SyntaxKind.SuperKeyword) { thisArg = createThis(); - target = languageVersion < ScriptTarget.ES2015 + target = languageVersion! < ScriptTarget.ES2015 ? setTextRange(createIdentifier("_super"), callee) : callee; } @@ -3380,12 +3377,12 @@ namespace ts { return { target, thisArg }; } - export function inlineExpressions(expressions: Expression[]) { + export function inlineExpressions(expressions: Expression[]): Expression { // Avoid deeply nested comma expressions as traversing them during emit can result in "Maximum call // stack size exceeded" errors. return expressions.length > 10 ? createCommaList(expressions) - : reduceLeft(expressions, createComma); + : reduceLeft(expressions, createComma)!; } export function createExpressionFromEntityName(node: EntityName | Expression): Expression { @@ -3411,11 +3408,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: @@ -3437,7 +3434,7 @@ namespace ts { /*typeParameters*/ undefined, getAccessor.parameters, /*type*/ undefined, - getAccessor.body + getAccessor.body! // TODO: GH#18217 ); setTextRange(getterFunction, getAccessor); setOriginalNode(getterFunction, getAccessor); @@ -3453,7 +3450,7 @@ namespace ts { /*typeParameters*/ undefined, setAccessor.parameters, /*type*/ undefined, - setAccessor.body + setAccessor.body! // TODO: GH#18217 ); setTextRange(setterFunction, setAccessor); setOriginalNode(setterFunction, setAccessor); @@ -3489,7 +3486,7 @@ namespace ts { setTextRange( createAssignment( createMemberAccessForPropertyName(receiver, property.name, /*location*/ property.name), - property.initializer + property.initializer! // TODO: GH#18217 ), property ), @@ -3528,7 +3525,7 @@ namespace ts { /*typeParameters*/ undefined, method.parameters, /*type*/ undefined, - method.body + method.body! // TODO: GH#18217 ), /*location*/ method ), @@ -3622,9 +3619,9 @@ namespace ts { const nodeName = getNameOfDeclaration(node); if (nodeName && isIdentifier(nodeName) && !isGeneratedIdentifier(nodeName)) { const name = getMutableClone(nodeName); - emitFlags |= getEmitFlags(nodeName); - if (!allowSourceMaps) emitFlags |= EmitFlags.NoSourceMap; - if (!allowComments) emitFlags |= EmitFlags.NoComments; + emitFlags! |= getEmitFlags(nodeName); + if (!allowSourceMaps) emitFlags! |= EmitFlags.NoSourceMap; + if (!allowComments) emitFlags! |= EmitFlags.NoComments; if (emitFlags) setEmitFlags(name, emitFlags); return name; } @@ -3660,7 +3657,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); @@ -3680,7 +3677,7 @@ namespace ts { node.typeParameters, node.parameters, node.type, - node.body + node.body! // TODO: GH#18217 ); setOriginalNode(updated, node); setTextRange(updated, node); @@ -3747,9 +3744,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); @@ -3831,7 +3830,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 @@ -4076,7 +4075,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]) { @@ -4364,7 +4363,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; @@ -4388,7 +4387,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) @@ -4414,7 +4413,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; } @@ -4450,8 +4449,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!; // TODO: GH#18217 + return isAssignmentExpression(initializer, /*excludeCompoundAssignment*/ true) + ? initializer.right : undefined; } @@ -4476,7 +4476,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 } = ...` @@ -4551,7 +4551,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 50181bb98e4f7..6fbbb5ea34c52 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -5,12 +5,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. */ @@ -19,11 +19,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); } @@ -53,7 +53,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 { @@ -137,7 +137,7 @@ namespace ts { return options.typeRoots; } - let currentDirectory: string; + let currentDirectory: string | undefined; if (options.configFilePath) { currentDirectory = getDirectoryPath(options.configFilePath); } @@ -160,10 +160,10 @@ namespace ts { // And if it doesn't exist, tough. } - let typeRoots: string[]; + let typeRoots: string[] | undefined; forEachAncestorDirectory(ts.normalizePath(currentDirectory), directory => { const atTypes = combinePaths(directory, nodeModulesAtTypes); - if (host.directoryExists(atTypes)) { + if (host.directoryExists!(atTypes)) { (typeRoots || (typeRoots = [])).push(atTypes); } return undefined; @@ -250,7 +250,6 @@ namespace ts { } function secondaryLookup(): PathAndPackageId | undefined { - let resolvedFile: PathAndPackageId; const initialLocationForSecondaryLookup = containingFile && getDirectoryPath(containingFile); if (initialLocationForSecondaryLookup !== undefined) { @@ -259,7 +258,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); } @@ -330,7 +329,7 @@ namespace ts { } export interface PerModuleNameCache { - get(directory: string): ResolvedModuleWithFailedLookupLocations; + get(directory: string): ResolvedModuleWithFailedLookupLocations | undefined; set(directory: string, result: ResolvedModuleWithFailedLookupLocations): void; } @@ -350,9 +349,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) { @@ -367,7 +366,7 @@ namespace ts { return { get, set }; - function get(directory: string): ResolvedModuleWithFailedLookupLocations { + function get(directory: string): ResolvedModuleWithFailedLookupLocations | undefined { return directoryPathMap.get(toPath(directory, currentDirectory, getCanonicalFileName)); } @@ -411,7 +410,7 @@ namespace ts { } } - function getCommonPrefix(directory: Path, resolution: string) { + function getCommonPrefix(directory: Path, resolution: string | undefined) { if (resolution === undefined) { return undefined; } @@ -470,13 +469,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); } @@ -589,8 +588,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 @@ -676,9 +675,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); } @@ -755,7 +754,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; } @@ -872,7 +871,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)); } @@ -920,7 +919,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 }; } } @@ -989,7 +988,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) { @@ -1094,7 +1093,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 { @@ -1102,7 +1101,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") { @@ -1240,7 +1239,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 70ddb7b791df1..1fa5123c49c69 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -13,10 +13,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 { @@ -34,11 +34,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); @@ -471,7 +471,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); } @@ -481,7 +481,7 @@ namespace ts { } 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); } } @@ -499,7 +499,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); } @@ -526,7 +526,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. @@ -571,7 +571,7 @@ namespace ts { let sourceFile: SourceFile; let parseDiagnostics: Diagnostic[]; - let syntaxCursor: IncrementalParser.SyntaxCursor; + let syntaxCursor: IncrementalParser.SyntaxCursor | undefined; let currentToken: SyntaxKind; let sourceText: string; @@ -658,7 +658,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); initializeState(sourceText, languageVersion, syntaxCursor, scriptKind); @@ -670,7 +670,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. @@ -711,7 +711,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(); @@ -751,11 +751,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 { @@ -793,7 +793,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)); } } @@ -821,7 +821,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); @@ -1128,7 +1128,7 @@ namespace ts { } function parseOptionalToken(t: TKind): Token; - function parseOptionalToken(t: SyntaxKind): Node { + function parseOptionalToken(t: SyntaxKind): Node | undefined { if (token() === t) { return parseTokenNode(); } @@ -1173,7 +1173,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); @@ -1450,7 +1450,7 @@ namespace ts { return true; } - Debug.fail("Non-exhaustive case in 'isListElement'."); + return Debug.fail("Non-exhaustive case in 'isListElement'."); } function isValidHeritageClauseObjectLiteral() { @@ -1552,6 +1552,8 @@ namespace ts { return token() === SyntaxKind.GreaterThanToken || token() === SyntaxKind.SlashToken; case ParsingContext.JsxChildren: return token() === SyntaxKind.LessThanToken && lookAhead(nextTokenIsSlash); + default: + return false; } } @@ -1626,7 +1628,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. @@ -1942,6 +1944,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);` } } @@ -2096,7 +2099,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); @@ -2300,7 +2303,7 @@ namespace ts { } } - function parseParameterType(): TypeNode { + function parseParameterType(): TypeNode | undefined { if (parseOptional(SyntaxKind.ColonToken)) { return parseType(); } @@ -2357,7 +2360,7 @@ namespace ts { if (!(flags & SignatureFlags.JSDoc)) { signature.typeParameters = parseTypeParameters(); } - signature.parameters = parseParameterList(flags); + signature.parameters = parseParameterList(flags)!; // TODO: GH#18217 signature.type = parseReturnType(returnToken, !!(flags & SignatureFlags.Type)); } @@ -2538,7 +2541,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; @@ -2628,7 +2631,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); } @@ -2637,7 +2640,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); } @@ -2678,7 +2681,7 @@ namespace ts { function parseLiteralTypeNode(negative?: boolean): LiteralTypeNode { const node = createNode(SyntaxKind.LiteralType) as LiteralTypeNode; - let unaryMinusExpression: PrefixUnaryExpression; + let unaryMinusExpression: PrefixUnaryExpression | undefined; if (negative) { unaryMinusExpression = createNode(SyntaxKind.PrefixUnaryExpression) as PrefixUnaryExpression; unaryMinusExpression.operator = SyntaxKind.MinusToken; @@ -2688,9 +2691,9 @@ namespace ts { ? parseTokenNode() : parseLiteralLikeNode(token()) as LiteralExpression; if (negative) { - unaryMinusExpression.operand = expression; - finishNode(unaryMinusExpression); - expression = unaryMinusExpression; + unaryMinusExpression!.operand = expression; + finishNode(unaryMinusExpression!); + expression = unaryMinusExpression!; } node.literal = expression; return finishNode(node); @@ -3013,7 +3016,7 @@ namespace ts { return type; } - function parseTypeAnnotation(): TypeNode { + function parseTypeAnnotation(): TypeNode | undefined { return parseOptional(SyntaxKind.ColonToken) ? parseType() : undefined; } @@ -3237,7 +3240,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; @@ -3436,7 +3439,7 @@ namespace ts { } } - function parsePossibleParenthesizedArrowFunctionExpressionHead(): ArrowFunction { + function parsePossibleParenthesizedArrowFunctionExpressionHead(): ArrowFunction | undefined { return parseParenthesizedArrowFunctionExpressionHead(/*allowAmbiguity*/ false); } @@ -3473,7 +3476,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; @@ -4097,7 +4100,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; } @@ -4123,7 +4126,7 @@ namespace ts { case SyntaxKind.LessThanToken: return parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ false); } - Debug.fail("Unknown JSX child kind " + token()); + return Debug.fail("Unknown JSX child kind " + token()); } function parseJsxChildren(openingTag: JsxOpeningElement | JsxOpeningFragment): NodeArray { @@ -4763,7 +4766,7 @@ namespace ts { const awaitToken = parseOptionalToken(SyntaxKind.AwaitKeyword); parseExpected(SyntaxKind.OpenParenToken); - let initializer: VariableDeclarationList | Expression = undefined; + let initializer: VariableDeclarationList | Expression | undefined; if (token() !== SyntaxKind.SemicolonToken) { if (token() === SyntaxKind.VarKeyword || token() === SyntaxKind.LetKeyword || token() === SyntaxKind.ConstKeyword) { initializer = parseVariableDeclarationList(/*inForStatementInitializer*/ true); @@ -4776,14 +4779,14 @@ namespace ts { if (awaitToken ? parseExpected(SyntaxKind.OfKeyword) : parseOptional(SyntaxKind.OfKeyword)) { const forOfStatement = createNode(SyntaxKind.ForOfStatement, pos); forOfStatement.awaitModifier = awaitToken; - forOfStatement.initializer = initializer; + forOfStatement.initializer = initializer!; forOfStatement.expression = allowInAnd(parseAssignmentExpressionOrHigher); parseExpected(SyntaxKind.CloseParenToken); forOrForInOrForOfStatement = forOfStatement; } else if (parseOptional(SyntaxKind.InKeyword)) { const forInStatement = createNode(SyntaxKind.ForInStatement, pos); - forInStatement.initializer = initializer; + forInStatement.initializer = initializer!; forInStatement.expression = allowInAnd(parseExpression); parseExpected(SyntaxKind.CloseParenToken); forOrForInOrForOfStatement = forInStatement; @@ -5206,7 +5209,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)); @@ -5259,6 +5262,7 @@ namespace ts { missing.modifiers = node.modifiers; return finishNode(missing); } + return undefined!; // TODO: GH#18217 } } @@ -5267,7 +5271,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; @@ -5345,7 +5349,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())) { @@ -5441,7 +5445,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(); @@ -5496,7 +5500,7 @@ namespace ts { } function isClassMemberStart(): boolean { - let idToken: SyntaxKind; + let idToken: SyntaxKind | undefined; if (token() === SyntaxKind.AtToken) { return true; @@ -5588,7 +5592,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(); @@ -5613,8 +5617,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(); @@ -5670,7 +5674,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 { @@ -5727,17 +5731,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 { @@ -5896,7 +5897,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) { @@ -5930,7 +5931,7 @@ namespace ts { return finishNode(node); } - function parseImportClause(identifier: Identifier, fullStart: number) { + function parseImportClause(identifier: Identifier | undefined, fullStart: number) { // ImportClause: // ImportedDefaultBinding // NameSpaceImport @@ -6088,9 +6089,9 @@ namespace ts { const triviaScanner = createScanner(sourceFile.languageVersion, /*skipTrivia*/ false, LanguageVariant.Standard, sourceText); const referencedFiles: FileReference[] = []; const typeReferenceDirectives: FileReference[] = []; - const amdDependencies: { path: string; name: string }[] = []; - let amdModuleName: string; - let checkJsDirective: CheckJsDirective = undefined; + const amdDependencies: AmdDependency[] = []; + let amdModuleName: string | undefined; + let checkJsDirective: CheckJsDirective | undefined; // Keep scanning all the leading trivia in the file until we get to something that // isn't trivia. Any single line comment will be analyzed to see if it is a @@ -6116,7 +6117,7 @@ namespace ts { const referencePathMatchResult = getFileReferenceFromReferencePath(comment, range); if (referencePathMatchResult) { const fileReference = referencePathMatchResult.fileReference; - sourceFile.hasNoDefaultLib = referencePathMatchResult.isNoDefaultLib; + sourceFile.hasNoDefaultLib = !!referencePathMatchResult.isNoDefaultLib; const diagnosticMessage = referencePathMatchResult.diagnosticMessage; if (fileReference) { if (referencePathMatchResult.isTypeReferenceDirective) { @@ -6217,7 +6218,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); @@ -6243,7 +6244,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); @@ -6253,7 +6254,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; @@ -6287,9 +6288,8 @@ namespace ts { Parameter, } - 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; @@ -6301,7 +6301,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 (!isJsDocStart(content, start)) { @@ -6448,7 +6448,7 @@ namespace ts { return; } - let tag: JSDocTag; + let tag: JSDocTag | undefined; if (tagName) { switch (tagName.escapedText) { case "augments": @@ -6637,13 +6637,13 @@ namespace ts { return finishNode(result); } - function parseNestedTypeLiteral(typeExpression: JSDocTypeExpression, name: EntityName) { + function parseNestedTypeLiteral(typeExpression: JSDocTypeExpression | undefined, name: EntityName) { if (typeExpression && isObjectOrObjectArrayTypeReference(typeExpression.type)) { const typeLiteralExpression = createNode(SyntaxKind.JSDocTypeExpression, scanner.getTokenPos()); let child: JSDocParameterTag | false; let jsdocTypeLiteral: JSDocTypeLiteral; const start = scanner.getStartPos(); - let children: JSDocParameterTag[]; + let children: JSDocParameterTag[] | undefined; while (child = tryParse(() => parseChildParameterOrPropertyTag(PropertyLikeParse.Parameter, name))) { children = append(children, child); } @@ -6708,7 +6708,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; @@ -6746,8 +6746,8 @@ namespace ts { typedefTag.typeExpression = typeExpression; 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(() => parseChildParameterOrPropertyTag(PropertyLikeParse.Property))) { if (!jsdocTypeLiteral) { @@ -6820,7 +6820,7 @@ namespace ts { if (canParseTag) { const child = tryParseChildTag(target); if (child && child.kind === SyntaxKind.JSDocParameterTag && - (ts.isIdentifier(child.name) || !escapedTextsEqual(name, child.name.left))) { + (ts.isIdentifier(child.name) || !escapedTextsEqual(name!, child.name.left))) { return false; } return child; @@ -7090,7 +7090,7 @@ namespace ts { forEachChild(node, visitNode, visitArray); if (hasJSDocNodes(node)) { - for (const jsDocComment of node.jsDoc) { + for (const jsDocComment of node.jsDoc!) { forEachChild(jsDocComment, visitNode, visitArray); } } @@ -7311,7 +7311,7 @@ namespace ts { function findNearestNodeStartingBeforeOrAtPosition(sourceFile: SourceFile, position: number): Node { let bestResult: Node = sourceFile; - let lastNodeEntirelyBeforePosition: Node; + let lastNodeEntirelyBeforePosition: Node | undefined; forEachChild(sourceFile, visit); @@ -7337,7 +7337,7 @@ namespace ts { } function getLastChildWorker(node: Node): Node | undefined { - let last: Node = undefined; + let last: Node | undefined; forEachChild(node, child => { if (nodeIsPresent(child)) { last = child; @@ -7422,10 +7422,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 { @@ -7491,9 +7491,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); 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 index 2cba011131edd..31716293ed91a 100755 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -20,7 +20,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); @@ -61,7 +61,7 @@ namespace ts { return currentDirectory; } - return getNormalizedPathFromPathComponents(commonPathComponents); + return getNormalizedPathFromPathComponents(commonPathComponents)!; } interface OutputFingerprint { @@ -79,8 +79,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); @@ -123,8 +123,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); @@ -139,7 +139,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, @@ -175,7 +175,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, @@ -231,7 +231,7 @@ namespace ts { const errorMessage = `${category} 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; @@ -278,8 +278,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; @@ -353,7 +353,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; } @@ -388,7 +388,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)); @@ -411,7 +411,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, @@ -459,7 +459,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(); @@ -489,6 +489,7 @@ namespace ts { * @param oldProgram - Reuses an old program structure. * @returns A 'Program' object. */ + // TODO: GH#18217 Have to write `host!` a lot export function createProgram(rootNames: ReadonlyArray, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program): Program { let program: Program; let files: SourceFile[] = []; @@ -526,7 +527,7 @@ namespace ts { host = host || createCompilerHost(options); let skipDefaultLib = options.noLib; - const getDefaultLibraryFileName = memoize(() => host.getDefaultLibFileName(options)); + const getDefaultLibraryFileName = memoize(() => host!.getDefaultLibFileName(options)); const defaultLibraryPath = host.getDefaultLibLocation ? host.getDefaultLibLocation() : getDirectoryPath(getDefaultLibraryFileName()); const programDiagnostics = createDiagnosticCollection(); const currentDirectory = host.getCurrentDirectory(); @@ -534,13 +535,13 @@ namespace ts { // Map storing if there is emit blocking diagnostics for given input const hasEmitBlockingDiagnostics = createMap(); - let _compilerOptionsObjectLiteralSyntax: ObjectLiteralExpression; + let _compilerOptionsObjectLiteralSyntax: ObjectLiteralExpression | null; - 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(checkAllDefined(moduleNames), containingFile, reusedNames).map(resolved => { + resolveModuleNamesWorker = (moduleNames, containingFile, reusedNames) => host!.resolveModuleNames!(checkAllDefined(moduleNames), containingFile, reusedNames).map(resolved => { // TODO: GH#18217 // 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; @@ -551,18 +552,18 @@ 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(checkAllDefined(moduleNames), containingFile, loader); + moduleResolutionCache = createModuleResolutionCache(currentDirectory, x => host!.getCanonicalFileName(x)); + const loader = (moduleName: string, containingFile: string) => resolveModuleName(moduleName, containingFile, options, host!, moduleResolutionCache).resolvedModule!; // TODO: GH#18217 + resolveModuleNamesWorker = (moduleNames, containingFile) => loadWithLocalCache(checkAllDefined(moduleNames), containingFile, loader); } let resolveTypeReferenceDirectiveNamesWorker: (typeDirectiveNames: string[], containingFile: string) => ResolvedTypeReferenceDirective[]; if (host.resolveTypeReferenceDirectives) { - resolveTypeReferenceDirectiveNamesWorker = (typeDirectiveNames, containingFile) => host.resolveTypeReferenceDirectives(checkAllDefined(typeDirectiveNames), containingFile); + resolveTypeReferenceDirectiveNamesWorker = (typeDirectiveNames, containingFile) => host!.resolveTypeReferenceDirectives!(checkAllDefined(typeDirectiveNames), containingFile); // TODO: GH#18217 } else { - const loader = (typesRef: string, containingFile: string) => resolveTypeReferenceDirective(typesRef, containingFile, options, host).resolvedTypeReferenceDirective; - resolveTypeReferenceDirectiveNamesWorker = (typeReferenceDirectiveNames, containingFile) => loadWithLocalCache(checkAllDefined(typeReferenceDirectiveNames), containingFile, loader); + const loader = (typesRef: string, containingFile: string) => resolveTypeReferenceDirective(typesRef, containingFile, options, host!).resolvedTypeReferenceDirective!; // TODO: GH#18217 + resolveTypeReferenceDirectiveNamesWorker = (typeReferenceDirectiveNames, containingFile) => loadWithLocalCache(checkAllDefined(typeReferenceDirectiveNames), containingFile, loader); } // Map from a stringified PackageId to the source file with that id. @@ -575,7 +576,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; @@ -642,7 +643,7 @@ namespace ts { getSourceFile, getSourceFileByPath, getSourceFiles: () => files, - getMissingFilePaths: () => missingFilePaths, + getMissingFilePaths: () => missingFilePaths!, // TODO: GH#18217 getCompilerOptions: () => options, getSyntacticDiagnostics, getOptionsDiagnostics, @@ -707,7 +708,7 @@ namespace ts { classifiableNames = createUnderscoreEscapedMap(); for (const sourceFile of files) { - copyEntries(sourceFile.classifiableNames, classifiableNames); + copyEntries(sourceFile.classifiableNames!, classifiableNames); } } @@ -718,7 +719,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) { @@ -740,7 +741,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; @@ -751,7 +752,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`. * @@ -761,8 +762,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 = {}; @@ -770,10 +771,10 @@ 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); + if (isTraceEnabled(options, host!)) { + trace(host!, Diagnostics.Reusing_resolution_of_module_0_to_file_1_from_old_program, moduleName, containingFile); } (result || (result = new Array(moduleNames.length)))[i] = oldResolvedModule; (reusedNames || (reusedNames = [])).push(moduleName); @@ -787,8 +788,8 @@ namespace ts { let resolvesToAmbientModuleInNonModifiedFile = false; if (contains(file.ambientModuleNames, moduleName)) { resolvesToAmbientModuleInNonModifiedFile = true; - if (isTraceEnabled(options, host)) { - trace(host, Diagnostics.Module_0_was_resolved_as_locally_declared_ambient_module_in_file_1, moduleName, containingFile); + if (isTraceEnabled(options, host!)) { + trace(host!, Diagnostics.Module_0_was_resolved_as_locally_declared_ambient_module_in_file_1, moduleName, containingFile); } } else { @@ -821,7 +822,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 { @@ -836,7 +837,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 @@ -860,8 +861,8 @@ namespace ts { return false; } - if (isTraceEnabled(options, host)) { - trace(host, Diagnostics.Module_0_was_resolved_as_ambient_module_declared_in_1_since_this_file_was_not_modified, moduleName, firstUnmodifiedFile.fileName); + if (isTraceEnabled(options, host!)) { + trace(host!, Diagnostics.Module_0_was_resolved_as_ambient_module_declared_in_1_since_this_file_was_not_modified, moduleName, firstUnmodifiedFile.fileName); } return true; } @@ -879,7 +880,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(); @@ -900,7 +901,7 @@ namespace ts { // If the missing file paths are now present, it can change the progam structure, // and hence cant reuse the structure. // This is same as how we dont reuse the structure if one of the file from old program is now missing - if (oldProgram.getMissingFilePaths().some(missingFilePath => host.fileExists(missingFilePath))) { + if (oldProgram.getMissingFilePaths().some(missingFilePath => host!.fileExists(missingFilePath))) { return oldProgram.structureIsReused = StructureIsReused.Not; } @@ -909,9 +910,9 @@ namespace ts { const seenPackageNames = createMap(); 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); + let newSourceFile = host!.getSourceFileByPath + ? 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; @@ -1047,7 +1048,7 @@ namespace ts { return oldProgram.structureIsReused; } - if (host.hasChangedAutomaticTypeDirectiveNames) { + if (host!.hasChangedAutomaticTypeDirectiveNames) { return oldProgram.structureIsReused = StructureIsReused.SafeModules; } @@ -1057,7 +1058,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); } } @@ -1082,19 +1083,19 @@ namespace ts { getCommonSourceDirectory: program.getCommonSourceDirectory, getCompilerOptions: program.getCompilerOptions, getCurrentDirectory: () => currentDirectory, - getNewLine: () => host.getNewLine(), + getNewLine: () => host!.getNewLine(), getSourceFile: program.getSourceFile, getSourceFileByPath: program.getSourceFileByPath, getSourceFiles: program.getSourceFiles, isSourceFileFromExternalLibrary, writeFile: writeFileCallback || ( - (fileName, data, writeByteOrderMark, onError, sourceFiles) => host.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles)), + (fileName, data, writeByteOrderMark, onError, sourceFiles) => host!.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles)), isEmitBlocked, }; } function isSourceFileFromExternalLibrary(file: SourceFile): boolean { - return sourceFilesFoundSearchingNodeModules.get(file.path); + return !!sourceFilesFoundSearchingNodeModules.get(file.path); } function isSourceFileDefaultLibrary(file: SourceFile): boolean { @@ -1108,12 +1109,12 @@ namespace ts { // If '--lib' is not specified, include default library file according to '--target' // otherwise, using options specified in '--lib' instead of '--target' default library file - const equalityComparer = host.useCaseSensitiveFileNames() ? equateStringsCaseSensitive : equateStringsCaseInsensitive; + const equalityComparer = host!.useCaseSensitiveFileNames() ? equateStringsCaseSensitive : equateStringsCaseInsensitive; if (!options.lib) { 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))); } } @@ -1122,7 +1123,7 @@ namespace ts { } function dropDiagnosticsProducingTypeChecker() { - diagnosticsProducingTypeChecker = undefined; + diagnosticsProducingTypeChecker = undefined!; } function getTypeChecker() { @@ -1137,12 +1138,12 @@ 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) { if (options.noEmit) { - return { diagnostics: declarationDiagnostics, sourceMaps: undefined, emittedFiles: undefined, emitSkipped: true }; + return { diagnostics: declarationDiagnostics, sourceMaps: undefined!, emittedFiles: undefined!, emitSkipped: true }; // TODO: GH#18217 } // If the noEmitOnError flag is set, then check if we have any errors so far. If so, @@ -1163,8 +1164,8 @@ namespace ts { if (diagnostics.length > 0 || declarationDiagnostics.length > 0) { return { diagnostics: concatenate(diagnostics, declarationDiagnostics), - sourceMaps: undefined, - emittedFiles: undefined, + sourceMaps: undefined!, + emittedFiles: undefined!, emitSkipped: true }; } @@ -1265,8 +1266,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; @@ -1313,7 +1314,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); @@ -1537,7 +1538,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(); @@ -1591,9 +1592,9 @@ namespace ts { const isExternalModuleFile = isExternalModule(file); // file.imports may not be undefined if there exists dynamic import - let imports: StringLiteral[]; - let moduleAugmentations: (StringLiteral | Identifier)[]; - let ambientModules: string[]; + let imports: StringLiteral[] | undefined; + 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. @@ -1702,7 +1703,7 @@ namespace ts { refFile?: SourceFile): SourceFile | undefined { if (hasExtension(fileName)) { - if (!options.allowNonTsExtensions && !forEach(supportedExtensions, extension => fileExtensionIs(host.getCanonicalFileName(fileName), extension))) { + if (!options.allowNonTsExtensions && !forEach(supportedExtensions, extension => fileExtensionIs(host!.getCanonicalFileName(fileName), extension))) { if (fail) fail(Diagnostics.File_0_has_unsupported_extension_The_only_supported_extensions_are_1, fileName, "'" + supportedExtensions.join("', '") + "'"); return undefined; } @@ -1712,7 +1713,7 @@ namespace ts { if (!sourceFile) { fail(Diagnostics.File_0_not_found, fileName); } - else if (refFile && host.getCanonicalFileName(fileName) === host.getCanonicalFileName(refFile.fileName)) { + else if (refFile && host!.getCanonicalFileName(fileName) === host!.getCanonicalFileName(refFile.fileName)) { fail(Diagnostics.A_file_cannot_have_a_reference_to_itself); } } @@ -1736,7 +1737,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) @@ -1762,12 +1763,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; @@ -1807,7 +1808,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)); @@ -1823,7 +1824,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); @@ -1842,15 +1843,15 @@ namespace ts { sourceFilesFoundSearchingNodeModules.set(path, currentNodeModulesDepth > 0); file.path = path; - if (host.useCaseSensitiveFileNames()) { + 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); } } @@ -1909,7 +1910,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 @@ -1917,9 +1918,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, @@ -1932,12 +1933,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) { @@ -1955,7 +1956,7 @@ namespace ts { } function getCanonicalFileName(fileName: string): string { - return host.getCanonicalFileName(fileName); + return host!.getCanonicalFileName(fileName); } function processImportedModules(file: SourceFile) { @@ -2031,11 +2032,11 @@ namespace ts { function checkSourceFilesBelongToPath(sourceFiles: SourceFile[], rootDirectory: string): boolean { let allFilesBelongToPath = true; if (sourceFiles) { - const absoluteRootDirectoryPath = host.getCanonicalFileName(getNormalizedAbsolutePath(rootDirectory, currentDirectory)); + const absoluteRootDirectoryPath = host!.getCanonicalFileName(getNormalizedAbsolutePath(rootDirectory, currentDirectory)); for (const sourceFile of sourceFiles) { if (!sourceFile.isDeclarationFile) { - const absoluteSourceFilePath = host.getCanonicalFileName(getNormalizedAbsolutePath(sourceFile.fileName, currentDirectory)); + const absoluteSourceFilePath = host!.getCanonicalFileName(getNormalizedAbsolutePath(sourceFile.fileName, currentDirectory)); if (absoluteSourceFilePath.indexOf(absoluteRootDirectoryPath) !== 0) { programDiagnostics.add(createCompilerDiagnostic(Diagnostics.File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files, sourceFile.fileName, options.rootDir)); allFilesBelongToPath = false; @@ -2163,7 +2164,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)); } @@ -2173,7 +2174,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")); } } @@ -2241,12 +2242,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); @@ -2255,7 +2256,7 @@ namespace ts { blockEmittingOfFile(emitFileName, createCompilerDiagnosticFromMessageChain(chain)); } - const emitFileKey = !host.useCaseSensitiveFileNames() ? emitFilePath.toLocaleLowerCase() : emitFilePath; + const emitFileKey = !host!.useCaseSensitiveFileNames() ? emitFilePath.toLocaleLowerCase() : emitFilePath; // Report error if multiple files write into same file if (emitFilesSeen.has(emitFileKey)) { // Already seen the same emit file - report error @@ -2272,11 +2273,11 @@ namespace ts { let needCompilerDiagnostic = true; const pathsSyntax = getOptionPathsSyntax(); 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)); + if (isObjectLiteralExpression(pathProp.initializer!)) { // TODO: GH#18217 + for (const keyProps of getPropertyAssignment(pathProp.initializer as ObjectLiteralExpression, key)) { + 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; } } @@ -2292,9 +2293,9 @@ namespace ts { let needCompilerDiagnostic = true; const pathsSyntax = getOptionPathsSyntax(); for (const pathProp of pathsSyntax) { - if (isObjectLiteralExpression(pathProp.initializer) && + if (isObjectLiteralExpression(pathProp.initializer!) && // TODO: GH#18217 createOptionDiagnosticInObjectLiteralSyntax( - pathProp.initializer, onKey, key, /*key2*/ undefined, + pathProp.initializer as ObjectLiteralExpression, onKey, key, /*key2*/ undefined, message, arg0)) { needCompilerDiagnostic = false; } @@ -2320,7 +2321,7 @@ namespace ts { createDiagnosticForOption(/*onKey*/ false, option1, /*option2*/ undefined, message, arg0); } - function createDiagnosticForOption(onKey: boolean, option1: string, option2: string, message: DiagnosticMessage, arg0: string | number, arg1?: string | number) { + function createDiagnosticForOption(onKey: boolean, option1: string, option2: string | undefined, message: DiagnosticMessage, arg0: string | number, arg1?: string | number) { const compilerOptionsObjectLiteralSyntax = getCompilerOptionsObjectLiteralSyntax(); const needCompilerDiagnostic = !compilerOptionsObjectLiteralSyntax || !createOptionDiagnosticInObjectLiteralSyntax(compilerOptionsObjectLiteralSyntax, onKey, option1, option2, message, arg0, arg1); @@ -2335,8 +2336,8 @@ namespace ts { _compilerOptionsObjectLiteralSyntax = null; // tslint:disable-line:no-null-keyword if (options.configFile && options.configFile.jsonObject) { for (const prop of getPropertyAssignment(options.configFile.jsonObject, "compilerOptions")) { - if (isObjectLiteralExpression(prop.initializer)) { - _compilerOptionsObjectLiteralSyntax = prop.initializer; + if (isObjectLiteralExpression(prop.initializer!)) { // TODO: GH#18217 + _compilerOptionsObjectLiteralSyntax = prop.initializer as ObjectLiteralExpression; break; } } @@ -2345,10 +2346,10 @@ namespace ts { return _compilerOptionsObjectLiteralSyntax; } - function createOptionDiagnosticInObjectLiteralSyntax(objectLiteral: ObjectLiteralExpression, onKey: boolean, key1: string, key2: string, message: DiagnosticMessage, arg0: string | number, arg1?: string | number): boolean { + function createOptionDiagnosticInObjectLiteralSyntax(objectLiteral: ObjectLiteralExpression, onKey: boolean, key1: string, key2: string | undefined, message: DiagnosticMessage, arg0: string | number, arg1?: 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)); + programDiagnostics.add(createDiagnosticForNodeInSourceFile(options.configFile!, onKey ? prop.name : prop.initializer!, message, arg0, arg1)); } return !!props.length; } @@ -2358,7 +2359,7 @@ namespace ts { programDiagnostics.add(diag); } - function isEmittedFile(file: string) { + function isEmittedFile(file: string): boolean { if (options.noEmit) { return false; } @@ -2377,7 +2378,7 @@ namespace ts { // If --outDir, check if file is in that directory if (options.outDir) { - return containsPath(options.outDir, filePath, currentDirectory, !host.useCaseSensitiveFileNames()); + return containsPath(options.outDir, filePath, currentDirectory, !host!.useCaseSensitiveFileNames()); } if (fileExtensionIsOneOf(filePath, supportedJavascriptExtensions) || fileExtensionIs(filePath, Extension.Dts)) { @@ -2390,7 +2391,7 @@ namespace ts { } function isSameFile(file1: string, file2: string) { - return comparePaths(file1, file2, currentDirectory, !host.useCaseSensitiveFileNames()) === Comparison.EqualTo; + return comparePaths(file1, file2, currentDirectory, !host!.useCaseSensitiveFileNames()) === Comparison.EqualTo; } } diff --git a/src/compiler/resolutionCache.ts b/src/compiler/resolutionCache.ts index e907d2d62b728..17abd28d16972 100644 --- a/src/compiler/resolutionCache.ts +++ b/src/compiler/resolutionCache.ts @@ -7,7 +7,7 @@ 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[]; resolveTypeReferenceDirectives(typeDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[]; @@ -71,9 +71,9 @@ namespace ts { export const maxNumberOfFilesToIterateForInvalidation = 256; type GetResolutionWithResolvedFileName = - (resolution: T) => R; + (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 allFilesHaveInvalidatedResolution = false; @@ -87,7 +87,7 @@ namespace ts { const resolvedTypeReferenceDirectives = createMap>(); const perDirectoryResolvedTypeReferenceDirectives = createMap>(); - const getCurrentDirectory = memoize(() => resolutionHost.getCurrentDirectory()); + const getCurrentDirectory = memoize(() => resolutionHost.getCurrentDirectory!()); const cachedDirectoryStructureHost = resolutionHost.getCachedDirectoryStructureHost(); /** @@ -101,7 +101,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(); @@ -131,7 +131,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; } @@ -168,7 +168,7 @@ namespace ts { } const collected = filesWithInvalidatedResolutions; filesWithInvalidatedResolutions = undefined; - return path => collected && collected.has(path); + return path => !!collected && collected.has(path); } function clearPerDirectoryResolutions() { @@ -221,7 +221,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) { @@ -267,7 +267,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 @@ -280,7 +280,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; } @@ -354,7 +354,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 } let dir = getDirectoryPath(getNormalizedAbsolutePath(failedLookupLocation, getCurrentDirectory())); @@ -459,7 +459,7 @@ namespace ts { } const { dirPath, ignore } = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath); if (!ignore) { - const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath); + const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath)!; // Do not close the watcher yet since it might be needed by other failed lookup locations. dirWatcher.refCount--; } @@ -513,10 +513,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; @@ -550,7 +550,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 } ); } diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index cdb055bb7326d..7de93f78fb6fb 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -40,8 +40,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; @@ -269,14 +269,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); } @@ -604,7 +604,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; } @@ -629,11 +629,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 | undefined; + let pendingEnd: number | undefined; + let pendingKind: CommentKind | undefined; + let pendingHasTrailingNewLine: boolean | undefined; let hasPendingCommentRange = false; let collecting = trailing || pos === 0; let accumulator = initial; @@ -691,7 +691,7 @@ namespace ts { if (collecting) { if (hasPendingCommentRange) { - accumulator = cb(pendingPos, pendingEnd, pendingKind, pendingHasTrailingNewLine, state, accumulator); + accumulator = cb(pendingPos!, pendingEnd!, pendingKind!, pendingHasTrailingNewLine!, state, accumulator); if (!reduce && accumulator) { // If we are not reducing and we have a truthy result, return it. return accumulator; @@ -723,7 +723,7 @@ namespace ts { } if (hasPendingCommentRange) { - accumulator = cb(pendingPos, pendingEnd, pendingKind, pendingHasTrailingNewLine, state, accumulator); + accumulator = cb(pendingPos!, pendingEnd!, pendingKind!, pendingHasTrailingNewLine!, state, accumulator); } return accumulator; @@ -774,20 +774,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; } @@ -805,13 +805,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; @@ -822,7 +825,7 @@ namespace ts { let tokenPos: number; let token: SyntaxKind; - let tokenValue: string; + let tokenValue: string | undefined; let tokenFlags: TokenFlags; setText(text, start, length); @@ -833,7 +836,7 @@ namespace ts { getToken: () => token, getTokenPos: () => tokenPos, getTokenText: () => text.substring(tokenPos, pos), - getTokenValue: () => tokenValue, + getTokenValue: () => tokenValue!, hasExtendedUnicodeEscape: () => (tokenFlags & TokenFlags.ExtendedUnicodeEscape) !== 0, hasPrecedingLineBreak: () => (tokenFlags & TokenFlags.PrecedingLineBreak) !== 0, isIdentifier: () => token === SyntaxKind.Identifier || token > SyntaxKind.LastReservedWord, @@ -912,8 +915,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(); @@ -1286,11 +1289,11 @@ namespace ts { function getIdentifierToken(): SyntaxKind { // Reserved words are between 2 and 11 characters long and start with a lowercase letter - const len = tokenValue.length; + const len = tokenValue!.length; if (len >= 2 && len <= 11) { - const ch = tokenValue.charCodeAt(0); + 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; } diff --git a/src/compiler/sourcemap.ts b/src/compiler/sourcemap.ts index 2dabb97b08d7d..8654026617dcf 100644 --- a/src/compiler/sourcemap.ts +++ b/src/compiler/sourcemap.ts @@ -10,7 +10,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): void; + initialize(filePath: string, sourceMapFilePath: string | undefined, sourceFileOrBundle: SourceFile | Bundle): void; /** * Reset the SourceMapWriter to an empty state. @@ -89,9 +89,9 @@ 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; @@ -132,8 +132,8 @@ namespace ts { reset(); } - currentSource = undefined; - currentSourceText = undefined; + currentSource = undefined!; + currentSourceText = undefined!; // Current source map file and its index in the sources list sourceMapSourceIndex = -1; @@ -146,7 +146,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: [], @@ -199,13 +199,13 @@ namespace ts { return; } - currentSource = undefined; - sourceMapDir = undefined; - sourceMapSourceIndex = undefined; + currentSource = undefined!; + sourceMapDir = undefined!; + sourceMapSourceIndex = undefined!; lastRecordedSourceMapSpan = undefined; - lastEncodedSourceMapSpan = undefined; + lastEncodedSourceMapSpan = undefined!; lastEncodedNameIndex = undefined; - sourceMapData = undefined; + sourceMapData = undefined!; } // Encoding for sourcemap span @@ -214,9 +214,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 += ","; @@ -224,7 +224,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; @@ -234,18 +234,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; } @@ -336,14 +336,14 @@ namespace ts { if (source) setSourceFile(source); if (node.kind !== SyntaxKind.NotEmittedStatement - && (emitFlags & EmitFlags.NoLeadingSourceMap) === 0 + && (emitFlags! & EmitFlags.NoLeadingSourceMap) === 0 && pos >= 0) { emitPos(skipSourceTrivia(pos)); } if (source) setSourceFile(oldSource); - if (emitFlags & EmitFlags.NoNestedSourceMaps) { + if (emitFlags! & EmitFlags.NoNestedSourceMaps) { disabled = true; emitCallback(hint, node); disabled = false; @@ -355,7 +355,7 @@ namespace ts { if (source) setSourceFile(source); if (node.kind !== SyntaxKind.NotEmittedStatement - && (emitFlags & EmitFlags.NoTrailingSourceMap) === 0 + && (emitFlags! & EmitFlags.NoTrailingSourceMap) === 0 && end >= 0) { emitPos(end); } @@ -382,14 +382,14 @@ namespace ts { const range = emitNode && emitNode.tokenSourceMapRanges && emitNode.tokenSourceMapRanges[token]; tokenPos = skipSourceTrivia(range ? range.pos : tokenPos); - if ((emitFlags & EmitFlags.NoTokenLeadingSourceMaps) === 0 && tokenPos >= 0) { + if ((emitFlags! & EmitFlags.NoTokenLeadingSourceMaps) === 0 && tokenPos >= 0) { emitPos(tokenPos); } tokenPos = emitCallback(token, writer, tokenPos); if (range) tokenPos = range.end; - if ((emitFlags & EmitFlags.NoTokenTrailingSourceMaps) === 0 && tokenPos >= 0) { + if ((emitFlags! & EmitFlags.NoTokenTrailingSourceMaps) === 0 && tokenPos >= 0) { emitPos(tokenPos); } @@ -429,7 +429,7 @@ namespace ts { sourceMapData.inputSourceFileNames.push(currentSource.fileName); if (compilerOptions.inlineSources) { - sourceMapData.sourceMapSourcesContent.push(currentSource.text); + sourceMapData.sourceMapSourcesContent!.push(currentSource.text); } } } @@ -439,7 +439,7 @@ namespace ts { */ function getText() { if (disabled) { - return; + return undefined!; // TODO: GH#18217 } encodeLastRecordedSourceMapSpan(); @@ -460,7 +460,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 8cafd8c01383d..a3331c726934f 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -119,6 +119,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 @@ -214,7 +215,7 @@ namespace ts { ? undefined : ts.getNormalizedAbsolutePath(relativeFileName, baseDirPath); // Some applications save a working file via rename operations - if ((eventName === "change" || eventName === "rename")) { + if (fileName !== undefined && (eventName === "change" || eventName === "rename")) { const callbacks = fileWatcherCallbacks.get(fileName); if (callbacks) { for (const fileCallback of callbacks) { @@ -227,7 +228,7 @@ namespace ts { const watchedFileSet = createWatchedFileSet(); const nodeVersion = getNodeMajorVersion(); - const isNode4OrLater = nodeVersion >= 4; + const isNode4OrLater = nodeVersion !== undefined && nodeVersion >= 4; function isFileSystemCaseSensitive(): boolean { // win32\win64 are case insensitive platforms @@ -373,7 +374,7 @@ namespace ts { data = byteOrderMarkIndicator + data; } - let fd: number; + let fd: number | undefined; try { fd = _fs.openSync(fileName, "w"); @@ -436,6 +437,7 @@ namespace ts { switch (entryKind) { case FileSystemEntryKind.File: return stat.isFile(); case FileSystemEntryKind.Directory: return stat.isDirectory(); + default: return false; } } catch (e) { @@ -608,7 +610,7 @@ namespace ts { } } - let sys: System; + let sys: System | undefined; if (typeof ChakraHost !== "undefined") { sys = getChakraSystem(); } @@ -622,13 +624,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 341c0c9cd45ec..231a13f3f2994 100644 --- a/src/compiler/transformer.ts +++ b/src/compiler/transformer.ts @@ -92,7 +92,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[]; @@ -100,7 +100,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; @@ -109,8 +109,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, @@ -279,8 +279,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. */ @@ -303,12 +303,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]; @@ -363,12 +363,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/destructuring.ts b/src/compiler/transformers/destructuring.ts index bafe43b0b1571..d9141088fc004 100644 --- a/src/compiler/transformers/destructuring.ts +++ b/src/compiler/transformers/destructuring.ts @@ -9,7 +9,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; @@ -40,7 +40,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)) { @@ -54,11 +54,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,10 +103,10 @@ namespace ts { return value; } - expressions.push(value); + expressions!.push(value); } - return aggregateTransformFlags(inlineExpressions(expressions)) || createOmittedExpression(); + return aggregateTransformFlags(inlineExpressions(expressions!)) || createOmittedExpression(); // TODO: GH#18217 function emitExpression(expression: Expression) { // NOTE: this completely disables source maps, but aligns with the behavior of @@ -130,7 +130,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); } @@ -167,15 +167,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, @@ -205,7 +205,7 @@ namespace ts { } else { context.hoistVariableDeclaration(temp); - const pendingDeclaration = lastOrUndefined(pendingDeclarations); + const pendingDeclaration = last(pendingDeclarations); pendingDeclaration.pendingExpressions = append( pendingDeclaration.pendingExpressions, createAssignment(temp, pendingDeclaration.value) @@ -234,7 +234,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)); @@ -271,15 +271,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 } } @@ -303,15 +303,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)) + && !(element.transformFlags! & (TransformFlags.ContainsRest | TransformFlags.ContainsObjectRest)) + && !(getTargetOfBindingOrAssignmentElement(element)!.transformFlags! & (TransformFlags.ContainsRest | TransformFlags.ContainsObjectRest)) && !isComputedPropertyName(propertyName)) { bindingElements = append(bindingElements, element); } @@ -322,7 +322,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); } @@ -332,7 +332,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); } } @@ -380,14 +380,14 @@ 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) { // If an array pattern contains an ObjectRest, we must cache the result so that we // can perform the ObjectRest destructuring in a different declaration - if (element.transformFlags & TransformFlags.ContainsObjectRest) { + if (element.transformFlags! & TransformFlags.ContainsObjectRest) { const temp = createTempVariable(/*recordTempVariable*/ undefined); if (flattenContext.hoistTempVariables) { flattenContext.context.hoistVariableDeclaration(temp); diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index 7e4769a3e50a7..f5bff868ced7e 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -163,7 +163,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 { @@ -290,7 +290,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. @@ -312,9 +312,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; } @@ -342,13 +342,13 @@ namespace ts { } function isReturnVoidStatementInConstructorWithCapturedSuper(node: Node): boolean { - return hierarchyFacts & HierarchyFacts.ConstructorWithCapturedSuper + return (hierarchyFacts & HierarchyFacts.ConstructorWithCapturedSuper) !== 0 && node.kind === SyntaxKind.ReturnStatement && !(node).expression; } function shouldVisitNode(node: Node): boolean { - return (node.transformFlags & TransformFlags.ContainsES2015) !== 0 + return (node.transformFlags! & TransformFlags.ContainsES2015) !== 0 || convertedLoopState !== undefined || (hierarchyFacts & HierarchyFacts.ConstructorWithCapturedSuper && (isStatement(node) || (node.kind === SyntaxKind.Block))) || (isIterationStatement(node, /*lookInLabeledStatements*/ false) && shouldConvertIterationStatementBody(node)) @@ -524,7 +524,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)); @@ -545,7 +545,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; @@ -566,7 +566,7 @@ namespace ts { function visitReturnStatement(node: ReturnStatement): Statement { if (convertedLoopState) { - convertedLoopState.nonLocalJumps |= Jump.Return; + convertedLoopState.nonLocalJumps! |= Jump.Return; if (isReturnVoidStatementInConstructorWithCapturedSuper(node)) { node = returnCapturedThis(node); } @@ -623,45 +623,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); } @@ -818,7 +819,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); @@ -854,7 +855,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( @@ -874,7 +875,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); @@ -908,13 +909,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) || []; } @@ -927,7 +928,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(); @@ -939,7 +940,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) { @@ -947,7 +948,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!"); @@ -955,7 +956,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. @@ -968,14 +969,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( createIdentifier("_this") @@ -994,7 +995,7 @@ namespace ts { createNodeArray( statements ), - /*location*/ constructor ? constructor.body.statements : node.members + /*location*/ constructor ? constructor.body!.statements : node.members ), /*multiLine*/ true ); @@ -1089,10 +1090,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]; @@ -1105,7 +1106,7 @@ namespace ts { // but only if the constructor itself doesn't use 'this' elsewhere. if (superCallExpression && statementOffset === ctorStatements.length - 1 - && !(ctor.transformFlags & (TransformFlags.ContainsLexicalThis | TransformFlags.ContainsCapturedLexicalThis))) { + && !(ctor.transformFlags! & (TransformFlags.ContainsLexicalThis | TransformFlags.ContainsCapturedLexicalThis))) { const returnStatement = createReturn(superCallExpression); if (superCallExpression.kind !== SyntaxKind.BinaryExpression @@ -1160,7 +1161,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; @@ -1214,7 +1215,7 @@ namespace ts { * @param node A function-like node. */ function shouldAddDefaultValueAssignments(node: FunctionLikeDeclaration): boolean { - return (node.transformFlags & TransformFlags.ContainsDefaultValueAssignments) !== 0; + return (node.transformFlags! & TransformFlags.ContainsDefaultValueAssignments) !== 0; } /** @@ -1255,7 +1256,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 '{}', @@ -1340,7 +1341,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; } @@ -1360,11 +1361,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(); @@ -1438,7 +1439,7 @@ namespace ts { * @param node A node. */ function addCaptureThisForNodeIfNeeded(statements: Statement[], node: Node): void { - if (node.transformFlags & TransformFlags.ContainsCapturedLexicalThis && node.kind !== SyntaxKind.ArrowFunction) { + if (node.transformFlags! & TransformFlags.ContainsCapturedLexicalThis && node.kind !== SyntaxKind.ArrowFunction) { captureThisForNode(statements, node, createThis()); } } @@ -1507,8 +1508,7 @@ namespace ts { break; default: - Debug.failBadSyntaxKind(node); - break; + return Debug.failBadSyntaxKind(node); } const captureNewTargetStatement = createVariableStatement( @@ -1625,7 +1625,7 @@ namespace ts { // No comments should be emitted for this statement to align with the // old emitter. setEmitFlags(statement, EmitFlags.NoComments); - setSourceMapRange(statement, getSourceMapRange(accessors.firstAccessor)); + setSourceMapRange(statement, getSourceMapRange(accessors.firstAccessor!)); // TODO: GH#18217 return statement; } @@ -1642,11 +1642,11 @@ 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)); + const propertyName = createExpressionForPropertyName(visitNode(firstAccessor!.name, visitor, isPropertyName)); setEmitFlags(propertyName, EmitFlags.NoComments | EmitFlags.NoLeadingSourceMap); - setSourceMapRange(propertyName, firstAccessor.name); + setSourceMapRange(propertyName, firstAccessor!.name); const properties: ObjectLiteralElementLike[] = []; if (getAccessor) { @@ -1695,7 +1695,7 @@ namespace ts { * @param node An ArrowFunction node. */ function visitArrowFunction(node: ArrowFunction) { - if (node.transformFlags & TransformFlags.ContainsLexicalThis) { + if (node.transformFlags! & TransformFlags.ContainsLexicalThis) { enableSubstitutionsForCapturedThis(); } const savedConvertedLoopState = convertedLoopState; @@ -1731,7 +1731,7 @@ namespace ts { convertedLoopState = undefined; const parameters = visitParameterList(node.parameters, visitor, context); - const body = node.transformFlags & TransformFlags.ES2015 + const body = node.transformFlags! & TransformFlags.ES2015 ? transformFunctionBody(node) : visitFunctionBodyDownLevel(node); const name = hierarchyFacts & HierarchyFacts.NewTarget @@ -1762,7 +1762,7 @@ namespace ts { convertedLoopState = undefined; const ancestorFacts = enterSubtree(HierarchyFacts.FunctionExcludes, HierarchyFacts.FunctionIncludes); const parameters = visitParameterList(node.parameters, visitor, context); - const body = node.transformFlags & TransformFlags.ES2015 + const body = node.transformFlags! & TransformFlags.ES2015 ? transformFunctionBody(node) : visitFunctionBodyDownLevel(node); const name = hierarchyFacts & HierarchyFacts.NewTarget @@ -1791,7 +1791,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) @@ -1831,11 +1831,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)) { @@ -1920,7 +1920,7 @@ namespace ts { } function visitFunctionBodyDownLevel(node: FunctionDeclaration | FunctionExpression) { - const updated = visitFunctionBody(node.body, functionBodyVisitor, context); + const updated = visitFunctionBody(node.body!, functionBodyVisitor, context); return updateBlock( updated, setTextRange( @@ -2004,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) { @@ -2052,7 +2052,7 @@ namespace ts { * @param node A VariableDeclarationList node. */ function visitVariableDeclarationList(node: VariableDeclarationList): VariableDeclarationList { - if (node.transformFlags & TransformFlags.ES2015) { + if (node.transformFlags! & TransformFlags.ES2015) { if (node.flags & NodeFlags.BlockScoped) { enableSubstitutionsForBlockScopedBindings(); } @@ -2066,14 +2066,13 @@ namespace ts { setTextRange(declarationList, node); setCommentRange(declarationList, node); - if (node.transformFlags & TransformFlags.ContainsBindingPattern - && (isBindingPattern(node.declarations[0].name) || isBindingPattern(lastOrUndefined(node.declarations).name))) { + if (node.transformFlags! & TransformFlags.ContainsBindingPattern + && (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)); } } @@ -2199,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 { @@ -2230,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, @@ -2245,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, @@ -2253,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, @@ -2261,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, @@ -2272,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. @@ -2294,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( @@ -2321,12 +2319,12 @@ namespace ts { boundValue ) ]), - moveRangePos(node.initializer, -1) + moveRangePos(initializer, -1) ), - node.initializer + initializer ) ), - moveRangeEnd(node.initializer, -1) + moveRangeEnd(initializer, -1) ) ); } @@ -2334,19 +2332,19 @@ 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))); } } - let bodyLocation: TextRange; - let statementsLocation: TextRange; + let bodyLocation: TextRange | undefined; + let statementsLocation: TextRange | undefined; if (convertedLoopBodyStatements) { addRange(statements, convertedLoopBodyStatements); } @@ -2568,11 +2566,11 @@ namespace ts { let numInitialPropertiesWithoutYield = numProperties; for (let i = 0; i < numProperties; i++) { const property = properties[i]; - if ((property.transformFlags & TransformFlags.ContainsYield && hierarchyFacts & HierarchyFacts.AsyncFunctionBody) + if ((property.transformFlags! & TransformFlags.ContainsYield && hierarchyFacts & HierarchyFacts.AsyncFunctionBody) && i < numInitialPropertiesWithoutYield) { numInitialPropertiesWithoutYield = i; } - if (property.name.kind === SyntaxKind.ComputedPropertyName) { + if (property.name!.kind === SyntaxKind.ComputedPropertyName) { numInitialProperties = i; break; } @@ -2632,7 +2630,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) { @@ -2644,9 +2642,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 @@ -2665,7 +2663,7 @@ namespace ts { } const functionName = createUniqueName("_loop"); - let loopInitializer: VariableDeclarationList; + let loopInitializer: VariableDeclarationList | undefined; switch (node.kind) { case SyntaxKind.ForStatement: case SyntaxKind.ForInStatement: @@ -2731,7 +2729,7 @@ namespace ts { loopBody = createBlock([loopBody], /*multiline*/ true); } - const containsYield = (node.statement.transformFlags & TransformFlags.ContainsYield) !== 0; + const containsYield = (node.statement.transformFlags! & TransformFlags.ContainsYield) !== 0; const isAsyncBlockContainingAwait = containsYield && (hierarchyFacts & HierarchyFacts.AsyncFunctionBody) !== 0; let loopBodyFlags: EmitFlags = 0; @@ -2773,7 +2771,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 @@ -2858,7 +2856,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 @@ -2893,7 +2891,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; @@ -2906,7 +2904,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"); @@ -2917,12 +2915,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 { @@ -2940,7 +2938,7 @@ namespace ts { ); } - if (state.nonLocalJumps & Jump.Break) { + if (state.nonLocalJumps! & Jump.Break) { statements.push( createIf( createBinary( @@ -2955,8 +2953,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, @@ -2983,7 +2981,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; } @@ -3041,21 +3039,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: @@ -3078,7 +3076,7 @@ namespace ts { receiver, visitNode(property.name, visitor, isPropertyName) ), - visitNode(property.initializer, visitor, isExpression) + visitNode(property.initializer!, visitor, isExpression) ); setTextRange(expression, property); if (startsOnNewLine) { @@ -3137,12 +3135,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, @@ -3199,7 +3197,7 @@ namespace ts { convertedLoopState = undefined; const ancestorFacts = enterSubtree(HierarchyFacts.FunctionExcludes, HierarchyFacts.FunctionIncludes); let updated: AccessorDeclaration; - if (node.transformFlags & TransformFlags.ContainsCapturedLexicalThis) { + if (node.transformFlags! & TransformFlags.ContainsCapturedLexicalThis) { const parameters = visitParameterList(node.parameters, visitor, context); const body = transformFunctionBody(node); if (node.kind === SyntaxKind.GetAccessor) { @@ -3255,9 +3253,9 @@ namespace ts { * @param node An ArrayLiteralExpression node. */ function visitArrayLiteralExpression(node: ArrayLiteralExpression): Expression { - if (node.transformFlags & TransformFlags.ES2015) { + 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); } @@ -3272,7 +3270,7 @@ namespace ts { return visitTypeScriptClassWrapper(node); } - if (node.transformFlags & TransformFlags.ES2015) { + if (node.transformFlags! & TransformFlags.ES2015) { return visitCallExpressionWithPotentialCapturedThisAssignment(node, /*assignToCapturedThis*/ true); } @@ -3329,7 +3327,7 @@ namespace ts { // 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: @@ -3382,7 +3380,7 @@ namespace ts { } // Find the trailing 'return' statement (4) - while (!isReturnStatement(elementAt(funcStatements, classBodyEnd))) { + while (!isReturnStatement(elementAt(funcStatements, classBodyEnd)!)) { classBodyEnd--; } @@ -3439,7 +3437,7 @@ namespace ts { function visitCallExpressionWithPotentialCapturedThisAssignment(node: CallExpression, assignToCapturedThis: boolean): CallExpression | BinaryExpression { // We are here either because SuperKeyword was used somewhere in the expression, or // because we contain a SpreadElementExpression. - if (node.transformFlags & TransformFlags.ContainsSpread || + if (node.transformFlags! & TransformFlags.ContainsSpread || node.expression.kind === SyntaxKind.SuperKeyword || isSuperProperty(skipOuterExpressions(node.expression))) { @@ -3449,7 +3447,7 @@ namespace ts { } let resultingCall: CallExpression | BinaryExpression; - if (node.transformFlags & TransformFlags.ContainsSpread) { + if (node.transformFlags! & TransformFlags.ContainsSpread) { // [source] // f(...a, b) // x.m(...a, b) @@ -3512,7 +3510,7 @@ namespace ts { * @param node A NewExpression node. */ function visitNewExpression(node: NewExpression): LeftHandSideExpression { - if (node.transformFlags & TransformFlags.ContainsSpread) { + if (node.transformFlags! & TransformFlags.ContainsSpread) { // We are here because we contain a SpreadElementExpression. // [source] // new C(...a) @@ -3525,7 +3523,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, [] @@ -3579,7 +3577,7 @@ namespace ts { } // Rewrite using the pattern .concat(, , ...) - return createArrayConcat(segments.shift(), segments); + return createArrayConcat(segments.shift()!, segments); } } @@ -3640,7 +3638,7 @@ namespace ts { * @param node A string literal. */ function visitNumericLiteral(node: NumericLiteral) { - if (node.numericLiteralFlags & TokenFlags.BinaryOrOctalSpecifier) { + if (node.numericLiteralFlags! & TokenFlags.BinaryOrOctalSpecifier) { return setTextRange(createNumericLiteral(node.text), node); } return node; @@ -3658,7 +3656,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; @@ -3742,7 +3740,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; @@ -3929,14 +3927,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 +3965,7 @@ namespace ts { if (enabledSubstitutions & ES2015SubstitutionFlags.BlockScopedBindings && !isInternalName(node)) { const declaration = resolver.getReferencedDeclarationWithCollidingName(node); if (declaration && !(isClassLike(declaration) && isPartOfClassBody(declaration, node))) { - return setTextRange(getGeneratedNameForNode(getNameOfDeclaration(declaration)), node); + return setTextRange(getGeneratedNameForNode(getNameOfDeclaration(declaration)!), node); } } @@ -3976,7 +3973,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. @@ -4018,7 +4015,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; } @@ -4027,7 +4024,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/es2016.ts b/src/compiler/transformers/es2016.ts index a946899177621..089bc15df1e3a 100644 --- a/src/compiler/transformers/es2016.ts +++ b/src/compiler/transformers/es2016.ts @@ -17,7 +17,7 @@ namespace ts { } function visitor(node: Node): VisitResult { - if ((node.transformFlags & TransformFlags.ContainsES2016) === 0) { + if ((node.transformFlags! & TransformFlags.ContainsES2016) === 0) { return node; } switch (node.kind) { @@ -51,7 +51,7 @@ namespace ts { target = setTextRange( createElementAccess( setTextRange(createAssignment(expressionTemp, left.expression), left.expression), - setTextRange(createAssignment(argumentExpressionTemp, left.argumentExpression), left.argumentExpression) + setTextRange(createAssignment(argumentExpressionTemp, left.argumentExpression!), left.argumentExpression) ), left ); diff --git a/src/compiler/transformers/es2017.ts b/src/compiler/transformers/es2017.ts index 0c6b25cf0b524..a835fa38beba5 100644 --- a/src/compiler/transformers/es2017.ts +++ b/src/compiler/transformers/es2017.ts @@ -56,7 +56,7 @@ namespace ts { } function visitor(node: Node): VisitResult { - if ((node.transformFlags & TransformFlags.ContainsES2017) === 0) { + if ((node.transformFlags! & TransformFlags.ContainsES2017) === 0) { return node; } @@ -119,10 +119,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) { @@ -156,7 +156,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) @@ -168,7 +168,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) @@ -176,10 +176,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), @@ -315,10 +316,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) { @@ -356,7 +357,7 @@ namespace ts { const converted = setSourceMapRange( createAssignment( convertToAssignmentElementTarget(node.name), - node.initializer + node.initializer! ), node ); @@ -440,7 +441,7 @@ namespace ts { context, hasLexicalArguments, promiseConstructor, - transformAsyncFunctionBodyWorker(node.body) + transformAsyncFunctionBodyWorker(node.body!) ); const declarations = endLexicalEnvironment(); @@ -466,7 +467,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); @@ -561,7 +562,7 @@ namespace ts { function substituteElementAccessExpression(node: ElementAccessExpression) { if (node.expression.kind === SyntaxKind.SuperKeyword) { return createSuperAccessInAsyncMethod( - node.argumentExpression, + node.argumentExpression!, node ); } @@ -637,7 +638,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( @@ -651,7 +652,7 @@ namespace ts { ); // Mark this node as originally an async function - (generatorFunc.emitNode || (generatorFunc.emitNode = {})).flags |= EmitFlags.AsyncFunctionBody | EmitFlags.ReuseTempVariableScope; + (generatorFunc.emitNode || (generatorFunc.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 bc6ee13520f7f..ccdaa7286d507 100644 --- a/src/compiler/transformers/es5.ts +++ b/src/compiler/transformers/es5.ts @@ -100,7 +100,7 @@ namespace ts { function substitutePropertyAssignment(node: PropertyAssignment): PropertyAssignment { const literalName = isIdentifier(node.name) && trySubstituteReservedName(node.name); if (literalName) { - return updatePropertyAssignment(node, literalName, node.initializer); + return updatePropertyAssignment(node, literalName, node.initializer!); } return node; } @@ -112,7 +112,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 2b887c9e93b37..0ebff5369c133 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -58,7 +58,7 @@ namespace ts { } function visitorWorker(node: Node, noDestructuringValue: boolean): VisitResult { - if ((node.transformFlags & TransformFlags.ContainsESNext) === 0) { + if ((node.transformFlags! & TransformFlags.ContainsESNext) === 0) { return node; } @@ -184,7 +184,7 @@ namespace ts { } function visitObjectLiteralExpression(node: ObjectLiteralExpression): Expression { - if (node.transformFlags & TransformFlags.ContainsObjectSpread) { + if (node.transformFlags! & TransformFlags.ContainsObjectSpread) { // spread elements emit like so: // non-spread elements are chunked together into object literals, and then all are passed to __assign: // { a, ...o, b } => __assign({a}, o, {b}); @@ -224,7 +224,7 @@ namespace ts { * @param node A BinaryExpression node. */ function visitBinaryExpression(node: BinaryExpression, noDestructuringValue: boolean): Expression { - if (isDestructuringAssignment(node) && node.left.transformFlags & TransformFlags.ContainsObjectRest) { + if (isDestructuringAssignment(node) && node.left.transformFlags! & TransformFlags.ContainsObjectRest) { return flattenDestructuringAssignment( node, visitor, @@ -250,7 +250,7 @@ namespace ts { */ function visitVariableDeclaration(node: VariableDeclaration): VisitResult { // If we are here it is because the name contains a binding pattern with a rest somewhere in it. - if (isBindingPattern(node.name) && node.name.transformFlags & TransformFlags.ContainsObjectRest) { + if (isBindingPattern(node.name) && node.name.transformFlags! & TransformFlags.ContainsObjectRest) { return flattenDestructuringBinding( node, visitor, @@ -280,8 +280,8 @@ namespace ts { * * @param node A ForOfStatement. */ - function visitForOfStatement(node: ForOfStatement, outermostLabeledStatement: LabeledStatement): VisitResult { - if (node.initializer.transformFlags & TransformFlags.ContainsObjectRest) { + function visitForOfStatement(node: ForOfStatement, outermostLabeledStatement: LabeledStatement | undefined): VisitResult { + if (node.initializer.transformFlags! & TransformFlags.ContainsObjectRest) { node = transformForOfStatementWithObjectRest(node); } if (node.awaitModifier) { @@ -295,8 +295,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)) { @@ -332,8 +332,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)) { @@ -363,7 +363,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); @@ -468,7 +468,7 @@ namespace ts { } function visitParameter(node: ParameterDeclaration): ParameterDeclaration { - if (node.transformFlags & TransformFlags.ContainsObjectRest) { + if (node.transformFlags! & TransformFlags.ContainsObjectRest) { // Binding patterns are converted into a generated name and are // evaluated inside the function body. return updateParameter( @@ -543,7 +543,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, @@ -621,7 +621,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( @@ -636,8 +636,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) ) ) ) @@ -645,7 +645,7 @@ namespace ts { ); addRange(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. @@ -683,9 +683,9 @@ 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) { + if (parameter.transformFlags! & TransformFlags.ContainsObjectRest) { const temp = getGeneratedNameForNode(parameter); const declarations = flattenDestructuringBinding( parameter, @@ -793,7 +793,7 @@ namespace ts { function substituteElementAccessExpression(node: ElementAccessExpression) { if (node.expression.kind === SyntaxKind.SuperKeyword) { return createSuperAccessInAsyncMethod( - node.argumentExpression, + node.argumentExpression!, node ); } @@ -870,7 +870,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); @@ -919,7 +919,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 = {})).flags! |= EmitFlags.AsyncFunctionBody; return createCall( getHelperName("__asyncGenerator"), diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts index 1a4c82020c77c..c2e5fd42cf4f4 100644 --- a/src/compiler/transformers/generators.ts +++ b/src/compiler/transformers/generators.ts @@ -138,7 +138,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 { @@ -227,6 +227,7 @@ namespace ts { case Instruction.Yield: return "yield"; case Instruction.YieldStar: return "yield*"; case Instruction.Endfinally: return "endfinally"; + default: return undefined!; // TODO: GH#18217 } } @@ -254,18 +255,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 @@ -273,9 +274,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. @@ -283,19 +284,19 @@ 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 transformSourceFile; function transformSourceFile(node: SourceFile) { - if (node.isDeclarationFile || (node.transformFlags & TransformFlags.ContainsGenerator) === 0) { + if (node.isDeclarationFile || (node.transformFlags! & TransformFlags.ContainsGenerator) === 0) { return node; } @@ -318,10 +319,10 @@ namespace ts { else if (inGeneratorFunctionBody) { return visitJavaScriptInGeneratorFunctionBody(node); } - else if (transformFlags & TransformFlags.Generator) { + else if (transformFlags! & TransformFlags.Generator) { return visitGenerator(node); } - else if (transformFlags & TransformFlags.ContainsGenerator) { + else if (transformFlags! & TransformFlags.ContainsGenerator) { return visitEachChild(node, visitor, context); } else { @@ -376,10 +377,10 @@ namespace ts { case SyntaxKind.ReturnStatement: return visitReturnStatement(node); default: - if (node.transformFlags & TransformFlags.ContainsYield) { + if (node.transformFlags! & TransformFlags.ContainsYield) { return visitJavaScriptContainingYield(node); } - else if (node.transformFlags & (TransformFlags.ContainsGenerator | TransformFlags.ContainsHoistedDeclarationOrCompletion)) { + else if (node.transformFlags! & (TransformFlags.ContainsGenerator | TransformFlags.ContainsHoistedDeclarationOrCompletion)) { return visitEachChild(node, visitor, context); } else { @@ -444,7 +445,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( @@ -457,7 +458,7 @@ namespace ts { /*typeParameters*/ undefined, visitParameterList(node.parameters, visitor, context), /*type*/ undefined, - transformGeneratorFunctionBody(node.body) + transformGeneratorFunctionBody(node.body!) ), /*location*/ node ), @@ -619,8 +620,8 @@ namespace ts { * * @param node The node to visit. */ - function visitVariableStatement(node: VariableStatement): Statement { - if (node.transformFlags & TransformFlags.ContainsYield) { + function visitVariableStatement(node: VariableStatement): Statement | undefined { + if (node.transformFlags! & TransformFlags.ContainsYield) { transformAndEmitVariableDeclarationList(node.declarationList); return undefined; } @@ -659,13 +660,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); } } @@ -733,7 +735,7 @@ namespace ts { target = updateElementAccess(left, cacheExpression(visitNode((left).expression, visitor, isLeftHandSideExpression)), - cacheExpression(visitNode((left).argumentExpression, visitor, isExpression)) + cacheExpression(visitNode((left).argumentExpression!, visitor, isExpression)) ); break; @@ -938,9 +940,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); @@ -982,7 +984,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); @@ -1091,7 +1093,7 @@ namespace ts { * @param node The node to visit. */ function visitElementAccessExpression(node: ElementAccessExpression) { - if (containsYield(node.argumentExpression)) { + if (containsYield(node.argumentExpression!)) { // [source] // a = x[yield]; // @@ -1159,7 +1161,7 @@ namespace ts { cacheExpression(visitNode(target, visitor, isExpression)), thisArg, visitElements( - node.arguments, + node.arguments!, /*leadingElement*/ createVoidZero() ) ), @@ -1250,7 +1252,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); @@ -1264,7 +1266,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; } @@ -1285,7 +1287,7 @@ namespace ts { return setSourceMapRange( createAssignment( setSourceMapRange(getSynthesizedClone(node.name), node.name), - visitNode(node.initializer, visitor, isExpression) + visitNode(node.initializer!, visitor, isExpression) ), node ); @@ -1310,11 +1312,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); @@ -1870,7 +1872,7 @@ namespace ts { function transformAndEmitThrowStatement(node: ThrowStatement): void { emitThrow( - visitNode(node.expression, visitor, isExpression), + visitNode(node.expression!, visitor, isExpression), /*location*/ node ); } @@ -1910,7 +1912,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); } @@ -1926,8 +1928,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) { @@ -2014,7 +2016,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; } /** @@ -2030,11 +2032,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; } @@ -2045,25 +2047,25 @@ namespace ts { const block = peekBlock(); Debug.assert(block !== undefined, "beginBlock was never called."); - const index = blockActions.length; - blockActions[index] = BlockAction.Close; - blockOffsets[index] = operations ? operations.length : 0; - blocks[index] = block; - blockStack.pop(); - return block; + const index = blockActions!.length; + blockActions![index] = BlockAction.Close; + blockOffsets![index] = operations ? operations.length : 0; + blocks![index] = block!; + blockStack!.pop(); + return block!; } /** * 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; } @@ -2335,7 +2337,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; @@ -2411,8 +2413,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 = []; } @@ -2624,8 +2626,8 @@ namespace ts { const operationIndex = operations.length; operations[operationIndex] = code; - operationArguments[operationIndex] = args; - operationLocations[operationIndex] = location; + operationArguments![operationIndex] = args; + operationLocations![operationIndex] = location; } /** @@ -2873,9 +2875,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) { @@ -2887,11 +2889,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: @@ -2903,7 +2905,7 @@ namespace ts { withBlockStack.push(block); } else if (blockAction === BlockAction.Close) { - withBlockStack.pop(); + withBlockStack!.pop(); } break; // default: do nothing @@ -2929,7 +2931,7 @@ namespace ts { lastOperationWasAbrupt = false; lastOperationWasCompletion = false; - const opcode = operations[operationIndex]; + const opcode = operations![operationIndex]; if (opcode === OpCode.Nop) { return; } @@ -2937,12 +2939,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); @@ -2986,7 +2988,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)); } @@ -2996,7 +2998,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)); @@ -3008,7 +3010,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( @@ -3033,7 +3035,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( @@ -3058,7 +3060,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( @@ -3088,7 +3090,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( @@ -3117,7 +3119,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( @@ -3142,7 +3144,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 94e41af9c2890..a4aff0c494004 100644 --- a/src/compiler/transformers/jsx.ts +++ b/src/compiler/transformers/jsx.ts @@ -27,7 +27,7 @@ namespace ts { } function visitor(node: Node): VisitResult { - if (node.transformFlags & TransformFlags.ContainsJsx) { + if (node.transformFlags! & TransformFlags.ContainsJsx) { return visitorWorker(node); } else { @@ -54,7 +54,7 @@ namespace ts { } } - function transformJsxChildToExpression(node: JsxChild): Expression { + function transformJsxChildToExpression(node: JsxChild): Expression | undefined { switch (node.kind) { case SyntaxKind.JsxText: return visitJsxText(node); @@ -89,9 +89,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" @@ -123,7 +123,7 @@ namespace ts { const element = createExpressionForJsxElement( context.getEmitResolver().getJsxFactoryEntity(), - compilerOptions.reactNamespace, + compilerOptions.reactNamespace!, // TODO: GH#18217 tagName, objectProperties, mapDefined(children, transformJsxChildToExpression), @@ -141,7 +141,7 @@ namespace ts { function visitJsxOpeningFragment(node: JsxOpeningFragment, children: ReadonlyArray, isChild: boolean, location: TextRange) { const element = createExpressionForJsxFragment( context.getEmitResolver().getJsxFactoryEntity(), - compilerOptions.reactNamespace, + compilerOptions.reactNamespace!, // TODO: GH#18217 mapDefined(children, transformJsxChildToExpression), node, location @@ -164,7 +164,7 @@ namespace ts { return createPropertyAssignment(name, expression); } - function transformJsxAttributeInitializer(node: StringLiteral | JsxExpression) { + function transformJsxAttributeInitializer(node: StringLiteral | JsxExpression | undefined): Expression { if (node === undefined) { return createTrue(); } @@ -182,7 +182,7 @@ namespace ts { return visitJsxExpression(node); } else { - Debug.failBadSyntaxKind(node); + return Debug.failBadSyntaxKind(node); } } diff --git a/src/compiler/transformers/module/es2015.ts b/src/compiler/transformers/module/es2015.ts index 4f218e4fdcf11..aeb968b0d4be6 100644 --- a/src/compiler/transformers/module/es2015.ts +++ b/src/compiler/transformers/module/es2015.ts @@ -12,7 +12,7 @@ namespace ts { context.enableEmitNotification(SyntaxKind.SourceFile); context.enableSubstitution(SyntaxKind.Identifier); - let currentSourceFile: SourceFile; + let currentSourceFile: SourceFile | undefined; return transformSourceFile; function transformSourceFile(node: SourceFile) { @@ -107,7 +107,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 b55dc583aa93e..50619cfaec6fb 100644 --- a/src/compiler/transformers/module/module.ts +++ b/src/compiler/transformers/module/module.ts @@ -42,7 +42,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. @@ -57,7 +57,7 @@ namespace ts { * @param node The SourceFile node. */ function transformSourceFile(node: SourceFile) { - if (node.isDeclarationFile || !(isEffectiveExternalModule(node, compilerOptions) || node.transformFlags & TransformFlags.ContainsDynamicImport)) { + if (node.isDeclarationFile || !(isEffectiveExternalModule(node, compilerOptions) || node.transformFlags! & TransformFlags.ContainsDynamicImport)) { return node; } @@ -68,8 +68,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); } @@ -395,7 +395,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; @@ -528,7 +528,7 @@ namespace ts { function importCallExpressionVisitor(node: Expression): VisitResult { // This visitor does not need to descend into the tree if there is no dynamic import, // as export/import statements are only transformed at the top level of a file. - if (!(node.transformFlags & TransformFlags.ContainsDynamicImport)) { + if (!(node.transformFlags! & TransformFlags.ContainsDynamicImport)) { return node; } @@ -542,7 +542,7 @@ namespace ts { function visitImportCallExpression(node: ImportCall): Expression { const argument = visitNode(firstOrUndefined(node.arguments), importCallExpressionVisitor); - const containsLexicalThis = !!(node.transformFlags & TransformFlags.ContainsLexicalThis); + const containsLexicalThis = !!(node.transformFlags! & TransformFlags.ContainsLexicalThis); switch (compilerOptions.module) { case ModuleKind.AMD: return createImportCallExpressionAMD(argument, containsLexicalThis); @@ -554,7 +554,7 @@ namespace ts { } } - function createImportCallExpressionUMD(arg: Expression | undefined, containsLexicalThis: boolean): Expression { + function createImportCallExpressionUMD(arg: Expression, containsLexicalThis: boolean): Expression { // (function (factory) { // ... (regular UMD) // } @@ -711,7 +711,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) { @@ -825,7 +825,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, @@ -958,7 +958,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 @@ -978,7 +978,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( @@ -1021,7 +1021,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( @@ -1062,12 +1062,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. @@ -1133,7 +1133,7 @@ namespace ts { ), /*location*/ node.name ), - visitNode(node.initializer, importCallExpressionVisitor) + visitNode(node.initializer!, importCallExpressionVisitor) ); } } @@ -1152,7 +1152,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); } @@ -1465,9 +1465,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 d4bae7230521d..2163561824c47 100644 --- a/src/compiler/transformers/module/system.ts +++ b/src/compiler/transformers/module/system.ts @@ -31,7 +31,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. @@ -39,9 +39,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 transformSourceFile; @@ -51,7 +51,7 @@ namespace ts { * @param node The SourceFile node. */ function transformSourceFile(node: SourceFile) { - if (node.isDeclarationFile || !(isEffectiveExternalModule(node, compilerOptions) || node.transformFlags & TransformFlags.ContainsDynamicImport)) { + if (node.isDeclarationFile || !(isEffectiveExternalModule(node, compilerOptions) || node.transformFlags! & TransformFlags.ContainsDynamicImport)) { return node; } @@ -130,12 +130,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); } @@ -263,7 +263,7 @@ namespace ts { // - Temporary variables will appear at the top rather than at the bottom of the file addRange(statements, endLexicalEnvironment()); - const exportStarFunction = addExportStarIfNeeded(statements); + const exportStarFunction = addExportStarIfNeeded(statements)!; // TODO: GH#18217 const moduleObject = createObjectLiteral([ createPropertyAssignment("setters", createSettersArray(exportStarFunction, dependencyGroups) @@ -468,7 +468,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) { @@ -594,9 +594,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)) { @@ -619,13 +619,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); @@ -698,7 +698,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); @@ -749,7 +749,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) { @@ -761,7 +761,7 @@ namespace ts { } } - let statements: Statement[]; + let statements: Statement[] | undefined; if (expressions) { statements = append(statements, setTextRange(createStatement(inlineExpressions(expressions)), node)); } @@ -858,7 +858,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))) @@ -879,9 +879,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); } @@ -926,7 +926,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; } @@ -968,7 +968,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; } @@ -1024,7 +1024,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); @@ -1050,9 +1050,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); } @@ -1219,7 +1219,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) @@ -1287,12 +1287,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) { @@ -1465,14 +1461,14 @@ namespace ts { * @param node The node to visit. */ function destructuringAndImportCallVisitor(node: Node): VisitResult { - if (node.transformFlags & TransformFlags.DestructuringAssignment + if (node.transformFlags! & TransformFlags.DestructuringAssignment && node.kind === SyntaxKind.BinaryExpression) { return visitDestructuringAssignment(node); } else if (isImportCall(node)) { return visitImportCallExpression(node); } - else if ((node.transformFlags & TransformFlags.ContainsDestructuringAssignment) || (node.transformFlags & TransformFlags.ContainsDynamicImport)) { + else if ((node.transformFlags! & TransformFlags.ContainsDestructuringAssignment) || (node.transformFlags! & TransformFlags.ContainsDynamicImport)) { return visitEachChild(node, destructuringAndImportCallVisitor, context); } else { @@ -1542,7 +1538,7 @@ namespace ts { return hasExportedReferenceInDestructuringTarget(node.name); } else if (isPropertyAssignment(node)) { - return hasExportedReferenceInDestructuringTarget(node.initializer); + return hasExportedReferenceInDestructuringTarget(node.initializer!); } else if (isIdentifier(node)) { const container = resolver.getReferencedExportContainer(node); @@ -1596,9 +1592,9 @@ namespace ts { previousOnEmitNode(hint, node, emitCallback); - currentSourceFile = undefined; - moduleInfo = undefined; - exportFunction = undefined; + currentSourceFile = undefined!; + moduleInfo = undefined!; + exportFunction = undefined!; noSubstitution = undefined; } else { @@ -1839,7 +1835,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 059ae73ea2bfa..fd4dc7b7a1ff9 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -66,7 +66,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. @@ -109,7 +109,7 @@ namespace ts { const visited = saveStateAndInvoke(node, visitSourceFile); addEmitHelpers(visited, context.readEmitHelpers()); - currentSourceFile = undefined; + currentSourceFile = undefined!; return visited; } @@ -188,11 +188,11 @@ namespace ts { * @param node The node to visit. */ function visitorWorker(node: Node): VisitResult { - if (node.transformFlags & TransformFlags.TypeScript) { + if (node.transformFlags! & TransformFlags.TypeScript) { // This node is explicitly marked as TypeScript, so we should transform the node. return visitTypeScript(node); } - else if (node.transformFlags & TransformFlags.ContainsTypeScript) { + else if (node.transformFlags! & TransformFlags.ContainsTypeScript) { // This node contains TypeScript, so we should visit its children. return visitEachChild(node, visitor, context); } @@ -233,7 +233,7 @@ namespace ts { // As the type information we would attempt to lookup to perform ellision is potentially unavailable for the synthesized nodes // We do not reuse `visitorWorker`, as the ellidable statement syntax kinds are technically unrecognized by the switch-case in `visitTypeScript`, // and will trigger debug failures when debug verbosity is turned up - if (node.transformFlags & TransformFlags.ContainsTypeScript) { + if (node.transformFlags! & TransformFlags.ContainsTypeScript) { // This node contains TypeScript, so we should visit its children. return visitEachChild(node, visitor, context); } @@ -277,12 +277,12 @@ namespace ts { // do not emit ES6 imports and exports since they are illegal inside a namespace return undefined; } - else if (node.transformFlags & TransformFlags.TypeScript || hasModifier(node, ModifierFlags.Export)) { + else if (node.transformFlags! & TransformFlags.TypeScript || hasModifier(node, ModifierFlags.Export)) { // This node is explicitly marked as TypeScript, or is exported at the namespace // level, so we should transform the node. return visitTypeScript(node); } - else if (node.transformFlags & TransformFlags.ContainsTypeScript) { + else if (node.transformFlags! & TransformFlags.ContainsTypeScript) { // This node contains TypeScript, so we should visit its children. return visitEachChild(node, visitor, context); } @@ -612,7 +612,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; @@ -710,7 +710,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} // } @@ -746,7 +746,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. // @@ -900,7 +900,7 @@ namespace ts { // record an alias as the class name is not in scope for statics. enableSubstitutionForClassAliases(); const alias = getSynthesizedClone(temp); - alias.autoGenerateFlags &= ~GeneratedIdentifierFlags.ReservedInNestedScopes; + alias.autoGenerateFlags! &= ~GeneratedIdentifierFlags.ReservedInNestedScopes; classAliases[getOriginalNodeId(node)] = alias; } @@ -948,7 +948,7 @@ namespace ts { // If there is a property assignment, we need to emit constructor whether users define it or not // If there is no property assignment, we can omit constructor if users do not define it const hasInstancePropertyWithInitializer = forEach(node.members, isInstanceInitializedProperty); - const hasParameterPropertyAssignments = node.transformFlags & TransformFlags.ContainsParameterPropertyAssignments; + const hasParameterPropertyAssignments = node.transformFlags! & TransformFlags.ContainsParameterPropertyAssignments; const constructor = getFirstConstructorWithBody(node); // If the class does not contain nodes that require a synthesized constructor, @@ -985,7 +985,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 @@ -1013,7 +1013,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; @@ -1068,7 +1068,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. @@ -1077,7 +1077,7 @@ namespace ts { createBlock( setTextRange( createNodeArray(statements), - /*location*/ constructor ? constructor.body.statements : node.members + /*location*/ constructor ? constructor.body!.statements : node.members ), /*multiLine*/ true ), @@ -1250,7 +1250,7 @@ namespace ts { const propertyName = isComputedPropertyName(property.name) && !isSimpleInlineableExpression(property.name.expression) ? updateComputedPropertyName(property.name, getGeneratedNameForNode(property.name, !hasModifier(property, ModifierFlags.Static))) : 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); @@ -1303,8 +1303,8 @@ namespace ts { * A structure describing the decorators for a class element. */ interface AllDecorators { - decorators: ReadonlyArray; - parameters?: ReadonlyArray>; + decorators: ReadonlyArray | undefined; + parameters?: ReadonlyArray | undefined>; } /** @@ -1313,8 +1313,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++) { @@ -1338,7 +1338,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) { @@ -1357,7 +1357,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: @@ -1380,13 +1380,13 @@ 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; } const { firstAccessor, secondAccessor, setAccessor } = getAllAccessorDeclarations(node.members, accessor); - const firstAccessorWithDecorators = firstAccessor.decorators ? firstAccessor : secondAccessor && secondAccessor.decorators ? secondAccessor : undefined; + const firstAccessorWithDecorators = firstAccessor!.decorators ? firstAccessor : secondAccessor && secondAccessor.decorators ? secondAccessor : undefined; if (!firstAccessorWithDecorators || accessor !== firstAccessorWithDecorators) { return undefined; } @@ -1405,7 +1405,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; } @@ -1424,7 +1424,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; @@ -1440,7 +1440,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; } @@ -1474,7 +1474,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) { @@ -1608,7 +1608,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) { @@ -1656,7 +1656,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)))); } @@ -1821,7 +1821,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"); } @@ -1907,7 +1907,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 @@ -2089,7 +2089,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) @@ -2109,7 +2109,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); @@ -2131,13 +2131,13 @@ 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 if (some(pendingExpressions)) { - expr = inlineExpressions([...pendingExpressions, expr]); - pendingExpressions.length = 0; + expr = inlineExpressions([...pendingExpressions!, expr]); + pendingExpressions!.length = 0; } return updateComputedPropertyName(name as ComputedPropertyName, expr); } @@ -2155,7 +2155,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( @@ -2442,7 +2442,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) { @@ -2480,7 +2480,7 @@ namespace ts { return setTextRange( createAssignment( getNamespaceMemberNameWithSourceMapsAndWithoutComments(name), - visitNode(node.initializer, visitor, isExpression) + visitNode(node.initializer!, visitor, isExpression) ), /*location*/ node ); @@ -2739,7 +2739,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); } /** @@ -2957,8 +2957,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; @@ -2975,7 +2975,7 @@ namespace ts { } } - const moduleBlock = getInnerMostModuleDeclarationFromDottedModule(node).body; + const moduleBlock = getInnerMostModuleDeclarationFromDottedModule(node)!.body; statementsLocation = moveRangePos(moduleBlock.statements, -1); } @@ -3019,8 +3019,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; } @@ -3111,7 +3111,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)) { @@ -3467,7 +3467,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 @@ -3477,7 +3477,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); @@ -3491,7 +3491,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 @@ -3531,7 +3531,7 @@ namespace ts { if (!compilerOptions.removeComments) { const propertyName = isPropertyAccessExpression(node) ? declarationNameToString(node.name) - : getTextOfNode(node.argumentExpression); + : getTextOfNode(node.argumentExpression!); addSyntheticTrailingComment(substitute, SyntaxKind.MultiLineCommentTrivia, ` ${propertyName} `); } @@ -3542,7 +3542,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 f7d28d6b4fc3c..26749fa96f4ba 100644 --- a/src/compiler/transformers/utilities.ts +++ b/src/compiler/transformers/utilities.ts @@ -10,7 +10,7 @@ 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* } @@ -23,22 +23,22 @@ namespace ts { return names.elements.length; } - 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 getImportNeedsImportStarHelper(node: ImportDeclaration) { - return !!getNamespaceDeclarationNode(node) || (getNamedImportCount(node) > 1 && containsDefaultReference(node.importClause.namedBindings)); + return !!getNamespaceDeclarationNode(node) || (getNamedImportCount(node) > 1 && containsDefaultReference(node.importClause!.namedBindings)); } export function getImportNeedsImportDefaultHelper(node: ImportDeclaration) { - return isDefaultImport(node) || (getNamedImportCount(node) === 1 && containsDefaultReference(node.importClause.namedBindings)); + return isDefaultImport(node) || (getNamedImportCount(node) === 1 && containsDefaultReference(node.importClause!.namedBindings)); } export function collectExternalModuleInfo(sourceFile: SourceFile, resolver: EmitResolver, compilerOptions: CompilerOptions): ExternalModuleInfo { @@ -46,9 +46,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 = undefined; + let exportEquals: ExportAssignment | undefined; let hasExportStarsToExportValues = false; let hasImportStarOrImportDefault = false; @@ -85,7 +85,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); @@ -130,7 +130,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); @@ -178,7 +178,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/types.ts b/src/compiler/types.ts index 0e1f08a69d840..06200e2062551 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -554,7 +554,7 @@ namespace ts { 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 */ locals?: SymbolTable; // Locals associated with node (initialized by binding) @@ -769,13 +769,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; @@ -820,7 +820,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 @@ -829,13 +829,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 @@ -845,7 +845,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 @@ -890,7 +890,7 @@ namespace ts { kind: SyntaxKind.PropertyAssignment; name: PropertyName; questionToken?: QuestionToken; - initializer: Expression; + initializer: Expression | undefined; } export interface ShorthandPropertyAssignment extends ObjectLiteralElement, JSDocContainer { @@ -929,13 +929,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; } @@ -985,7 +985,7 @@ namespace ts { export interface MethodSignature extends SignatureDeclarationBase, TypeElement { kind: SyntaxKind.MethodSignature; - parent?: ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode; + parent: ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode; name: PropertyName; } @@ -1000,14 +1000,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; } @@ -1015,14 +1015,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; } @@ -1031,7 +1031,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; } @@ -1040,7 +1040,7 @@ namespace ts { export interface IndexSignatureDeclaration extends SignatureDeclarationBase, ClassElement, TypeElement { kind: SyntaxKind.IndexSignature; - parent?: ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode; + parent: ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode; } export interface TypeNode extends Node { @@ -1085,7 +1085,7 @@ namespace ts { export interface TypePredicateNode extends TypeNode { kind: SyntaxKind.TypePredicate; - parent?: SignatureDeclaration; + parent: SignatureDeclaration; parameterName: Identifier | ThisTypeNode; type: TypeNode; } @@ -1577,17 +1577,17 @@ namespace ts { 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; @@ -1602,7 +1602,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; } @@ -1621,7 +1621,7 @@ namespace ts { export interface SpreadElement extends Expression { kind: SyntaxKind.SpreadElement; - parent?: ArrayLiteralExpression | CallExpression | NewExpression; + parent: ArrayLiteralExpression | CallExpression | NewExpression; expression: Expression; } @@ -1692,7 +1692,7 @@ namespace ts { export interface ExpressionWithTypeArguments extends TypeNode { kind: SyntaxKind.ExpressionWithTypeArguments; - parent?: HeritageClause; + parent: HeritageClause; expression: LeftHandSideExpression; typeArguments?: NodeArray; } @@ -1755,13 +1755,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; attributes: JsxAttributes; } @@ -1784,18 +1784,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; @@ -1803,19 +1803,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; } @@ -1823,7 +1823,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; @@ -1975,20 +1975,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; } @@ -2002,7 +2002,7 @@ namespace ts { export interface ThrowStatement extends Statement { kind: SyntaxKind.ThrowStatement; - expression: Expression; + expression: Expression | undefined; } export interface TryStatement extends Statement { @@ -2014,7 +2014,7 @@ namespace ts { export interface CatchClause extends Node { kind: SyntaxKind.CatchClause; - parent?: TryStatement; + parent: TryStatement; variableDeclaration?: VariableDeclaration; block: Block; } @@ -2062,7 +2062,7 @@ namespace ts { export interface HeritageClause extends Node { kind: SyntaxKind.HeritageClause; - parent?: InterfaceDeclaration | ClassLikeDeclaration; + parent: InterfaceDeclaration | ClassLikeDeclaration; token: SyntaxKind.ExtendsKeyword | SyntaxKind.ImplementsKeyword; types: NodeArray; } @@ -2076,7 +2076,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; @@ -2095,7 +2095,7 @@ namespace ts { export interface ModuleDeclaration extends DeclarationStatement, JSDocContainer { kind: SyntaxKind.ModuleDeclaration; - parent?: ModuleBody | SourceFile; + parent: ModuleBody | SourceFile; name: ModuleName; body?: ModuleBody | JSDocNamespaceDeclaration; } @@ -2111,12 +2111,12 @@ namespace ts { export interface JSDocNamespaceDeclaration extends ModuleDeclaration { name: Identifier; - body: JSDocNamespaceBody; + body: JSDocNamespaceBody | undefined; } export interface ModuleBlock extends Node, Statement { kind: SyntaxKind.ModuleBlock; - parent?: ModuleDeclaration; + parent: ModuleDeclaration; statements: NodeArray; } @@ -2129,7 +2129,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 @@ -2139,7 +2139,7 @@ namespace ts { export interface ExternalModuleReference extends Node { kind: SyntaxKind.ExternalModuleReference; - parent?: ImportEqualsDeclaration; + parent: ImportEqualsDeclaration; expression?: Expression; } @@ -2149,7 +2149,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; @@ -2165,14 +2165,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; } @@ -2183,7 +2183,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. */ @@ -2192,13 +2192,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; } @@ -2206,14 +2206,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 } @@ -2226,7 +2226,7 @@ namespace ts { */ export interface ExportAssignment extends DeclarationStatement { kind: SyntaxKind.ExportAssignment; - parent?: SourceFile; + parent: SourceFile; isExportEquals?: boolean; expression: Expression; } @@ -2298,7 +2298,7 @@ namespace ts { export interface JSDoc extends Node { kind: SyntaxKind.JSDocComment; - parent?: HasJSDoc; + parent: HasJSDoc; tags: NodeArray | undefined; comment: string | undefined; } @@ -2334,12 +2334,12 @@ namespace ts { export interface JSDocReturnTag extends JSDocTag { kind: SyntaxKind.JSDocReturnTag; - typeExpression: JSDocTypeExpression; + typeExpression: JSDocTypeExpression | undefined; } export interface JSDocTypeTag extends JSDocTag { kind: SyntaxKind.JSDocTypeTag; - typeExpression: JSDocTypeExpression; + typeExpression: JSDocTypeExpression | undefined; } export interface JSDocTypedefTag extends JSDocTag, NamedDeclaration { @@ -2421,7 +2421,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, @@ -2464,7 +2464,7 @@ namespace ts { export interface AmdDependency { path: string; - name: string; + name: string | undefined; } /* @internal */ @@ -2506,7 +2506,7 @@ namespace ts { /* @internal */ redirectInfo?: RedirectInfo | undefined; amdDependencies: ReadonlyArray; - moduleName: string; + moduleName: string | undefined; referencedFiles: ReadonlyArray; typeReferenceDirectives: ReadonlyArray; languageVariant: LanguageVariant; @@ -2530,9 +2530,9 @@ namespace ts { /* @internal */ scriptKind: ScriptKind; // The first node that causes this file to be an external module - /* @internal */ externalModuleIndicator: Node; + /* @internal */ externalModuleIndicator: Node | undefined; // The first node that causes this file to be a CommonJS module - /* @internal */ commonJsModuleIndicator: Node; + /* @internal */ commonJsModuleIndicator: Node | undefined; /* @internal */ identifiers: Map; // Map from a string to an interned string /* @internal */ nodeCount: number; @@ -2559,7 +2559,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 | undefined; /* @internal */ resolvedTypeReferenceDirectiveNames: Map; /* @internal */ imports: ReadonlyArray; // Identifier only if `declare global` @@ -2618,6 +2618,7 @@ namespace ts { throwIfCancellationRequested(): void; } + // TODO: This should implement TypeCheckerHost but that's an internal type. export interface Program extends ScriptReferenceHost { /** @@ -2761,7 +2762,7 @@ namespace ts { getCompilerOptions(): CompilerOptions; getSourceFiles(): ReadonlyArray; - getSourceFile(fileName: string): SourceFile; + getSourceFile(fileName: string): SourceFile | undefined; getResolvedTypeReferenceDirectives(): ReadonlyMap; } @@ -2785,8 +2786,9 @@ 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; + 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} | undefined; /** Note that the resulting nodes cannot be checked. */ @@ -2817,7 +2819,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; @@ -2839,15 +2841,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: FunctionLike): boolean | undefined; isUndefinedSymbol(symbol: Symbol): boolean; @@ -2862,7 +2865,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[]; @@ -2897,10 +2900,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, @@ -2911,7 +2914,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; @@ -3177,9 +3180,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; @@ -3187,7 +3190,7 @@ namespace ts { getNodeCheckFlags(node: Node): NodeCheckFlags; isDeclarationVisible(node: Declaration): boolean; isLateBound(node: Declaration): node is LateBoundDeclaration; - collectLinkedAliases(node: Identifier): Node[]; + collectLinkedAliases(node: Identifier): Node[] | undefined; isImplementationOfOverload(node: FunctionLikeDeclaration): boolean | undefined; isRequiredInitializedParameter(node: ParameterDeclaration): boolean; isOptionalUninitializedParameterProperty(node: ParameterDeclaration): boolean; @@ -3197,15 +3200,15 @@ namespace ts { isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags, 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): SourceFile; - getTypeReferenceDirectivesForEntityName(name: EntityNameOrEntityNameExpression): string[]; - getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags): string[]; + getExternalModuleFileFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration): SourceFile | undefined; + getTypeReferenceDirectivesForEntityName(name: EntityNameOrEntityNameExpression): string[] | undefined; + getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags): string[] | undefined; isLiteralConstDeclaration(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration): boolean; writeLiteralConstValue(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration, writer: EmitTextWriter): void; getJsxFactoryEntity(): EntityName; @@ -3638,25 +3641,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 | undefined; // Declared string indexing info + declaredNumberIndexInfo: IndexInfo | undefined; // Declared numeric indexing info } /** @@ -3744,12 +3747,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 */ @@ -3825,7 +3828,7 @@ namespace ts { trueType: Type; falseType: Type; /* @internal */ - inferTypeParameters: TypeParameter[]; + inferTypeParameters: TypeParameter[] | undefined; /* @internal */ target?: ConditionalType; /* @internal */ @@ -3907,13 +3910,13 @@ namespace ts { } 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 | undefined; // Cache for resolved inferred type + priority: InferencePriority | undefined; // Priority of current inference set + topLevel: boolean; // True if all inferences are to top level occurrences + isFixed: boolean; // True if inferences are fixed } export const enum InferenceFlags { @@ -3950,7 +3953,7 @@ namespace ts { /* @internal */ export interface WideningContext { - parent?: WideningContext; // Parent context + parent: WideningContext | undefined; // Parent context propertyName?: __String; // Name of property in parent siblings?: Type[]; // Types of siblings resolvedPropertyNames?: __String[]; // Property names occurring in sibling object literals @@ -4106,7 +4109,7 @@ namespace ts { suppressExcessPropertyErrors?: boolean; suppressImplicitAnyIndexErrors?: boolean; /* @internal */ suppressOutputPathCheck?: boolean; - target?: ScriptTarget; + target?: ScriptTarget; // TODO: GH#18217 frequently asserted as defined traceResolution?: boolean; types?: string[]; /** Paths used to compute primary types search locations */ @@ -4211,17 +4214,17 @@ namespace ts { /* @internal */ export interface ConfigFileSpecs { - filesSpecs: ReadonlyArray; + filesSpecs: ReadonlyArray | undefined; /** * Present to report errors (user specified specs), validatedIncludeSpecs are used for file name matching */ - includeSpecs: ReadonlyArray; + includeSpecs: ReadonlyArray | undefined; /** * Present to report errors (user specified specs), validatedExcludeSpecs are used for file name matching */ - excludeSpecs: ReadonlyArray; - validatedIncludeSpecs: ReadonlyArray; - validatedExcludeSpecs: ReadonlyArray; + excludeSpecs: ReadonlyArray | undefined; + validatedIncludeSpecs: ReadonlyArray | undefined; + validatedExcludeSpecs: ReadonlyArray | undefined; wildcardDirectories: MapLike; } @@ -4409,6 +4412,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 @@ -4498,7 +4503,7 @@ namespace ts { } export interface ResolvedTypeReferenceDirectiveWithFailedLookupLocations { - readonly resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective; + readonly resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective | undefined; readonly failedLookupLocations: ReadonlyArray; } @@ -4529,7 +4534,7 @@ 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)[]; + resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[]; getEnvironmentVariable?(name: string): string; /* @internal */ onReleaseOldSourceFile?(oldSourceFile: SourceFile, oldOptions: CompilerOptions): void; /* @internal */ hasInvalidatedResolution?: HasInvalidatedResolution; @@ -4639,7 +4644,7 @@ namespace ts { 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 @@ -4770,7 +4775,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; @@ -4897,7 +4902,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): void; } @@ -4926,7 +4931,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, @@ -4945,12 +4950,12 @@ 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*/ onEmitHelpers?: (node: Node, writeLines: (text: string) => void) => 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 c6861380d8dd0..0315867aa5c1d 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -15,7 +15,7 @@ namespace ts { isTypeReferenceDirective?: boolean; } - 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) { @@ -112,7 +112,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 { @@ -127,7 +127,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); @@ -171,6 +171,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; @@ -241,7 +243,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; } @@ -249,7 +251,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); } @@ -291,7 +293,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 @@ -349,15 +351,15 @@ 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) { // If we don't need to downlevel and we can reach the original source text using // the node's parent reference, then simply get the text as it was originally written. - if (!nodeIsSynthesized(node) && node.parent && !(isNumericLiteral(node) && node.numericLiteralFlags & TokenFlags.ContainsSeparator)) { + if (!nodeIsSynthesized(node) && node.parent && !(isNumericLiteral(node) && node.numericLiteralFlags! & TokenFlags.ContainsSeparator)) { return getSourceTextOfNodeFromSourceFile(sourceFile, node); } @@ -388,7 +390,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) { @@ -439,7 +441,7 @@ namespace ts { /** Given a symbol for a module, checks that it is a shorthand ambient module. */ export function isShorthandAmbientModuleSymbol(moduleSymbol: Symbol): boolean { - return isShorthandAmbientModule(moduleSymbol.valueDeclaration); + return isShorthandAmbientModule(moduleSymbol.valueDeclaration!); } function isShorthandAmbientModule(node: Node): boolean { @@ -477,7 +479,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: @@ -498,7 +500,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; @@ -546,13 +548,11 @@ 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 { - let current = node.parent; - while (current) { - if (isBlockScope(current, current.parent)) { - return current; + while (true) { + node = node.parent; + if (isBlockScope(node, node.parent)) { + return node; } - - current = current.parent; } } @@ -575,7 +575,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); } @@ -589,6 +589,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); } } @@ -667,7 +669,7 @@ namespace ts { case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: case SyntaxKind.TypeAliasDeclaration: - errorNode = (node).name; + errorNode = (node).name!; break; case SyntaxKind.ArrowFunction: return getErrorSpanForArrowFunction(sourceFile, node); @@ -788,8 +790,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; } @@ -834,6 +836,7 @@ namespace ts { // TODO (drosen): TaggedTemplateExpressions may eventually support type arguments. return false; } + } } return false; @@ -851,11 +854,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); @@ -926,7 +929,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; } @@ -992,7 +995,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); @@ -1004,7 +1007,7 @@ namespace ts { } } - export function isFunctionBlock(node: Node) { + export function isFunctionBlock(node: Node): boolean { return node && node.kind === SyntaxKind.Block && isFunctionLike(node.parent); } @@ -1030,24 +1033,26 @@ 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 getContainingFunction(node: Node): FunctionLike { + export function getContainingFunction(node: Node): FunctionLike | 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: @@ -1167,7 +1172,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; @@ -1199,7 +1204,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; @@ -1240,22 +1245,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; @@ -1266,14 +1271,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; @@ -1281,15 +1286,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) { @@ -1357,7 +1364,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: @@ -1412,7 +1419,7 @@ namespace ts { export function getExternalModuleImportEqualsDeclarationExpression(node: Node) { Debug.assert(isExternalModuleImportEqualsDeclaration(node)); - return ((node).moduleReference).expression; + return ((node).moduleReference).expression!; } export function isInternalModuleImportEqualsDeclaration(node: Node): node is ImportEqualsDeclaration { @@ -1424,11 +1431,11 @@ namespace ts { } export function isInJavaScriptFile(node: Node | undefined): boolean { - return node && !!(node.flags & NodeFlags.JavaScriptFile); + return !!node && !!(node.flags & NodeFlags.JavaScriptFile); } 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) { @@ -1475,10 +1482,11 @@ namespace ts { * Returns true if the node is a variable declaration whose initializer is a function or class expression. * This function does not test if the node is in a JavaScript file or not. */ - export function isDeclarationOfFunctionOrClassExpression(s: Symbol) { + // TODO: Would like to return `s is Symbol & { valueDeclaration: { initializer: Expression } }` but it causes long (at least 5min) compile times + export function isDeclarationOfFunctionOrClassExpression(s: Symbol): boolean { if (s.valueDeclaration && s.valueDeclaration.kind === SyntaxKind.VariableDeclaration) { const declaration = s.valueDeclaration as VariableDeclaration; - return declaration.initializer && (declaration.initializer.kind === SyntaxKind.FunctionExpression || declaration.initializer.kind === SyntaxKind.ClassExpression); + return !!declaration.initializer && (declaration.initializer.kind === SyntaxKind.FunctionExpression || declaration.initializer.kind === SyntaxKind.ClassExpression); } return false; } @@ -1551,7 +1559,7 @@ namespace ts { !!getJSDocTypeTag(expr.parent); } - export function getExternalModuleName(node: Node): Expression { + export function getExternalModuleName(node: Node): Expression | undefined { if (node.kind === SyntaxKind.ImportDeclaration) { return (node).moduleSpecifier; } @@ -1569,7 +1577,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); @@ -1610,11 +1618,12 @@ namespace ts { ((node as JSDocFunctionType).parameters[0].name as Identifier).escapedText === "new"; } - 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 getSingleInitializerOfVariableStatementOrPropertyDeclaration(node: Node): Expression | undefined { @@ -1628,16 +1637,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(node: Node): ReadonlyArray { @@ -1673,8 +1681,11 @@ namespace ts { result = addRange(result, getJSDocParameterTags(node as ParameterDeclaration)); } - if (isVariableLike(node) && hasInitializer(node) && hasJSDocNodes(node.initializer)) { - result = addRange(result, node.initializer.jsDoc); + if (isVariableLike(node) && hasInitializer(node)) { + const initializer = node.initializer!; + if (hasJSDocNodes(initializer)) { + result = addRange(result, initializer.jsDoc); + } } if (hasJSDocNodes(node)) { @@ -1711,19 +1722,19 @@ namespace ts { } export function getJSDocHost(node: JSDocTag): HasJSDoc { - Debug.assert(node.parent!.kind === SyntaxKind.JSDocComment); - return node.parent!.parent!; + Debug.assert(node.parent.kind === SyntaxKind.JSDocComment); + return node.parent.parent; } export function getTypeParameterFromJsDoc(node: TypeParameterDeclaration & { parent: JSDocTemplateTag }): TypeParameterDeclaration | undefined { const name = node.name.escapedText; const { typeParameters } = (node.parent.parent.parent as ts.SignatureDeclaration | ts.InterfaceDeclaration | ts.ClassDeclaration); - return find(typeParameters, p => p.name.escapedText === name); + return find(typeParameters!, p => p.name.escapedText === name); } export function hasRestParameter(s: SignatureDeclaration): boolean { const last = lastOrUndefined(s.parameters); - return last && isRestParameter(last); + return !!last && isRestParameter(last); } export function isRestParameter(node: ParameterDeclaration): boolean { @@ -1865,8 +1876,10 @@ namespace ts { switch (name.kind) { case SyntaxKind.Identifier: case SyntaxKind.StringLiteral: - case SyntaxKind.NumericLiteral: - return isDeclaration(name.parent) && name.parent.name === name; + case SyntaxKind.NumericLiteral: { + const parent = name.parent; + return isDeclaration(parent) && parent.name === name; + } default: return false; } @@ -1877,12 +1890,14 @@ 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; } - const binExp = name.parent.parent; + const binExp = parent.parent; return isBinaryExpression(binExp) && getSpecialPropertyAssignmentKind(binExp) !== SpecialPropertyAssignmentKind.None && getNameOfDeclaration(binExp) === name; + } default: return false; } @@ -1967,7 +1982,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) { @@ -1996,7 +2011,7 @@ namespace ts { return undefined; } - export function getFileReferenceFromReferencePath(comment: string, commentRange: CommentRange): ReferencePathMatchResult { + export function getFileReferenceFromReferencePath(comment: string, commentRange: CommentRange): ReferencePathMatchResult | undefined { const simpleReferenceRegEx = /^\/\/\/\s*; - 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; let modificationCount = 0; @@ -2456,11 +2471,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); insertSorted(filesWithDiagnostics, diagnostic.file.fileName, compareStringsCaseSensitive); } @@ -2618,7 +2633,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); } } } @@ -2672,7 +2687,7 @@ namespace ts { return file.moduleName || getExternalModuleNameFromPath(host, file.fileName); } - export function getExternalModuleNameFromDeclaration(host: EmitHost, resolver: EmitResolver, declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration): string { + export function getExternalModuleNameFromDeclaration(host: EmitHost, resolver: EmitResolver, declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration): string | undefined { const file = resolver.getExternalModuleFileFromDeclaration(declaration); if (!file || file.isDeclarationFile) { return undefined; @@ -2716,8 +2731,8 @@ namespace ts { export interface EmitFileNames { jsFilePath: string; - sourceMapFilePath: string; - declarationFilePath: string; + sourceMapFilePath: string | undefined; + declarationFilePath: string | undefined; } /** @@ -2758,7 +2773,7 @@ namespace ts { return combinePaths(newDirPath, sourceFilePath); } - export function writeFile(host: EmitHost, diagnostics: DiagnosticCollection, fileName: string, data: string, writeByteOrderMark: boolean, sourceFiles?: ReadonlyArray) { + export function writeFile(host: EmitHost, diagnostics: DiagnosticCollection, fileName: string, data: string, writeByteOrderMark: boolean, sourceFiles: ReadonlyArray) { host.writeFile(fileName, data, writeByteOrderMark, hostErrorMessage => { diagnostics.add(createCompilerDiagnostic(Diagnostics.Could_not_write_file_0_Colon_1, fileName, hostErrorMessage)); }, sourceFiles); @@ -2772,9 +2787,9 @@ namespace ts { return computeLineAndCharacterOfPosition(lineMap, pos).line; } - export function getFirstConstructorWithBody(node: ClassLikeDeclaration): ConstructorDeclaration { + export function getFirstConstructorWithBody(node: ClassLikeDeclaration): ConstructorDeclaration | undefined { return forEach(node.members, member => { - if (member.kind === SyntaxKind.Constructor && nodeIsPresent((member).body)) { + if (member.kind === SyntaxKind.Constructor && nodeIsPresent((member).body!)) { return member; } }); @@ -2788,7 +2803,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; } @@ -2807,7 +2822,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 { @@ -2815,17 +2830,17 @@ namespace ts { } export interface AllAccessorDeclarations { - firstAccessor: AccessorDeclaration; - secondAccessor: AccessorDeclaration; - getAccessor: AccessorDeclaration; - setAccessor: AccessorDeclaration; + firstAccessor: AccessorDeclaration | undefined; + secondAccessor: AccessorDeclaration | undefined; + getAccessor: AccessorDeclaration | undefined; + setAccessor: AccessorDeclaration | undefined; } export function getAllAccessorDeclarations(declarations: NodeArray, accessor: AccessorDeclaration): AllAccessorDeclarations { - let firstAccessor: AccessorDeclaration; - let secondAccessor: AccessorDeclaration; - let getAccessor: AccessorDeclaration; - let setAccessor: AccessorDeclaration; + let firstAccessor: AccessorDeclaration | undefined; + let secondAccessor: AccessorDeclaration | undefined; + let getAccessor: AccessorDeclaration | undefined; + let setAccessor: AccessorDeclaration | undefined; if (hasDynamicName(accessor)) { firstAccessor = accessor; if (accessor.kind === SyntaxKind.GetAccessor) { @@ -2842,7 +2857,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) { @@ -2901,7 +2916,7 @@ namespace ts { * Gets the effective type parameters. If the node was parsed in a * JavaScript file, gets the type parameters from the `@template` tag from JSDoc. */ - export function getEffectiveTypeParameterDeclarations(node: DeclarationWithTypeParameters, checkJSDoc?: boolean): ReadonlyArray { + export function getEffectiveTypeParameterDeclarations(node: DeclarationWithTypeParameters, checkJSDoc?: boolean): ReadonlyArray | undefined { if (node.typeParameters) { return node.typeParameters; } @@ -2915,16 +2930,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, checkJSDoc?: boolean): TypeNode { + export function getEffectiveSetAccessorTypeAnnotationNode(node: SetAccessorDeclaration, checkJSDoc?: boolean): TypeNode | undefined { const parameter = getSetAccessorValueParameter(node); return parameter && getEffectiveTypeAnnotationNode(parameter, checkJSDoc); } - 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)) { @@ -2944,7 +2959,7 @@ namespace ts { text: string, lineMap: ReadonlyArray, writer: EmitTextWriter, - comments: ReadonlyArray, + comments: ReadonlyArray | undefined, leadingSeparator: boolean, trailingSeparator: boolean, newLine: string, @@ -2983,8 +2998,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: @@ -3002,7 +3017,7 @@ namespace ts { if (leadingComments) { const detachedComments: CommentRange[] = []; - let lastComment: CommentRange; + let lastComment: CommentRange | undefined; for (const comment of leadingComments) { if (lastComment) { @@ -3025,13 +3040,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 }; } } } @@ -3048,7 +3063,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 @@ -3162,8 +3177,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); @@ -3216,8 +3231,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; } @@ -3277,11 +3292,11 @@ namespace ts { } export function getLocalSymbolForExportDefault(symbol: Symbol) { - return isExportDefaultSymbol(symbol) ? symbol.declarations[0].localSymbol : undefined; + return isExportDefaultSymbol(symbol) ? symbol.declarations![0].localSymbol : undefined; } function isExportDefaultSymbol(symbol: Symbol): boolean { - return symbol && length(symbol.declarations) > 0 && hasModifier(symbol.declarations[0], ModifierFlags.Default); + return symbol && length(symbol.declarations) > 0 && hasModifier(symbol.declarations![0], ModifierFlags.Default); } /** Return ".ts", ".d.ts", or ".tsx", if that is the extension. */ @@ -3420,31 +3435,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); } @@ -3512,7 +3527,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) { @@ -3746,7 +3761,7 @@ namespace ts { } export function getClassLikeDeclarationOfSymbol(symbol: Symbol): Declaration | undefined { - return find(symbol.declarations, isClassLike); + return find(symbol.declarations!, isClassLike); } export function getObjectFlags(type: Type): ObjectFlags { @@ -3761,7 +3776,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]); } } @@ -3999,7 +4014,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) { @@ -4110,7 +4125,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); @@ -4127,7 +4142,7 @@ namespace ts { } // TODO: Add codePage support for readFile? - let fileContents = ""; + let fileContents: string | undefined = ""; try { fileContents = sys.readFile(filePath); } @@ -4138,9 +4153,9 @@ namespace ts { return false; } try { - ts.localizedDiagnosticMessages = JSON.parse(fileContents); + ts.localizedDiagnosticMessages = JSON.parse(fileContents!); } - catch (e) { + catch { if (errors) { errors.push(createCompilerDiagnostic(Diagnostics.Corrupted_locale_file_0, filePath)); } @@ -4153,7 +4168,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; @@ -4187,8 +4204,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; } @@ -4257,7 +4274,7 @@ namespace ts { case SyntaxKind.PropertyAccessExpression: return (expr as PropertyAccessExpression).name; case SyntaxKind.ElementAccessExpression: - const arg = (expr as ElementAccessExpression).argumentExpression; + const arg = (expr as ElementAccessExpression).argumentExpression!; if (isIdentifier(arg)) { return arg; } @@ -4279,8 +4296,8 @@ namespace ts { } } - function getDeclarationIdentifier(node: Declaration | Expression) { - const name = getNameOfDeclaration(node); + function getDeclarationIdentifier(node: Declaration | Expression): Identifier | undefined { + const name = getNameOfDeclaration(node)!; return isIdentifier(name) ? name : undefined; } @@ -4288,6 +4305,11 @@ namespace ts { return declaration.name || nameForNamelessJSDocTypedef(declaration); } + export function isNamedDeclaration(node: Node): node is NamedDeclaration & { name: DeclarationName } { + return !!(node as NamedDeclaration).name; + } + + // TODO: GH#18217 This is often used as if it returns a defined result export function getNameOfDeclaration(declaration: Declaration | Expression): DeclarationName | undefined { if (!declaration) { return undefined; @@ -4399,7 +4421,7 @@ namespace ts { * tag directly on the node would be returned. */ export function getJSDocType(node: Node): TypeNode | undefined { - let tag: JSDocTypeTag | JSDocParameterTag = getFirstJSDocTag(node, SyntaxKind.JSDocTypeTag) as JSDocTypeTag; + let tag: JSDocTypeTag | JSDocParameterTag | undefined = getFirstJSDocTag(node, SyntaxKind.JSDocTypeTag) as JSDocTypeTag; if (!tag && node.kind === SyntaxKind.Parameter) { const paramTags = getJSDocParameterTags(node as ParameterDeclaration); if (paramTags) { @@ -4422,7 +4444,7 @@ namespace ts { } /** Get all JSDoc tags related to a node, including those on parent nodes. */ - export function getJSDocTags(node: Node): ReadonlyArray | undefined { + export function getJSDocTags(node: Node): ReadonlyArray { let tags = (node as JSDocContainer).jsDocCache; // If cache is 'null', that means we did the work of searching for JSDoc tags and came up with nothing. if (tags === undefined) { @@ -5186,8 +5208,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 @@ -5386,7 +5407,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 @@ -5892,8 +5913,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 9c1462e7ec6a6..a74acd96e16a6 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -13,7 +13,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. @@ -23,9 +23,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; } @@ -36,7 +36,7 @@ namespace ts { return node; } - let visitedNode: Node; + let visitedNode: Node | undefined; if (visited === undefined) { return undefined; } @@ -48,7 +48,7 @@ namespace ts { } Debug.assertNode(visitedNode, test); - aggregateTransformFlags(visitedNode); + aggregateTransformFlags(visitedNode!); return visitedNode; } @@ -61,7 +61,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. @@ -88,7 +88,7 @@ namespace ts { return nodes; } - let updated: MutableNodeArray; + let updated: MutableNodeArray | undefined; // Ensure start and count have valid values const length = nodes.length; @@ -156,7 +156,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(); @@ -178,13 +178,13 @@ 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(); if (some(declarations)) { const block = convertToFunctionBody(updated); - const statements = mergeLexicalEnvironment(block.statements, declarations); + const statements = mergeLexicalEnvironment(block.statements, declarations!); return updateBlock(block, statements); } return updated; @@ -208,7 +208,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; } @@ -294,14 +294,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, @@ -310,7 +310,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, @@ -318,7 +318,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, @@ -337,7 +337,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 @@ -457,7 +457,7 @@ namespace ts { case SyntaxKind.ElementAccessExpression: return updateElementAccess(node, visitNode((node).expression, visitor, isExpression), - visitNode((node).argumentExpression, visitor, isExpression)); + visitNode((node).argumentExpression!, visitor, isExpression)); case SyntaxKind.CallExpression: return updateCall(node, @@ -550,7 +550,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, @@ -669,7 +669,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, @@ -808,7 +808,7 @@ namespace ts { case SyntaxKind.ExternalModuleReference: return updateExternalModuleReference(node, - visitNode((node).expression, visitor, isExpression)); + visitNode((node).expression!, visitor, isExpression)); // JSX @@ -841,7 +841,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, @@ -880,7 +880,7 @@ namespace ts { case SyntaxKind.PropertyAssignment: return updatePropertyAssignment(node, visitNode((node).name, visitor, isPropertyName), - visitNode((node).initializer, visitor, isExpression)); + visitNode((node).initializer!, visitor, isExpression)); case SyntaxKind.ShorthandPropertyAssignment: return updateShorthandPropertyAssignment(node, @@ -923,7 +923,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); } @@ -931,11 +931,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; } @@ -947,12 +947,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; @@ -1449,13 +1449,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; } @@ -1494,8 +1494,8 @@ namespace ts { if (node === undefined) { return TransformFlags.None; } - if (node.transformFlags & TransformFlags.HasComputedFlags) { - return node.transformFlags & ~getTransformFlagsSubtreeExclusions(node.kind); + if (node.transformFlags! & TransformFlags.HasComputedFlags) { + return node.transformFlags! & ~getTransformFlagsSubtreeExclusions(node.kind); } const subtreeFlags = aggregateTransformFlagsForSubtree(node); return computeTransformFlagsForNode(node, subtreeFlags); @@ -1509,7 +1509,7 @@ namespace ts { let nodeArrayFlags = TransformFlags.None; for (const node of nodes) { subtreeFlags |= aggregateTransformFlagsForNode(node); - nodeArrayFlags |= node.transformFlags & ~TransformFlags.HasComputedFlags; + nodeArrayFlags |= node.transformFlags! & ~TransformFlags.HasComputedFlags; } nodes.transformFlags = nodeArrayFlags | TransformFlags.HasComputedFlags; return subtreeFlags; @@ -1544,11 +1544,9 @@ namespace ts { export namespace Debug { let isDebugInfoEnabled = false; - export const failBadSyntaxKind = shouldAssert(AssertionLevel.Normal) - ? (node: Node, message?: string): void => fail( - `${message || "Unexpected node."}\r\nNode ${formatSyntaxKind(node.kind)} was unexpected.`, - failBadSyntaxKind) - : noop; + export const failBadSyntaxKind = (node: Node, message?: string): never => fail( + `${message || "Unexpected node."}\r\nNode ${formatSyntaxKind(node.kind)} was unexpected.`, + failBadSyntaxKind); export const assertEachNode = shouldAssert(AssertionLevel.Normal) ? (nodes: Node[], test: (node: Node) => boolean, message?: string): void => assert( @@ -1559,10 +1557,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 7a98c43dd04a7..0bb8b6dccb228 100644 --- a/src/compiler/watch.ts +++ b/src/compiler/watch.ts @@ -8,7 +8,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 @@ -27,7 +27,7 @@ namespace ts { return diagnostic => { diagnostics[0] = diagnostic; system.write(formatDiagnosticsWithColorAndContext(diagnostics, host) + host.getNewLine()); - diagnostics[0] = undefined; + diagnostics[0] = undefined!; // TODO: GH#18217 }; } @@ -72,8 +72,8 @@ namespace ts { host.onConfigFileDiagnostic = reportDiagnostic; host.onUnRecoverableConfigFileDiagnostic = diagnostic => reportUnrecoverableDiagnostic(sys, reportDiagnostic, diagnostic); const result = getParsedCommandLineOfConfigFile(configFileName, optionsToExtend, host); - host.onConfigFileDiagnostic = undefined; - host.onUnRecoverableConfigFileDiagnostic = undefined; + host.onConfigFileDiagnostic = undefined!; // TODO: GH#18217 + host.onUnRecoverableConfigFileDiagnostic = undefined!; return result; } @@ -81,7 +81,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); } @@ -181,7 +181,7 @@ namespace ts { */ function createWatchCompilerHost(system = sys, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHost { if (!createProgram) { - createProgram = createEmitAndSemanticDiagnosticsBuilderProgram as any; + createProgram = createEmitAndSemanticDiagnosticsBuilderProgram as any as CreateProgram; } let host: DirectoryStructureHost = system; @@ -198,18 +198,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: reportWatchStatus || createWatchStatusReporter(system), 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 }; @@ -219,7 +219,7 @@ namespace ts { } function emitFilesAndReportErrorUsingBuilder(builderProgram: BuilderProgram) { - emitFilesAndReportErrors(builderProgram, reportDiagnostic, writeFileName); + emitFilesAndReportErrors(builderProgram, reportDiagnostic!, writeFileName); // TODO: GH#18217 } } @@ -238,7 +238,7 @@ namespace ts { reportDiagnostic = reportDiagnostic || createDiagnosticReporter(system); const host = createWatchCompilerHost(system, createProgram, reportDiagnostic, reportWatchStatus) as WatchCompilerHostOfConfigFile; host.onConfigFileDiagnostic = reportDiagnostic; - host.onUnRecoverableConfigFileDiagnostic = diagnostic => reportUnrecoverableDiagnostic(system, reportDiagnostic, diagnostic); + host.onUnRecoverableConfigFileDiagnostic = diagnostic => reportUnrecoverableDiagnostic(system, reportDiagnostic!, diagnostic); host.configFileName = configFileName; host.optionsToExtend = optionsToExtend; return host; @@ -260,6 +260,8 @@ namespace ts { export type WatchStatusReporter = (diagnostic: Diagnostic, newLine: string, options: CompilerOptions) => void; export type CreateProgram = (rootNames: ReadonlyArray, options: CompilerOptions, host?: CompilerHost, oldProgram?: T) => 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 */ @@ -309,7 +311,7 @@ namespace ts { /** 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; @@ -324,6 +326,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; @@ -413,7 +416,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); @@ -450,7 +453,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 @@ -461,14 +464,14 @@ namespace ts { const { configFileName, optionsToExtend: optionsToExtendForConfigFile = {}, createProgram } = host; let { rootFiles: rootFileNames, options: compilerOptions, configFileSpecs, configFileWildCardDirectories } = host; - 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, @@ -481,7 +484,7 @@ namespace ts { parseConfigFile(); } - const trace = host.trace && ((s: string) => { host.trace(s + newLine); }); + const trace = host.trace! && ((s: string) => { host.trace!(s + newLine); }); const loggingEnabled = trace && (compilerOptions.diagnostics || compilerOptions.extendedDiagnostics); const writeLog = loggingEnabled ? trace : noop; const watchFile = compilerOptions.extendedDiagnostics ? ts.addFileWatcherWithLogging : loggingEnabled ? ts.addFileWatcherWithOnlyTriggerLogging : ts.addFileWatcher; @@ -500,7 +503,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, @@ -510,12 +513,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, @@ -539,10 +542,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; @@ -649,15 +652,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; @@ -702,7 +705,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); @@ -732,7 +735,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(); } @@ -797,9 +800,9 @@ namespace ts { } function reloadFileNamesFromConfigFile() { - const result = getFileNamesFromConfigSpecs(configFileSpecs, getDirectoryPath(configFileName), compilerOptions, parseConfigFileHost); - if (!configFileSpecs.filesSpecs && result.fileNames.length === 0) { - host.onConfigFileDiagnostic(getErrorForNoInputFiles(configFileSpecs, configFileName)); + const result = getFileNamesFromConfigSpecs(configFileSpecs!, getDirectoryPath(configFileName), compilerOptions, parseConfigFileHost); + if (!configFileSpecs!.filesSpecs && result.fileNames.length === 0) { + host.onConfigFileDiagnostic(getErrorForNoInputFiles(configFileSpecs!, configFileName)); } rootFileNames = result.fileNames; @@ -824,10 +827,10 @@ namespace ts { function parseConfigFile() { const configParseResult = ts.getParsedCommandLineOfConfigFile(configFileName, optionsToExtendForConfigFile, parseConfigFileHost); - rootFileNames = configParseResult.fileNames; - compilerOptions = configParseResult.options; - configFileSpecs = configParseResult.configFileSpecs; - configFileWildCardDirectories = configParseResult.wildcardDirectories; + rootFileNames = configParseResult!.fileNames; + compilerOptions = configParseResult!.options; + configFileSpecs = configParseResult!.configFileSpecs; + configFileWildCardDirectories = configParseResult!.wildcardDirectories; } function onSourceFileChange(fileName: string, eventKind: FileWatcherEventKind, path: Path) { @@ -861,7 +864,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 @@ -919,10 +922,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); } } @@ -931,7 +934,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 f5c614d9d577c..8d25ac9385409 100644 --- a/src/compiler/watchUtilities.ts +++ b/src/compiler/watchUtilities.ts @@ -9,6 +9,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[]; @@ -78,8 +79,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(rootDirPath, resultFromHost); @@ -132,7 +133,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 { @@ -144,7 +145,7 @@ namespace ts { function directoryExists(dirPath: string): boolean { const path = toPath(dirPath); - return cachedReadDirectoryResult.has(path) || host.directoryExists(dirPath); + return cachedReadDirectoryResult.has(path) || host.directoryExists!(dirPath); } function createDirectory(dirPath: string) { @@ -154,7 +155,7 @@ namespace ts { if (result) { updateFileSystemEntry(result.directories, baseFileName, /*isValid*/ true); } - host.createDirectory(dirPath); + host.createDirectory!(dirPath); } function getDirectories(rootDir: string): string[] { @@ -163,7 +164,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[] { @@ -172,12 +173,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; } diff --git a/src/harness/compilerRunner.ts b/src/harness/compilerRunner.ts index 30c5e47949f44..51444c5d36832 100644 --- a/src/harness/compilerRunner.ts +++ b/src/harness/compilerRunner.ts @@ -66,18 +66,18 @@ class CompilerBaselineRunner extends RunnerBase { before(() => { justName = fileName.replace(/^.*[\\\/]/, ""); // strips the fileName from the path. - const content = Harness.IO.readFile(fileName); + const content = Harness.IO.readFile(fileName)!; const rootDir = fileName.indexOf("conformance") === -1 ? "tests/cases/compiler/" : ts.getDirectoryPath(fileName) + "/"; const testCaseContent = Harness.TestCaseParser.makeUnitsFromTest(content, fileName, rootDir); const units = testCaseContent.testUnitData; harnessSettings = testCaseContent.settings; - let tsConfigOptions: ts.CompilerOptions; + let tsConfigOptions: ts.CompilerOptions | undefined; 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); - tsConfigFiles.push(this.createHarnessTestFile(testCaseContent.tsConfigFileUnitData, rootDir, ts.combinePaths(rootDir, tsConfigOptions.configFilePath))); + tsConfigFiles.push(this.createHarnessTestFile(testCaseContent.tsConfigFileUnitData!, rootDir, ts.combinePaths(rootDir, tsConfigOptions.configFilePath!))); // TODO: GH#18217 } else { const baseUrl = harnessSettings.baseUrl; @@ -87,7 +87,7 @@ class CompilerBaselineRunner extends RunnerBase { } lastUnit = units[units.length - 1]; - hasNonDtsFiles = ts.forEach(units, unit => !ts.fileExtensionIs(unit.name, ts.Extension.Dts)); + hasNonDtsFiles = ts.some(units, 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. @@ -110,7 +110,7 @@ class CompilerBaselineRunner extends RunnerBase { if (tsConfigOptions && tsConfigOptions.configFilePath !== undefined) { tsConfigOptions.configFilePath = ts.combinePaths(rootDir, tsConfigOptions.configFilePath); - tsConfigOptions.configFile.fileName = tsConfigOptions.configFilePath; + tsConfigOptions.configFile!.fileName = tsConfigOptions.configFilePath; } const output = Harness.Compiler.compileFiles( @@ -123,14 +123,14 @@ class CompilerBaselineRunner extends RunnerBase { after(() => { // Mocha holds onto the closure environment of the describe callback even after the test is done. // Therefore we have to clean out large objects after the test is done. - justName = undefined; - lastUnit = undefined; - hasNonDtsFiles = undefined; - result = undefined; - options = undefined; - toBeCompiled = undefined; - otherFiles = undefined; - tsConfigFiles = undefined; + justName = undefined!; + lastUnit = undefined!; + hasNonDtsFiles = undefined!; + result = undefined!; + options = undefined!; + toBeCompiled = undefined!; + otherFiles = undefined!; + tsConfigFiles = undefined!; }); // check errors diff --git a/src/harness/externalCompileRunner.ts b/src/harness/externalCompileRunner.ts index 1f945cfcc9c80..030193a9fa94a 100644 --- a/src/harness/externalCompileRunner.ts +++ b/src/harness/externalCompileRunner.ts @@ -15,7 +15,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); } @@ -43,7 +43,7 @@ abstract class ExternalCompileRunnerBase extends RunnerBase { it("should build successfully", () => { let cwd = path.join(__dirname, "../../", cls.testDir, directoryName); 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/fourslash.ts b/src/harness/fourslash.ts index 7fdbbbc964098..d2e9b401f3aa8 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -181,7 +181,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) { @@ -201,7 +201,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); @@ -240,16 +240,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 @@ -277,7 +277,7 @@ namespace FourSlash { const baseDir = ts.normalizePath(ts.getDirectoryPath(configFileName)); const host = new Utils.MockParseConfigHost(baseDir, /*ignoreCase*/ false, this.inputFiles); - const configJsonObj = ts.parseConfigFileTextToJson(configFileName, this.inputFiles.get(configFileName)); + const configJsonObj = ts.parseConfigFileTextToJson(configFileName, this.inputFiles.get(configFileName)!); assert.isTrue(configJsonObj.config !== undefined); compilationOptions = ts.parseJsonConfigFileContent(configJsonObj.config, host, baseDir, compilationOptions, configFileName).options; @@ -318,7 +318,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 { @@ -329,7 +329,7 @@ namespace FourSlash { } }); this.languageServiceAdapterHost.addScript(Harness.Compiler.defaultLibFileName, - Harness.Compiler.getDefaultLibrarySourceFile().text, /*isRootFile*/ false); + Harness.Compiler.getDefaultLibrarySourceFile()!.text, /*isRootFile*/ false); } for (const file of testData.files) { @@ -385,7 +385,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, @@ -398,7 +398,7 @@ namespace FourSlash { } private getFileContent(fileName: string): string { - const script = this.languageServiceAdapterHost.getScriptInfo(fileName); + const script = this.languageServiceAdapterHost.getScriptInfo(fileName)!; return script.content; } @@ -537,9 +537,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[]) { @@ -551,12 +551,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)}`; } @@ -585,7 +585,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}`); } }); } @@ -623,11 +623,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?: string | string[]) { @@ -682,7 +682,7 @@ namespace FourSlash { testName = "goToDefinitions"; } else { - this.verifyDefinitionTextSpan(defs, startMarkerName); + this.verifyDefinitionTextSpan(defs, startMarkerName!); definitions = defs.definitions; testName = "goToDefinitionsAndBoundSpan"; @@ -701,7 +701,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; @@ -887,7 +887,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); } @@ -958,8 +958,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(expectedTag.name, actualTag.name); assert.equal(expectedTag.text, actualTag.text, this.messageAtLastKnownMarker("QuickInfo tag " + actualTag.name)); }); @@ -1008,7 +1008,7 @@ namespace FourSlash { } private verifySymbol(symbol: ts.Symbol, declarationRanges: Range[]) { - const { declarations } = symbol; + const declarations = symbol.declarations!; if (declarations.length !== declarationRanges.length) { this.raiseError(`Expected to get ${declarationRanges.length} declarations, got ${declarations.length}`); } @@ -1020,7 +1020,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"); } @@ -1190,7 +1190,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"); @@ -1221,11 +1221,11 @@ Actual: ${stringify(fullActual)}`); } private getCompletionListAtCaret(options?: FourSlashInterface.CompletionsAtOptions): ts.CompletionInfo { - return this.languageService.getCompletionsAtPosition(this.activeFile.fileName, this.currentCaretPosition, options); + return this.languageService.getCompletionsAtPosition(this.activeFile.fileName, this.currentCaretPosition, options)!; } private getCompletionEntryDetails(entryName: string, source?: string): ts.CompletionEntryDetails { - return this.languageService.getCompletionEntryDetails(this.activeFile.fileName, this.currentCaretPosition, entryName, this.formatCodeSettings, source); + return this.languageService.getCompletionEntryDetails(this.activeFile.fileName, this.currentCaretPosition, entryName, this.formatCodeSettings, source)!; } private getReferencesAtCaret() { @@ -1291,14 +1291,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)); }); @@ -1437,7 +1437,7 @@ Actual: ${stringify(fullActual)}`); } public verifySignatureHelpArgumentCount(expected: number) { - const signatureHelpItems = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition); + const signatureHelpItems = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition)!; const actual = signatureHelpItems.argumentCount; assert.equal(actual, expected); } @@ -1456,7 +1456,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."); } @@ -1495,13 +1495,13 @@ Actual: ${stringify(fullActual)}`); } private getActiveSignatureHelpItem() { - const help = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition); + const help = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition)!; const index = help.selectedItemIndex; return help.items[index]; } private getActiveParameter(): ts.SignatureHelpParameter { - const help = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition); + const help = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition)!; const item = help.items[help.selectedItemIndex]; const currentParam = help.argumentIndex; return item.parameters[currentParam]; @@ -1531,19 +1531,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; } @@ -1564,12 +1564,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(); @@ -1590,7 +1590,7 @@ Actual: ${stringify(fullActual)}`); Harness.Baseline.runBaseline( baselineFile, () => { - return this.baselineCurrentFileLocations(pos => this.getBreakpointStatementLocation(pos)); + return this.baselineCurrentFileLocations(pos => this.getBreakpointStatementLocation(pos)!); }); } @@ -1626,7 +1626,7 @@ Actual: ${stringify(fullActual)}`); const diagnostics = ts.getPreEmitDiagnostics(this.languageService.getProgram()); 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(); @@ -1668,7 +1668,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() { @@ -1681,8 +1681,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() { @@ -2010,7 +2010,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"); } @@ -2053,7 +2053,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"); } @@ -2068,7 +2068,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"); } @@ -2243,7 +2243,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"); } @@ -2265,12 +2265,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) { @@ -2329,7 +2329,7 @@ Actual: ${stringify(fullActual)}`); ); assert.equal( expected.join(","), - actual.fileNames.map(file => { + actual.fileNames!.map(file => { return file.replace(this.basePath + "/", ""); }).join(",") ); @@ -2396,22 +2396,23 @@ Actual: ${stringify(fullActual)}`); this.goToMarker(markerName); const actualCompletion = this.getCompletionListAtCaret({ includeExternalModuleExports: true, includeInsertTextCompletions: false }).entries.find(e => - e.name === options.name && e.source === options.source); + e.name === options.name && e.source === options.source)!; if (!actualCompletion.hasAction) { this.raiseError(`Completion for ${options.name} does not have an associated action.`); } const details = this.getCompletionEntryDetails(options.name, actualCompletion.source); - if (details.codeActions.length !== 1) { - this.raiseError(`Expected one code action, got ${details.codeActions.length}`); + 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); } @@ -2448,7 +2449,7 @@ Actual: ${stringify(fullActual)}`); const fixIds = ts.mapDefined(this.getCodeFixes(this.activeFile.fileName), a => a.fixId); ts.Debug.assert(ts.contains(fixIds, fixId), "No available code fix has that group id.", () => `Expected '${fixId}'. Available action ids: ${fixIds}`); const { changes, commands } = this.languageService.getCombinedCodeFix({ type: "file", fileName: this.activeFile.fileName }, fixId, this.formatCodeSettings); - assert.deepEqual(commands, options.commands); + assert.deepEqual | undefined>(commands, options.commands); assert(changes.every(c => c.fileName === this.activeFile.fileName), "TODO: support testing codefixes that touch multiple files"); this.applyChanges(changes); this.verifyCurrentFileContent(newFileContent); @@ -2507,7 +2508,7 @@ Actual: ${stringify(fullActual)}`); this.verifyCurrentFileContent(options.newFileContent); } else { - this.verifyRangeIs(options.newRangeContent, /*includeWhitespace*/ true); + this.verifyRangeIs(options.newRangeContent!, /*includeWhitespace*/ true); } } @@ -2527,7 +2528,7 @@ Actual: ${stringify(fullActual)}`); return; } - return this.languageService.getCodeFixesAtPosition(fileName, diagnostic.start, diagnostic.start + diagnostic.length, [diagnostic.code], this.formatCodeSettings); + return this.languageService.getCodeFixesAtPosition(fileName, diagnostic.start!, diagnostic.start! + diagnostic.length!, [diagnostic.code], this.formatCodeSettings); }); } @@ -2571,7 +2572,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); @@ -2594,7 +2595,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) { @@ -2633,7 +2634,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; @@ -2805,7 +2806,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) { @@ -3000,13 +3001,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); + const editInfo = this.languageService.getEditsForRefactor(this.activeFile.fileName, this.formatCodeSettings, range, refactorName, actionName)!; for (const edit of editInfo.edits) { this.applyEdits(edit.fileName, edit.textChanges, /*isFormattingEdit*/ false); } @@ -3058,7 +3059,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); + const editInfo = this.languageService.getEditsForRefactor(this.activeFile.fileName, formattingOptions, markerPos, refactorNameToApply, actionName)!; for (const edit of editInfo.edits) { this.applyEdits(edit.fileName, edit.textChanges, /*isFormattingEdit*/ false); @@ -3218,11 +3219,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); } } @@ -3244,13 +3245,13 @@ 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; } } 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); } @@ -3263,8 +3264,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); } @@ -3322,13 +3323,13 @@ ${code} const ranges: Range[] = []; // Stuff related to the subfile we're parsing - let currentFileContent: string = undefined; + let currentFileContent: string | undefined; let currentFileName = fileName; let currentFileSymlinks: string[] | undefined; let currentFileOptions: { [s: string]: string } = {}; function nextFile() { - const file = parseFileContent(currentFileContent, currentFileName, markerPositions, markers, ranges); + const file = parseFileContent(currentFileContent!, currentFileName, markerPositions, markers, ranges); file.fileOptions = currentFileOptions; file.symlinks = currentFileSymlinks; @@ -3432,11 +3433,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; @@ -3456,7 +3457,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 = undefined; try { // Attempt to parse the marker value as JSON @@ -3487,7 +3488,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 @@ -3516,7 +3517,7 @@ ${code} let output = ""; /// The current marker (or maybe multi-line comment?) we're parsing, possibly - let openMarker: LocationInformation = undefined; + let openMarker: LocationInformation | undefined; /// A stack of the open range markers that are still unclosed const openRanges: RangeLocationInformation[] = []; @@ -3537,7 +3538,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); }; @@ -3564,7 +3565,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 = { @@ -3607,8 +3608,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; @@ -3616,7 +3617,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; @@ -3628,17 +3629,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; @@ -3753,7 +3754,7 @@ namespace FourSlashInterface { return this.state.getMarkerNames(); } - public marker(name?: string): FourSlash.Marker { + public marker(name: string): FourSlash.Marker { return this.state.getMarkerByName(name); } @@ -3796,7 +3797,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!); } public rangeStart(range: FourSlash.Range) { @@ -3995,7 +3996,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); } diff --git a/src/harness/harness.ts b/src/harness/harness.ts index e35ecba2a04ca..d3c979731d384 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -145,7 +145,7 @@ namespace Utils { path = "tests/" + path; } - let content: string = undefined; + let content: string | undefined; try { content = Harness.IO.readFile(Harness.userSpecifiedRoot + path); } @@ -174,7 +174,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,16 +504,16 @@ namespace Harness { newLine(): string; getCurrentDirectory(): string; useCaseSensitiveFileNames(): boolean; - resolvePath(path: string): string; + resolvePath(path: string): string | undefined; 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; directoryExists(path: string): boolean; deleteFile(fileName: string): void; - listFiles(path: string, filter: RegExp, options?: { recursive?: boolean }): string[]; + listFiles(path: string, filter: RegExp | undefined, options?: { recursive?: boolean }): string[]; log(text: string): void; getMemoryUsage?(): number; args(): string[]; @@ -598,7 +598,7 @@ namespace Harness { for (const file of fs.readdirSync(folder)) { const pathToFile = pathModule.join(folder, file); const stat = fs.statSync(pathToFile); - if (options.recursive && stat.isDirectory()) { + if (options!.recursive && stat.isDirectory()) { paths = paths.concat(filesInFolder(pathToFile)); } else if (stat.isFile() && (!spec || file.match(spec))) { @@ -643,7 +643,7 @@ namespace Harness { export interface XHRResponse { status: number; - responseText: string; + responseText: string | undefined; } /// Ask the server for the contents of the file at the given URL via a simple GET request @@ -691,7 +691,7 @@ namespace Harness { } function directoryNameImpl(path: string) { - let dirPath = path; + let dirPath: string | undefined = path; // root of the server if (dirPath.match(/localhost:\d+$/) || dirPath.match(/localhost:\d+\/$/)) { dirPath = undefined; @@ -731,7 +731,7 @@ namespace Harness { export const listFiles = Utils.memoize((path: string, spec?: RegExp, options?: { recursive?: boolean }): string[] => { const response = Http.getFileFromServerSync(serverRoot + path); if (response.status === 200) { - let results = response.responseText.split(","); + let results = response.responseText!.split(","); // TODO: GH#18217 if (spec) { results = results.filter(file => spec.test(file)); } @@ -823,7 +823,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 @@ -833,17 +833,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!; } } @@ -877,20 +877,20 @@ namespace Harness { const testLibFileNameSourceFileMap = ts.createMap(); const es6TestLibFileNameSourceFileMap = ts.createMap(); - 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; } @@ -965,12 +965,12 @@ namespace Harness { if (scriptTarget <= ts.ScriptTarget.ES5) { if (!testLibFileNameSourceFileMap.get(libFileName)) { - testLibFileNameSourceFileMap.set(libFileName, createSourceFileAndAssertInvariants(libFileName, IO.readFile(libFileName), scriptTarget)); + testLibFileNameSourceFileMap.set(libFileName, createSourceFileAndAssertInvariants(libFileName, IO.readFile(libFileName)!, scriptTarget)); } } else { if (!es6TestLibFileNameSourceFileMap.get(libFileName)) { - es6TestLibFileNameSourceFileMap.set(libFileName, createSourceFileAndAssertInvariants(libFileName, IO.readFile(libFileName), scriptTarget)); + es6TestLibFileNameSourceFileMap.set(libFileName, createSourceFileAndAssertInvariants(libFileName, IO.readFile(libFileName)!, scriptTarget)); } } } @@ -984,7 +984,7 @@ namespace Harness { } else if (fileName === fourslashFileName) { const tsFn = "tests/cases/fourslash/" + fourslashFileName; - fourslashSourceFile = fourslashSourceFile || createSourceFileAndAssertInvariants(tsFn, Harness.IO.readFile(tsFn), scriptTarget); + fourslashSourceFile = fourslashSourceFile || createSourceFileAndAssertInvariants(tsFn, Harness.IO.readFile(tsFn)!, scriptTarget); return fourslashSourceFile; } else if (ts.startsWith(fileName, "tests/lib/")) { @@ -1016,7 +1016,7 @@ namespace Harness { getNewLine: () => newLine, fileExists: fileName => fileMap.has(toPath(fileName)), readFile(fileName: string): string | undefined { - const file = fileMap.get(toPath(fileName)); + const file = fileMap.get(toPath(fileName))!; if (ts.endsWith(fileName, "json")) { // strip comments return file.getText(); @@ -1160,17 +1160,17 @@ 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): CompilationOutput { + currentDirectory: string | undefined): CompilationOutput { 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; options.noErrorTruncation = true; options.skipDefaultLibCheck = typeof options.skipDefaultLibCheck === "undefined" ? true : options.skipDefaultLibCheck; - if (typeof currentDirectory === "undefined") { + if (currentDirectory === undefined) { currentDirectory = Harness.IO.getCurrentDirectory(); } @@ -1179,7 +1179,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 : Harness.IO.useCaseSensitiveFileNames(); @@ -1190,7 +1190,7 @@ namespace Harness { const builtFileName = ts.combinePaths(libFolder, options.includeBuiltFile); const builtFile: TestFile = { unitName: builtFileName, - content: normalizeLineEndings(IO.readFile(builtFileName), Harness.IO.newLine()), + content: normalizeLineEndings(IO.readFile(builtFileName)!, Harness.IO.newLine()), }; programFiles.push(builtFile); } @@ -1202,7 +1202,7 @@ namespace Harness { for (const fileName of options.libFiles.split(",")) { const libFileName = "tests/lib/" + fileName; // Content is undefined here because in createCompilerHost we will create sourceFile for the lib file and cache the result - programFiles.push({ unitName: libFileName, content: undefined }); + programFiles.push({ unitName: libFileName, content: undefined! }); // TODO: GH#18217 } } @@ -1218,10 +1218,10 @@ namespace Harness { options.newLine, options.libFiles); - let traceResults: string[]; + let traceResults: string[] | undefined; if (options.traceResolution) { traceResults = []; - compilerHost.trace = text => traceResults.push(text); + compilerHost.trace = text => traceResults!.push(text); } else { compilerHost.directoryExists = () => true; // This only visibly affects resolution traces, so to save time we always return true where possible @@ -1239,7 +1239,7 @@ namespace Harness { export interface DeclarationCompilationContext { declInputFiles: TestFile[]; declOtherFiles: TestFile[]; - harnessSettings: TestCaseParser.CompilerSettings & HarnessOptions; + harnessSettings: TestCaseParser.CompilerSettings & HarnessOptions | undefined; options: ts.CompilerOptions; currentDirectory: string; } @@ -1250,7 +1250,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 (result.errors.length === 0) { if (options.declaration) { @@ -1288,7 +1288,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; @@ -1440,7 +1440,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))) { @@ -1458,7 +1459,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++; } } @@ -1473,12 +1474,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 @@ -1486,7 +1487,7 @@ namespace Harness { } export function doErrorBaseline(baselinePath: string, inputFiles: TestFile[], errors: ts.Diagnostic[], pretty?: boolean) { - Harness.Baseline.runBaseline(baselinePath.replace(/\.tsx?$/, ".errors.txt"), (): string => { + Harness.Baseline.runBaseline(baselinePath.replace(/\.tsx?$/, ".errors.txt"), () => { if (!errors || (errors.length === 0)) { /* tslint:disable:no-null-keyword */ return null; @@ -1516,7 +1517,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); } @@ -1564,7 +1565,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()) { @@ -1753,7 +1754,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}`; } @@ -1815,7 +1816,7 @@ namespace Harness { /** @param fileResults an array of strings for the fileName and an ITextWriter with its code */ constructor(fileResults: GeneratedFile[], errors: ts.Diagnostic[], public program: ts.Program, - public currentDirectoryForProgram: string, private sourceMapData: ts.SourceMapData[], public traceResults: string[]) { + public currentDirectoryForProgram: string, private sourceMapData: ts.SourceMapData[] | undefined, public traceResults: string[] | undefined) { for (const emittedFile of fileResults) { if (isDTS(emittedFile.fileName)) { @@ -1866,7 +1867,7 @@ namespace Harness { 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 */ @@ -1880,8 +1881,8 @@ namespace Harness { export function makeUnitsFromTest(code: string, fileName: string, rootDir?: string): { settings: CompilerSettings; testUnitData: TestUnitData[]; - tsConfig: ts.ParsedCommandLine; - tsConfigFileUnitData: TestUnitData; + tsConfig: ts.ParsedCommandLine | undefined; + tsConfigFileUnitData: TestUnitData | undefined; } { const settings = extractCompilerSettings(code); @@ -1891,7 +1892,7 @@ namespace Harness { const lines = Utils.splitContentByNewlines(code); // Stuff related to the subfile we're parsing - let currentFileContent: string = undefined; + let currentFileContent: string | undefined; let currentFileOptions: any = {}; let currentFileName: any = undefined; let refs: string[] = []; @@ -1911,7 +1912,7 @@ namespace Harness { if (currentFileName) { // Store result file const newTestFile = { - content: currentFileContent, + content: currentFileContent!, // TODO: GH#18217 name: currentFileName, fileOptions: currentFileOptions, originalFilePath: fileName, @@ -1966,8 +1967,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)) { @@ -2028,7 +2029,7 @@ namespace Harness { } const fileCache: { [idx: string]: boolean } = {}; - function generateActual(generateContent: () => string): string { + function generateActual(generateContent: () => string | null): string | null { const actual = generateContent(); @@ -2039,12 +2040,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); @@ -2057,7 +2058,7 @@ namespace Harness { let expected = ""; if (IO.fileExists(refFileName)) { - expected = IO.readFile(refFileName); + expected = IO.readFile(refFileName)!; // TODO: GH#18217 } return { expected, actual }; @@ -2073,7 +2074,7 @@ namespace Harness { return; } - const parentDirectory = IO.directoryName(dirName); + const parentDirectory = IO.directoryName(dirName)!; // TODO: GH#18217 if (parentDirectory !== "") { createDirectoryStructure(parentDirectory); } @@ -2082,7 +2083,7 @@ namespace Harness { } // Create folders if needed - createDirectoryStructure(Harness.IO.directoryName(actualFileName)); + createDirectoryStructure(Harness.IO.directoryName(actualFileName)!); // TODO: GH#18217 // Delete the actual file in case it fails if (IO.fileExists(actualFileName)) { @@ -2101,14 +2102,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[] = []; @@ -2178,7 +2179,7 @@ namespace Harness { export function getDefaultLibraryFile(filePath: string, io: Harness.Io): Harness.Compiler.TestFile { const libFile = Harness.userSpecifiedRoot + Harness.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 c38ab1f3c6df3..e57322fb4d235 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); } @@ -131,7 +131,7 @@ namespace Harness.LanguageService { public getFilenames(): string[] { const fileNames: string[] = []; for (const virtualEntry of this.virtualFileSystem.getAllFileEntries()) { - const scriptInfo = virtualEntry.content; + const scriptInfo = virtualEntry.content!; if (scriptInfo.isRootFile) { // only include root files here // usually it means that we won't include lib.d.ts in the list of root files so it won't mess the computation of compilation root dir. @@ -141,7 +141,7 @@ namespace Harness.LanguageService { return fileNames; } - public getScriptInfo(fileName: string): ScriptInfo { + public getScriptInfo(fileName: string): ScriptInfo | undefined { const fileEntry = this.virtualFileSystem.traversePath(fileName); return fileEntry && fileEntry.isFile() ? fileEntry.content : undefined; } @@ -169,9 +169,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); } } @@ -181,7 +180,7 @@ namespace Harness.LanguageService { symlinks = ts.createMap(); isKnownTypesPackageName(name: string): boolean { - return this.typesRegistry && this.typesRegistry.has(name); + return !!this.typesRegistry && this.typesRegistry.has(name); } installPackage = ts.notImplemented; @@ -196,14 +195,14 @@ namespace Harness.LanguageService { getScriptFileNames(): string[] { 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; } getScriptKind(): ts.ScriptKind { return ts.ScriptKind.Unknown; } 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 { @@ -212,7 +211,7 @@ namespace Harness.LanguageService { } const fileEntry = this.virtualFileSystem.traversePath(dirName); - return fileEntry && fileEntry.isDirectory(); + return !!fileEntry && fileEntry.isDirectory(); } fileExists(fileName: string): boolean { @@ -227,7 +226,7 @@ namespace Harness.LanguageService { } readFile(path: string): string | undefined { const target = this.symlinks.get(path); - return target !== undefined ? this.readFile(target) : ts.getSnapshotText(this.getScriptSnapshot(path)); + return target !== undefined ? this.readFile(target) : ts.getSnapshotText(this.getScriptSnapshot(path)!); } addSymlink(from: string, target: string) { this.symlinks.set(from, target); } realpath(path: string): string { @@ -278,7 +277,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) { @@ -297,8 +296,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); @@ -311,7 +310,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); } @@ -323,7 +322,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(); } @@ -499,7 +498,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 { @@ -600,7 +599,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); } @@ -707,7 +706,7 @@ namespace Harness.LanguageService { return true; } - getLogFileName(): string { + getLogFileName(): string | undefined { return undefined; } @@ -842,7 +841,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 949c6e5d947c7..e756fe169981d 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,9 +87,9 @@ interface PlaybackControl { } namespace Playback { - let recordLog: IoLog = undefined; - let replayLog: IoLog = undefined; - let replayFilesRead: ts.Map | undefined = undefined; + let recordLog: IoLog | undefined; + let replayLog: IoLog | undefined; + let replayFilesRead: ts.Map | undefined; let recordLogFileNameBase = ""; interface Memoized { @@ -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 59105cd5b0829..99c6050bb3db2 100644 --- a/src/harness/parallel/host.ts +++ b/src/harness/parallel/host.ts @@ -32,7 +32,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 = Harness.IO.readFile(perfdataFileName(target)); if (perfDataContents) { return JSON.parse(perfDataContents); @@ -73,7 +73,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..."); @@ -223,16 +223,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 } } } @@ -264,7 +264,7 @@ namespace Harness.Parallel.Host { doneBatching[i] = true; continue; } - const task = tasks.pop(); + const task = tasks.pop()!; batches[i].push(task); scheduledTotal += task.size; } @@ -289,7 +289,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 }); @@ -298,7 +298,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 }); } @@ -479,7 +479,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] = { }); @@ -515,7 +515,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++) { @@ -524,7 +524,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 1902ff70b1933..f22284bb5ef4e 100644 --- a/src/harness/parallel/worker.ts +++ b/src/harness/parallel/worker.ts @@ -32,25 +32,25 @@ 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; } 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; }, @@ -60,9 +60,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; @@ -123,13 +123,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) { timeout = n as number; const timeoutMsg: ParallelTimeoutChangeMessage = { type: "timeout", payload: { duration: timeout } }; - process.send(timeoutMsg); + process.send!(timeoutMsg); return this; }, retries() { return this; }, @@ -159,7 +159,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++; @@ -189,7 +189,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) { @@ -213,7 +213,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); @@ -233,16 +233,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); @@ -267,7 +267,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 f8d4d171f01df..9d02844053de1 100644 --- a/src/harness/projectsRunner.ts +++ b/src/harness/projectsRunner.ts @@ -63,17 +63,17 @@ class ProjectRunner extends RunnerBase { let testFileText: string; try { - testFileText = Harness.IO.readFile(testCaseFileName); + testFileText = Harness.IO.readFile(testCaseFileName)!; } catch (e) { - assert(false, "Unable to open testcase file: " + testCaseFileName + ": " + e.message); + return ts.Debug.fail("Unable to open testcase file: " + testCaseFileName + ": " + e.message); } try { testCase = JSON.parse(testFileText); } catch (e) { - assert(false, "Testcase: " + testCaseFileName + " does not contain valid json format: " + e.message); + return ts.Debug.fail("Testcase: " + testCaseFileName + " does not contain valid json format: " + e.message); } let testCaseJustName = testCaseFileName.replace(/^.*[\\\/]/, "").replace(/\.json/, ""); @@ -98,8 +98,10 @@ class ProjectRunner extends RunnerBase { return Harness.Baseline.localPath("projectOutput/" + testCaseJustName + "/" + moduleNameToString(moduleKind) + "/" + fileName); } - function cleanProjectUrl(url: string) { - let diskProjectPath = ts.normalizeSlashes(Harness.IO.resolvePath(testCase.projectRoot)); + function cleanProjectUrl(url: string): string; + function cleanProjectUrl(url: string | undefined): string | undefined; + function cleanProjectUrl(url: string | undefined) { + let diskProjectPath = ts.normalizeSlashes(Harness.IO.resolvePath(testCase.projectRoot)!); let projectRootUrl = "file:///" + diskProjectPath; const normalizedProjectRoot = ts.normalizeSlashes(testCase.projectRoot); diskProjectPath = diskProjectPath.substr(0, diskProjectPath.lastIndexOf(normalizedProjectRoot)); @@ -122,12 +124,12 @@ class ProjectRunner extends RunnerBase { } function getCurrentDirectory() { - return Harness.IO.resolvePath(testCase.projectRoot); + return Harness.IO.resolvePath(testCase.projectRoot)!; } function compileProjectFiles(moduleKind: ts.ModuleKind, configFileSourceFiles: ReadonlyArray, getInputFiles: () => ReadonlyArray, - getSourceFileTextImpl: (fileName: string) => string, + getSourceFileTextImpl: (fileName: string) => string | undefined, writeFile: (fileName: string, data: string, writeByteOrderMark: boolean) => void, compilerOptions: ts.CompilerOptions): CompileProjectFilesResult { @@ -157,13 +159,13 @@ class ProjectRunner extends RunnerBase { sourceMapData }; - function getSourceFileText(fileName: string): string { + function getSourceFileText(fileName: string): string | undefined { const text = getSourceFileTextImpl(fileName); return text !== undefined ? text : getSourceFileTextImpl(ts.getNormalizedAbsolutePath(fileName, getCurrentDirectory())); } - function getSourceFile(fileName: string, languageVersion: ts.ScriptTarget): ts.SourceFile { - let sourceFile: ts.SourceFile = undefined; + function getSourceFile(fileName: string, languageVersion: ts.ScriptTarget): ts.SourceFile | undefined { + let sourceFile: ts.SourceFile | undefined; if (fileName === Harness.Compiler.defaultLibFileName) { sourceFile = Harness.Compiler.getDefaultLibrarySourceFile(Harness.Compiler.getDefaultLibFileName(compilerOptions)); } @@ -201,7 +203,7 @@ class ProjectRunner extends RunnerBase { let compilerOptions = createCompilerOptions(); const configFileSourceFiles: ts.SourceFile[] = []; - let configFileName: string; + let configFileName: string | undefined; if (compilerOptions.project) { // Parse project configFileName = ts.normalizePath(ts.combinePaths(compilerOptions.project, "tsconfig.json")); @@ -211,7 +213,7 @@ class ProjectRunner extends RunnerBase { configFileName = ts.findConfigFile("", fileExists); } - let errors: ts.Diagnostic[]; + let errors: ts.Diagnostic[] | undefined; if (configFileName) { const result = ts.readJsonConfigFile(configFileName, getSourceFileText); configFileSourceFiles.push(result); @@ -293,8 +295,8 @@ class ProjectRunner extends RunnerBase { return Harness.IO.readFile(getFileNameInTheProjectTest(fileName)); } - function getSourceFileText(fileName: string): string { - let text: string = undefined; + function getSourceFileText(fileName: string): string | undefined { + let text: string | undefined; try { text = Harness.IO.readFile(getFileNameInTheProjectTest(fileName)); } @@ -309,7 +311,7 @@ class ProjectRunner extends RunnerBase { // if filename is not rooted - concat it with project root and then expand project root relative to current directory const diskFileName = ts.isRootedDiskPath(fileName) ? fileName - : Harness.IO.resolvePath(ts.normalizeSlashes(testCase.projectRoot) + "/" + ts.normalizeSlashes(fileName)); + : Harness.IO.resolvePath(ts.normalizeSlashes(testCase.projectRoot) + "/" + ts.normalizeSlashes(fileName))!; const currentDirectory = getCurrentDirectory(); // compute file name relative to current directory (expanded project root) @@ -370,10 +372,10 @@ class ProjectRunner extends RunnerBase { allInputFiles.unshift({ emittedFileName: sourceFile.fileName, code: sourceFile.text }); } else if (!(compilerOptions.outFile || compilerOptions.out)) { - let emitOutputFilePathWithoutExtension: string = undefined; + 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 { @@ -387,8 +389,8 @@ class ProjectRunner extends RunnerBase { } } 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); } @@ -396,15 +398,15 @@ class ProjectRunner extends RunnerBase { }); // Dont allow config files since we are compiling existing source options - return compileProjectFiles(compilerResult.moduleKind, compilerResult.configFileSourceFiles, getInputFiles, getSourceFileText, /*writeFile*/ ts.noop, compilerResult.compilerOptions); + return compileProjectFiles(compilerResult.moduleKind, compilerResult.configFileSourceFiles, getInputFiles, getSourceFileText, /*writeFile*/ ts.noop, compilerResult.compilerOptions!); function findOutputDtsFile(fileName: string) { - return ts.forEach(compilerResult.outputFiles, outputFile => outputFile.emittedFileName === fileName ? outputFile : undefined); + return compilerResult.outputFiles && ts.find(compilerResult.outputFiles, outputFile => outputFile.emittedFileName === fileName); } function getInputFiles() { return ts.map(allInputFiles, outputFile => outputFile.emittedFileName); } - function getSourceFileText(fileName: string): string { + function getSourceFileText(fileName: string): string | undefined { for (const inputFile of allInputFiles) { const isMatchingFile = ts.isRootedDiskPath(fileName) ? ts.getNormalizedAbsolutePath(inputFile.emittedFileName, getCurrentDirectory()) === fileName @@ -447,10 +449,10 @@ class ProjectRunner extends RunnerBase { function getCompilerResolutionInfo() { const resolutionInfo: ProjectRunnerTestCaseResolutionInfo & ts.CompilerOptions = JSON.parse(JSON.stringify(testCase)); - resolutionInfo.resolvedInputFiles = ts.map(compilerResult.program.getSourceFiles(), inputFile => { + resolutionInfo.resolvedInputFiles = ts.map(compilerResult.program!.getSourceFiles(), inputFile => { return ts.convertToRelativePath(inputFile.fileName, getCurrentDirectory(), path => Harness.Compiler.getCanonicalFileName(path)); }); - resolutionInfo.emittedFiles = ts.map(compilerResult.outputFiles, outputFile => { + resolutionInfo.emittedFiles = ts.map(compilerResult.outputFiles!, outputFile => { return ts.convertToRelativePath(outputFile.emittedFileName, getCurrentDirectory(), path => Harness.Compiler.getCanonicalFileName(path)); }); return resolutionInfo; @@ -485,10 +487,10 @@ class ProjectRunner extends RunnerBase { try { Harness.Baseline.runBaseline(getBaselineFolder(compilerResult.moduleKind) + outputFile.fileName, () => { try { - return Harness.IO.readFile(getProjectOutputFolder(outputFile.fileName, compilerResult.moduleKind)); + return Harness.IO.readFile(getProjectOutputFolder(outputFile.fileName, compilerResult.moduleKind))!; } catch (e) { - return undefined; + return undefined!; // TODO: GH#18217 } }); } @@ -523,7 +525,7 @@ class ProjectRunner extends RunnerBase { } }); after(() => { - compilerResult = undefined; + compilerResult = undefined!; }); } @@ -533,9 +535,9 @@ class ProjectRunner extends RunnerBase { after(() => { // Mocha holds onto the closure environment of the describe callback even after the test is done. // Therefore we have to clean out large objects after the test is done. - testCase = undefined; - testFileText = undefined; - testCaseJustName = undefined; + testCase = undefined!; + testFileText = undefined!; + testCaseJustName = undefined!; }); }); }); diff --git a/src/harness/runner.ts b/src/harness/runner.ts index 76d65090f02db..2c70db53e0fb8 100644 --- a/src/harness/runner.ts +++ b/src/harness/runner.ts @@ -65,10 +65,10 @@ 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}`); } -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(); } @@ -80,10 +80,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; @@ -133,7 +133,7 @@ function handleTestConfig() { if (testConfig.stackTraceLimit === "full") { (Error).stackTraceLimit = Infinity; } - else if ((+testConfig.stackTraceLimit | 0) > 0) { + else if ((+testConfig.stackTraceLimit! | 0) > 0) { (Error).stackTraceLimit = testConfig.stackTraceLimit; } if (testConfig.listenForWork) { @@ -223,6 +223,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 3631186bb4822..06a8d8631476c 100644 --- a/src/harness/rwcRunner.ts +++ b/src/harness/rwcRunner.ts @@ -45,22 +45,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(800000); // Allow long timeouts for RWC compilations 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); @@ -106,7 +106,7 @@ namespace RWC { const isInInputList = (resolvedPath: string) => (inputFile: { unitName: string; content: string; }) => inputFile.unitName === resolvedPath; for (const fileRead of ioLog.filesRead) { // Check if the file is already added into the set of input files. - const resolvedPath = ts.normalizeSlashes(Harness.IO.resolvePath(fileRead.path)); + const resolvedPath = ts.normalizeSlashes(Harness.IO.resolvePath(fileRead.path)!); const inInputList = ts.forEach(inputFiles, isInInputList(resolvedPath)); if (isTsConfigFile(fileRead)) { @@ -142,7 +142,7 @@ namespace RWC { opts.options.noLib = true; // Emit the results - compilerOptions = undefined; + compilerOptions = undefined!; const output = Harness.Compiler.compileFiles( inputFiles, otherFiles, @@ -157,13 +157,13 @@ namespace RWC { }); 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 }; } @@ -219,11 +219,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.errors); }, baselineOpts); diff --git a/src/harness/sourceMapRecorder.ts b/src/harness/sourceMapRecorder.ts index 606d4e67acdf3..06885ddc51a40 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: Compiler.GeneratedFile; let jsLineMap: number[]; @@ -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 @@ -344,7 +345,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++) { @@ -360,7 +361,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); @@ -420,7 +421,7 @@ namespace Harness.SourceMapRecorder { const jsFileText = getTextOfLine(currentJsLine, jsLineMap, jsFile.code); 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 @@ -439,11 +440,11 @@ namespace Harness.SourceMapRecorder { for (let i = 0; i < sourceMapDataList.length; i++) { const sourceMapData = sourceMapDataList[i]; - let prevSourceFile: ts.SourceFile; + let prevSourceFile: ts.SourceFile | undefined; SourceMapSpanWriter.initializeSourceMapSpanWriter(sourceMapRecorder, sourceMapData, jsFiles[i]); 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 6c5b186f2b89e..3e85ea9be3e0f 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 }; const output = Harness.Compiler.compileFiles( @@ -63,7 +63,7 @@ class Test262BaselineRunner extends RunnerBase { }); after(() => { - testState = undefined; + testState = undefined!; }); it("has the expected emitted code", () => { @@ -91,7 +91,7 @@ class Test262BaselineRunner extends RunnerBase { 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 bc25bfd12d6ad..7ee34ad2da9a6 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.getTextOfNodeFromSourceText(this.currentSourceFile.text, 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/compileOnSave.ts b/src/harness/unittests/compileOnSave.ts index a64d7bdd2a57f..2e293da5c8319 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 be1ada10a972c..1dd5c7463fee6 100644 --- a/src/harness/unittests/convertTypeAcquisitionFromJson.ts +++ b/src/harness/unittests/convertTypeAcquisitionFromJson.ts @@ -9,7 +9,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); @@ -118,7 +118,7 @@ namespace ts { file: undefined, start: 0, length: 0, - messageText: undefined + messageText: undefined!, // TODO: GH#18217 } ] }); @@ -213,7 +213,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 ce9d18815bfe0..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 (ts.isArray(result.targetRange.range)) { - pos = result.targetRange.range[0].getStart(f); - end = ts.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 8970990326c15..98280badf0665 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, @@ -130,15 +130,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); @@ -181,7 +181,7 @@ namespace ts { const projectService = projectSystem.createProjectService(host); projectService.openClientFile(f.path); const program = projectService.inferredProjects[0].getLanguageService().getProgram(); - const sourceFile = program.getSourceFile(f.path); + const sourceFile = program.getSourceFile(f.path)!; const context: RefactorContext = { cancellationToken: { throwIfCancellationRequested: noop, isCancellationRequested: returnFalse }, program, @@ -193,7 +193,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 e7e5c11e33e23..4dc2c9b30770b 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 b7215f5ea3539..d1a0c8e6772e4 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"); } @@ -314,7 +314,7 @@ namespace ts { assert.equal(root.kind, ts.SyntaxKind.SourceFile); const first = root.getFirstToken(); assert.isDefined(first); - assert.equal(first.kind, ts.SyntaxKind.VarKeyword); + assert.equal(first!.kind, ts.SyntaxKind.VarKeyword); }); }); describe("getLastToken", () => { @@ -323,7 +323,7 @@ namespace ts { assert.isDefined(root); const last = root.getLastToken(); assert.isDefined(last); - assert.equal(last.kind, ts.SyntaxKind.EndOfFileToken); + assert.equal(last!.kind, ts.SyntaxKind.EndOfFileToken); }); }); }); diff --git a/src/harness/unittests/moduleResolution.ts b/src/harness/unittests/moduleResolution.ts index 0dd016b2f229c..c222c21b10634 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; } } @@ -325,7 +325,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, @@ -413,7 +413,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, @@ -968,9 +968,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", () => { @@ -1104,10 +1104,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); }); @@ -1138,7 +1135,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/organizeImports.ts b/src/harness/unittests/organizeImports.ts index 8d7b0904eb7f1..efdfd7d3933fa 100644 --- a/src/harness/unittests/organizeImports.ts +++ b/src/harness/unittests/organizeImports.ts @@ -285,7 +285,7 @@ F2(); assert.equal(changes[0].fileName, testPath); Harness.Baseline.runBaseline(baselinePath, () => { - const newText = textChanges.applyChanges(testContent, changes[0].textChanges); + const newText = textChanges.applyChanges(testContent!, changes[0].textChanges); // TODO: GH#18217 return [ "// ==ORIGINAL==", testContent, diff --git a/src/harness/unittests/programMissingFiles.ts b/src/harness/unittests/programMissingFiles.ts index 2a7f6d24ea787..766f7a34a9634 100644 --- a/src/harness/unittests/programMissingFiles.ts +++ b/src/harness/unittests/programMissingFiles.ts @@ -41,8 +41,8 @@ namespace ts { const testCompilerHost = Harness.Compiler.createCompilerHost( /*inputFiles*/ [emptyFile, referenceFile], - /*writeFile*/ undefined, - /*scriptTarget*/ undefined, + /*writeFile*/ undefined!, // TODO: GH#18217 + /*scriptTarget*/ undefined!, /*useCaseSensitiveFileNames*/ false, /*currentDirectory*/ "d:\\pretend\\", /*newLineKind*/ NewLineKind.LineFeed, 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/publicApi.ts b/src/harness/unittests/publicApi.ts index 35acfec57f530..b0626def5f7df 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 70325831f5129..d900f69caf2f7 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 fef382e8a3b03..64d3f9ae334a8 100644 --- a/src/harness/unittests/services/patternMatcher.ts +++ b/src/harness/unittests/services/patternMatcher.ts @@ -95,43 +95,43 @@ describe("PatternMatcher", () => { describe("SingleWordPattern", () => { it("PreferCaseSensitiveExact", () => { - const match = getFirstMatch("Foo", "Foo"); + const match = getFirstMatch("Foo", "Foo")!; assert.equal(ts.PatternMatchKind.exact, match.kind); assert.equal(true, match.isCaseSensitive); }); it("PreferCaseSensitiveExactInsensitive", () => { - const match = getFirstMatch("foo", "Foo"); + const match = getFirstMatch("foo", "Foo")!; assert.equal(ts.PatternMatchKind.exact, match.kind); assert.equal(false, match.isCaseSensitive); }); it("PreferCaseSensitivePrefix", () => { - const match = getFirstMatch("Foo", "Fo"); + const match = getFirstMatch("Foo", "Fo")!; assert.equal(ts.PatternMatchKind.prefix, match.kind); assert.equal(true, match.isCaseSensitive); }); it("PreferCaseSensitivePrefixCaseInsensitive", () => { - const match = getFirstMatch("Foo", "fo"); + const match = getFirstMatch("Foo", "fo")!; assert.equal(ts.PatternMatchKind.prefix, match.kind); assert.equal(false, match.isCaseSensitive); }); it("PreferCaseSensitiveCamelCaseMatchSimple", () => { - const match = getFirstMatch("FogBar", "FB"); + const match = getFirstMatch("FogBar", "FB")!; assert.equal(ts.PatternMatchKind.camelCase, match.kind); assert.equal(true, match.isCaseSensitive); - assertInRange(match.camelCaseWeight, 1, 1 << 30); + assertInRange(match.camelCaseWeight!, 1, 1 << 30); }); it("PreferCaseSensitiveCamelCaseMatchPartialPattern", () => { - const match = getFirstMatch("FogBar", "FoB"); + const match = getFirstMatch("FogBar", "FoB")!; assert.equal(ts.PatternMatchKind.camelCase, match.kind); assert.equal(true, match.isCaseSensitive); @@ -162,56 +162,56 @@ describe("PatternMatcher", () => { }); it("TwoUppercaseCharacters", () => { - const match = getFirstMatch("SimpleUIElement", "SiUI"); + const match = getFirstMatch("SimpleUIElement", "SiUI")!; assert.equal(ts.PatternMatchKind.camelCase, match.kind); assert.equal(true, match.isCaseSensitive); }); it("PreferCaseSensitiveLowercasePattern", () => { - const match = getFirstMatch("FogBar", "b"); + const match = getFirstMatch("FogBar", "b")!; assert.equal(ts.PatternMatchKind.substring, match.kind); assert.equal(false, match.isCaseSensitive); }); it("PreferCaseSensitiveLowercasePattern2", () => { - const match = getFirstMatch("FogBar", "fB"); + const match = getFirstMatch("FogBar", "fB")!; assert.equal(ts.PatternMatchKind.camelCase, match.kind); assert.equal(false, match.isCaseSensitive); }); it("PreferCaseSensitiveTryUnderscoredName", () => { - const match = getFirstMatch("_fogBar", "_fB"); + const match = getFirstMatch("_fogBar", "_fB")!; assert.equal(ts.PatternMatchKind.camelCase, match.kind); assert.equal(true, match.isCaseSensitive); }); it("PreferCaseSensitiveTryUnderscoredName2", () => { - const match = getFirstMatch("_fogBar", "fB"); + const match = getFirstMatch("_fogBar", "fB")!; assert.equal(ts.PatternMatchKind.camelCase, match.kind); assert.equal(true, match.isCaseSensitive); }); it("PreferCaseSensitiveTryUnderscoredNameInsensitive", () => { - const match = getFirstMatch("_FogBar", "_fB"); + const match = getFirstMatch("_FogBar", "_fB")!; assert.equal(ts.PatternMatchKind.camelCase, match.kind); assert.equal(false, match.isCaseSensitive); }); it("PreferCaseSensitiveMiddleUnderscore", () => { - const match = getFirstMatch("Fog_Bar", "FB"); + const match = getFirstMatch("Fog_Bar", "FB")!; assert.equal(ts.PatternMatchKind.camelCase, match.kind); assert.equal(true, match.isCaseSensitive); }); it("PreferCaseSensitiveMiddleUnderscore2", () => { - const match = getFirstMatch("Fog_Bar", "F_B"); + const match = getFirstMatch("Fog_Bar", "F_B")!; assert.equal(ts.PatternMatchKind.camelCase, match.kind); assert.equal(true, match.isCaseSensitive); @@ -224,41 +224,41 @@ describe("PatternMatcher", () => { }); it("PreferCaseSensitiveMiddleUnderscore4", () => { - const match = getFirstMatch("Fog_Bar", "f_B"); + const match = getFirstMatch("Fog_Bar", "f_B")!; assert.equal(ts.PatternMatchKind.camelCase, match.kind); assert.equal(false, match.isCaseSensitive); }); it("PreferCaseSensitiveMiddleUnderscore5", () => { - const match = getFirstMatch("Fog_Bar", "F_b"); + const match = getFirstMatch("Fog_Bar", "F_b")!; assert.equal(ts.PatternMatchKind.camelCase, match.kind); assert.equal(false, match.isCaseSensitive); }); it("PreferCaseSensitiveRelativeWeights1", () => { - const match1 = getFirstMatch("FogBarBaz", "FB"); - const match2 = getFirstMatch("FooFlobBaz", "FB"); + const match1 = getFirstMatch("FogBarBaz", "FB")!; + const match2 = getFirstMatch("FooFlobBaz", "FB")!; // We should prefer something that starts at the beginning if possible - assertInRange(match1.camelCaseWeight, match2.camelCaseWeight + 1, 1 << 30); + assertInRange(match1.camelCaseWeight!, match2.camelCaseWeight! + 1, 1 << 30); }); it("PreferCaseSensitiveRelativeWeights2", () => { - const match1 = getFirstMatch("BazBarFooFooFoo", "FFF"); - const match2 = getFirstMatch("BazFogBarFooFoo", "FFF"); + const match1 = getFirstMatch("BazBarFooFooFoo", "FFF")!; + const match2 = getFirstMatch("BazFogBarFooFoo", "FFF")!; // Contiguous things should also be preferred - assertInRange(match1.camelCaseWeight, match2.camelCaseWeight + 1, 1 << 30); + assertInRange(match1.camelCaseWeight!, match2.camelCaseWeight! + 1, 1 << 30); }); it("PreferCaseSensitiveRelativeWeights3", () => { - const match1 = getFirstMatch("FogBarFooFoo", "FFF"); - const match2 = getFirstMatch("BarFooFooFoo", "FFF"); + const match1 = getFirstMatch("FogBarFooFoo", "FFF")!; + const match2 = getFirstMatch("BarFooFooFoo", "FFF")!; // The weight of being first should be greater than the weight of being contiguous - assertInRange(match1.camelCaseWeight, match2.camelCaseWeight + 1, 1 << 30); + assertInRange(match1.camelCaseWeight!, match2.camelCaseWeight! + 1, 1 << 30); }); it("AllLowerPattern1", () => { @@ -288,81 +288,81 @@ describe("PatternMatcher", () => { describe("MultiWordPattern", () => { it("ExactWithLowercase", () => { - const matches = getAllMatches("AddMetadataReference", "addmetadatareference"); + const matches = getAllMatches("AddMetadataReference", "addmetadatareference")!; assertContainsKind(ts.PatternMatchKind.exact, matches); }); it("SingleLowercasedSearchWord1", () => { - const matches = getAllMatches("AddMetadataReference", "add"); + const matches = getAllMatches("AddMetadataReference", "add")!; assertContainsKind(ts.PatternMatchKind.prefix, matches); }); it("SingleLowercasedSearchWord2", () => { - const matches = getAllMatches("AddMetadataReference", "metadata"); + const matches = getAllMatches("AddMetadataReference", "metadata")!; assertContainsKind(ts.PatternMatchKind.substring, matches); }); it("SingleUppercaseSearchWord1", () => { - const matches = getAllMatches("AddMetadataReference", "Add"); + const matches = getAllMatches("AddMetadataReference", "Add")!; assertContainsKind(ts.PatternMatchKind.prefix, matches); }); it("SingleUppercaseSearchWord2", () => { - const matches = getAllMatches("AddMetadataReference", "Metadata"); + const matches = getAllMatches("AddMetadataReference", "Metadata")!; assertContainsKind(ts.PatternMatchKind.substring, matches); }); it("SingleUppercaseSearchLetter1", () => { - const matches = getAllMatches("AddMetadataReference", "A"); + const matches = getAllMatches("AddMetadataReference", "A")!; assertContainsKind(ts.PatternMatchKind.prefix, matches); }); it("SingleUppercaseSearchLetter2", () => { - const matches = getAllMatches("AddMetadataReference", "M"); + const matches = getAllMatches("AddMetadataReference", "M")!; assertContainsKind(ts.PatternMatchKind.substring, matches); }); it("TwoLowercaseWords", () => { - const matches = getAllMatches("AddMetadataReference", "add metadata"); + const matches = getAllMatches("AddMetadataReference", "add metadata")!; assertContainsKind(ts.PatternMatchKind.prefix, matches); assertContainsKind(ts.PatternMatchKind.substring, matches); }); it("TwoLowercaseWords", () => { - const matches = getAllMatches("AddMetadataReference", "A M"); + const matches = getAllMatches("AddMetadataReference", "A M")!; assertContainsKind(ts.PatternMatchKind.prefix, matches); assertContainsKind(ts.PatternMatchKind.substring, matches); }); it("TwoLowercaseWords", () => { - const matches = getAllMatches("AddMetadataReference", "AM"); + const matches = getAllMatches("AddMetadataReference", "AM")!; assertContainsKind(ts.PatternMatchKind.camelCase, matches); }); it("TwoLowercaseWords", () => { - const matches = getAllMatches("AddMetadataReference", "ref Metadata"); + const matches = getAllMatches("AddMetadataReference", "ref Metadata")!; assertArrayEquals(ts.map(matches, m => m.kind), [ts.PatternMatchKind.substring, ts.PatternMatchKind.substring]); }); it("TwoLowercaseWords", () => { - const matches = getAllMatches("AddMetadataReference", "ref M"); + const matches = getAllMatches("AddMetadataReference", "ref M")!; assertArrayEquals(ts.map(matches, m => m.kind), [ts.PatternMatchKind.substring, ts.PatternMatchKind.substring]); }); it("MixedCamelCase", () => { - const matches = getAllMatches("AddMetadataReference", "AMRe"); + const matches = getAllMatches("AddMetadataReference", "AMRe")!; assertContainsKind(ts.PatternMatchKind.camelCase, matches); }); @@ -380,21 +380,21 @@ describe("PatternMatcher", () => { }); it("EachWordSeparately1", () => { - const matches = getAllMatches("AddMetadataReference", "add Meta"); + const matches = getAllMatches("AddMetadataReference", "add Meta")!; assertContainsKind(ts.PatternMatchKind.prefix, matches); assertContainsKind(ts.PatternMatchKind.substring, matches); }); it("EachWordSeparately2", () => { - const matches = getAllMatches("AddMetadataReference", "Add meta"); + const matches = getAllMatches("AddMetadataReference", "Add meta")!; assertContainsKind(ts.PatternMatchKind.prefix, matches); assertContainsKind(ts.PatternMatchKind.substring, matches); }); it("EachWordSeparately3", () => { - const matches = getAllMatches("AddMetadataReference", "Add Meta"); + const matches = getAllMatches("AddMetadataReference", "Add Meta")!; assertContainsKind(ts.PatternMatchKind.prefix, matches); assertContainsKind(ts.PatternMatchKind.substring, matches); @@ -413,7 +413,7 @@ describe("PatternMatcher", () => { }); it("AsteriskSplit", () => { - const matches = getAllMatches("GetKeyWord", "K*W"); + const matches = getAllMatches("GetKeyWord", "K*W")!; assertArrayEquals(ts.map(matches, m => m.kind), [ts.PatternMatchKind.substring, ts.PatternMatchKind.substring]); }); @@ -425,7 +425,7 @@ describe("PatternMatcher", () => { }); it("LowercaseSubstring2", () => { - const matches = getAllMatches("FooAttribute", "a"); + const matches = getAllMatches("FooAttribute", "a")!; assertContainsKind(ts.PatternMatchKind.substring, matches); assert.isFalse(matches[0].isCaseSensitive); }); @@ -433,7 +433,7 @@ describe("PatternMatcher", () => { describe("DottedPattern", () => { it("DottedPattern1", () => { - const match = getFirstMatchForDottedPattern("Foo.Bar.Baz", "Quux", "B.Q"); + const match = getFirstMatchForDottedPattern("Foo.Bar.Baz", "Quux", "B.Q")!; assert.equal(ts.PatternMatchKind.prefix, match.kind); assert.equal(true, match.isCaseSensitive); @@ -445,19 +445,19 @@ describe("PatternMatcher", () => { }); it("DottedPattern3", () => { - const match = getFirstMatchForDottedPattern("Foo.Bar.Baz", "Quux", "B.B.Q"); + const match = getFirstMatchForDottedPattern("Foo.Bar.Baz", "Quux", "B.B.Q")!; assert.equal(ts.PatternMatchKind.prefix, match.kind); assert.equal(true, match.isCaseSensitive); }); it("DottedPattern4", () => { - const match = getFirstMatchForDottedPattern("Foo.Bar.Baz", "Quux", "Baz.Quux"); + const match = getFirstMatchForDottedPattern("Foo.Bar.Baz", "Quux", "Baz.Quux")!; assert.equal(ts.PatternMatchKind.exact, match.kind); assert.equal(true, match.isCaseSensitive); }); it("DottedPattern5", () => { - const match = getFirstMatchForDottedPattern("Foo.Bar.Baz", "Quux", "F.B.B.Quux"); + const match = getFirstMatchForDottedPattern("Foo.Bar.Baz", "Quux", "F.B.B.Quux")!; assert.equal(ts.PatternMatchKind.exact, match.kind); assert.equal(true, match.isCaseSensitive); }); @@ -474,16 +474,16 @@ describe("PatternMatcher", () => { }); }); - function getFirstMatch(candidate: string, pattern: string): ts.PatternMatch { + function getFirstMatch(candidate: string, pattern: string): ts.PatternMatch | undefined { const matches = ts.createPatternMatcher(pattern).getMatchesForLastSegmentOfPattern(candidate); return matches ? matches[0] : undefined; } - function getAllMatches(candidate: string, pattern: string): ts.PatternMatch[] { + function getAllMatches(candidate: string, pattern: string): ts.PatternMatch[] | undefined { return ts.createPatternMatcher(pattern).getMatchesForLastSegmentOfPattern(candidate); } - function getFirstMatchForDottedPattern(dottedContainer: string, candidate: string, pattern: string): ts.PatternMatch { + function getFirstMatchForDottedPattern(dottedContainer: string, candidate: string, pattern: string): ts.PatternMatch | undefined { const matches = ts.createPatternMatcher(pattern).getMatches(dottedContainer.split("."), candidate); return matches ? matches[0] : undefined; } @@ -521,6 +521,6 @@ describe("PatternMatcher", () => { } function assertContainsKind(kind: ts.PatternMatchKind, results: ts.PatternMatch[]) { - assert.isTrue(ts.forEach(results, r => r.kind === kind)); + assert.isTrue(results.some(r => r.kind === kind)); } }); diff --git a/src/harness/unittests/session.ts b/src/harness/unittests/session.ts index 765fc29ee49b7..0bbca21547f1b 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 } }; @@ -436,7 +436,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"); } @@ -448,7 +448,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, @@ -495,7 +495,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, @@ -563,7 +563,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, @@ -599,7 +599,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 6d38fbb5198c9..e363b79abaf14 100644 --- a/src/harness/unittests/symbolWalker.ts +++ b/src/harness/unittests/symbolWalker.ts @@ -8,13 +8,14 @@ namespace ts { unitName: "main.ts", content: source }], [], {}, {}, "/"); - let file = result.program.getSourceFile("main.ts"); + let file = result.program.getSourceFile("main.ts")!; let checker = result.program.getTypeChecker(); verifier(file, checker); - result = undefined; - file = undefined; - checker = undefined; + // TODO: GH#18217 GH#20039 These writes are unused... + result = undefined!; + file = undefined!; + checker = undefined!; }); } @@ -40,7 +41,7 @@ export default function foo(a: number, b: Bar): void {}`, (file, checker) => { foundCount++; return true; }); - const symbols = checker.getExportsOfModule(file.symbol); + const symbols = checker.getExportsOfModule(file.symbol!); for (const symbol of symbols) { walker.walkSymbol(symbol); } diff --git a/src/harness/unittests/textChanges.ts b/src/harness/unittests/textChanges.ts index e3f67b8c513b5..d577525018250 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; } @@ -91,7 +91,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, @@ -108,11 +108,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 64f0a19b32d65..ec2942cbb3249 100644 --- a/src/harness/unittests/transform.ts +++ b/src/harness/unittests/transform.ts @@ -139,7 +139,7 @@ namespace ts { return (sourceFile: ts.SourceFile) => { const result = getMutableClone(sourceFile); result.statements = ts.createNodeArray([ - ts.createClassDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, "Foo", /*typeParameters*/ undefined, /*heritageClauses*/ undefined, /*members*/ undefined), + ts.createClassDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, "Foo", /*typeParameters*/ undefined, /*heritageClauses*/ undefined, /*members*/ undefined!), // TODO: GH#18217 ts.createModuleDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createIdentifier("Foo"), createModuleBlock([createEmptyStatement()])) ]); return result; diff --git a/src/harness/unittests/transpile.ts b/src/harness/unittests/transpile.ts index 7c4af8be16786..6ae30eb397b33 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 b7a477b04bf1f..cdd055be7ed45 100644 --- a/src/harness/unittests/tscWatchMode.ts +++ b/src/harness/unittests/tscWatchMode.ts @@ -103,6 +103,8 @@ namespace ts.tscWatch { assertWatchDiagnosticAt(host, errors.length, Diagnostics.Starting_compilation_in_watch_mode); index = 0; break; + default: + throw Debug.assertNever(errorsPosition); } forEach(errors, error => { @@ -133,7 +135,7 @@ namespace ts.tscWatch { return ` - ${flattenDiagnosticMessageText(getLocaleSpecificMessage(diagnosticMessage), host.newLine)}${host.newLine + host.newLine + host.newLine}`; } - 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, @@ -167,7 +169,7 @@ namespace ts.tscWatch { function getUnknownCompilerOption(program: Program, configFile: FileOrFolder, 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 { @@ -177,13 +179,13 @@ 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); } function getDiagnosticModuleNotFoundOfFile(program: Program, file: FileOrFolder, moduleName: string) { const quotedModuleName = `"${moduleName}"`; - return getDiagnosticOfFileFromProgram(program, file.path, file.content.indexOf(quotedModuleName), quotedModuleName.length, Diagnostics.Cannot_find_module_0, moduleName); + return getDiagnosticOfFileFromProgram(program, file.path, file.content!.indexOf(quotedModuleName), quotedModuleName.length, Diagnostics.Cannot_find_module_0, moduleName); } describe("tsc-watch program updates", () => { @@ -347,8 +349,8 @@ namespace ts.tscWatch { checkProgramRootFiles(watch(), [file1.path]); checkProgramActualFiles(watch(), [file1.path, libFile.path]); checkOutputErrors(host, [ - getDiagnosticOfFileFromProgram(watch(), file1.path, file1.content.indexOf(commonFile2Name), commonFile2Name.length, Diagnostics.File_0_not_found, commonFile2.path), - getDiagnosticOfFileFromProgram(watch(), file1.path, file1.content.indexOf("y"), 1, Diagnostics.Cannot_find_name_0, "y") + getDiagnosticOfFileFromProgram(watch(), file1.path, file1.content!.indexOf(commonFile2Name), commonFile2Name.length, Diagnostics.File_0_not_found, commonFile2.path), + getDiagnosticOfFileFromProgram(watch(), file1.path, file1.content!.indexOf("y"), 1, Diagnostics.Cannot_find_name_0, "y") ], /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting); host.reloadFS([file1, commonFile2, libFile]); @@ -1042,8 +1044,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(); checkOutputErrors(host, intialErrors, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting); @@ -1053,8 +1055,8 @@ namespace ts.tscWatch { host.runQueuedTimeoutCallbacks(); const nowErrors = errors(); checkOutputErrors(host, nowErrors, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected); - 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", () => { @@ -1322,7 +1324,7 @@ namespace ts.tscWatch { } function getFile(fileName: string) { - return find(files, file => file.path === fileName); + return find(files, file => file.path === fileName)!; } function verifyAffectedAllFiles() { @@ -2087,7 +2089,7 @@ declare module "fs" { return { path: removeFileExtension(file.path.replace(configDir, outDirFolder)) + Extension.Js, isExpectedToEmit: true, - content: '"use strict";\nexports.__esModule = true;\n' + file.content.replace("import", "var") + "\n" + content: '"use strict";\nexports.__esModule = true;\n' + file.content!.replace("import", "var") + "\n" }; } }); diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index e09dff2a6d5dd..427ac358a3232 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -54,7 +54,7 @@ namespace ts.projectSystem { msg: noop, startGroup: noop, endGroup: noop, - getLogFileName: (): string => undefined + getLogFileName: () => undefined, }; export class TestTypingsInstaller extends TI.TypingsInstaller implements server.ITypingsInstaller { @@ -178,7 +178,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) { @@ -189,8 +189,7 @@ namespace ts.projectSystem { } return true; }); - assert.isDefined(eventData); - return eventData; + return Debug.assertDefined(eventData); } hasZeroEvent(eventName: T["eventName"]) { @@ -276,7 +275,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, @@ -318,7 +317,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) { @@ -386,7 +385,7 @@ namespace ts.projectSystem { } function checkOpenFiles(projectService: server.ProjectService, expectedFiles: FileOrFolder[]) { - checkFileNames("Open files", arrayFrom(projectService.openFiles.keys(), path => projectService.getScriptInfoForPath(path as Path).fileName), expectedFiles.map(file => file.path)); + checkFileNames("Open files", arrayFrom(projectService.openFiles.keys(), path => projectService.getScriptInfoForPath(path as Path)!.fileName), expectedFiles.map(file => file.path)); } /** @@ -396,7 +395,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; @@ -1042,15 +1041,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); }); @@ -1118,7 +1117,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); @@ -1152,7 +1151,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); @@ -1321,13 +1320,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, { includeExternalModuleExports: false, includeInsertTextCompletions: false }); + const completions1 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 2, { includeExternalModuleExports: false, includeInsertTextCompletions: false })!; // 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, { includeExternalModuleExports: false, includeInsertTextCompletions: false }); + const completions2 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 2, { includeExternalModuleExports: false, includeInsertTextCompletions: false })!; // 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'"); @@ -1353,13 +1352,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, { includeExternalModuleExports: false, includeInsertTextCompletions: false }); + const completions1 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 0, { includeExternalModuleExports: false, includeInsertTextCompletions: false })!; 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, { includeExternalModuleExports: false, includeInsertTextCompletions: false }); + const completions2 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 0, { includeExternalModuleExports: false, includeInsertTextCompletions: false })!; 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, ""); }); @@ -1845,8 +1844,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], [], []); }); @@ -2130,7 +2129,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}"`); @@ -2138,12 +2137,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}"`); }); @@ -2181,7 +2180,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); }); @@ -2208,9 +2207,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); @@ -2219,12 +2218,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 }); @@ -2284,10 +2283,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]; @@ -2357,7 +2356,7 @@ namespace ts.projectSystem { function verifyConfiguredProjectStateAfterUpdate(hasOpenRef: boolean) { checkNumberOfConfiguredProjects(projectService, 1); - 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); @@ -2396,7 +2395,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]; @@ -2496,7 +2495,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()); @@ -2508,7 +2507,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}'`); } @@ -2551,7 +2550,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 => { @@ -2603,7 +2602,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 => { @@ -2693,7 +2692,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; @@ -2766,7 +2765,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)); @@ -2827,7 +2826,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]); @@ -2884,7 +2883,7 @@ namespace ts.projectSystem { checkProjectActualFiles(project, [file.path, libFile.path]); assert.strictEqual(projectService.getDefaultProjectForFile(server.toNormalizedPath(file.path), /*ensureProject*/ true), project); - const indexOfX = file.content.indexOf("x"); + const indexOfX = file.content!.indexOf("x"); assert.deepEqual(project.getLanguageService(/*ensureSynchronized*/ true).getQuickInfoAtPosition(file.path, indexOfX), { kind: ScriptElementKind.variableElement, kindModifiers: "", @@ -2932,7 +2931,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 @@ -2969,7 +2968,7 @@ namespace ts.projectSystem { arguments: { file: filesFile1.path, line: 1, - offset: filesFile1.content.indexOf("a") + offset: filesFile1.content!.indexOf("a") } }); @@ -2996,7 +2995,7 @@ namespace ts.projectSystem { }, startGroup: noop, endGroup: noop, - getLogFileName: (): string => undefined + getLogFileName: () => undefined }; return { errorLogger, @@ -3019,7 +3018,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]); }); @@ -3470,7 +3469,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); @@ -3619,7 +3618,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 @@ -3703,7 +3702,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)); } }); @@ -3935,7 +3934,7 @@ namespace ts.projectSystem { host.runQueuedImmediateCallbacks(); const moduleNotFound = Diagnostics.Cannot_find_module_0; - const startOffset = file1.content.indexOf('"') + 1; + const startOffset = file1.content!.indexOf('"') + 1; checkErrorMessage(session, "semanticDiag", { file: file1.path, diagnostics: [{ start: { line: 1, offset: startOffset }, @@ -4424,7 +4423,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 @@ -4436,7 +4435,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"); }); @@ -4461,7 +4460,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"); @@ -5527,7 +5526,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; @@ -5549,7 +5548,7 @@ namespace ts.projectSystem { ts.TestFSWithWatch.verifyMapSize(callback, calledMap, arrayFrom(expectedKeys.keys())); expectedKeys.forEach((called, name) => { assert.isTrue(calledMap.has(name), `${callback} is expected to contain ${name}, actual keys: ${arrayFrom(calledMap.keys())}`); - assert.equal(calledMap.get(name).length, called, `${callback} is expected to be called ${called} times with ${name}. Actual entry: ${calledMap.get(name)}`); + assert.equal(calledMap.get(name)!.length, called, `${callback} is expected to be called ${called} times with ${name}. Actual entry: ${calledMap.get(name)}`); }); } @@ -5787,7 +5786,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); @@ -5795,9 +5794,9 @@ namespace ts.projectSystem { // Get definitions shouldnt make host requests const getDefinitionRequest = makeSessionRequest(protocol.CommandTypes.Definition, { file: clientFile.path, - position: clientFile.content.indexOf("/vessel") + 1, - line: undefined, - offset: undefined + position: clientFile.content!.indexOf("/vessel") + 1, + 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)); @@ -5873,11 +5872,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 ts.server.NormalizedPath, `should find config`); // 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); @@ -5979,7 +5978,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 ts.server.NormalizedPath, `should find config`); // TODO: GH#18217 const recursiveWatchedDirectories: string[] = [appFolder].concat(getNodeModuleDirectories(getDirectoryPath(appFolder))); verifyProject(); @@ -6058,7 +6057,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 @@ -6079,7 +6078,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); @@ -6276,7 +6275,7 @@ namespace ts.projectSystem { content: JSON.stringify(configObj || { compilerOptions: {} }) }; - const files = [file1Consumer1, moduleFile1, file1Consumer2, moduleFile2, ...additionalFiles, globalFile3, libFile, configFile]; + const files: FileOrFolder[] = [file1Consumer1, moduleFile1, file1Consumer2, moduleFile2, ...additionalFiles, globalFile3, libFile, configFile]; const filesToReload = firstReloadFileList && getFiles(firstReloadFileList) || files; const host = createServerHost([filesToReload[0], configFile]); @@ -6302,7 +6301,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?: FileOrFolder[]) { @@ -6329,7 +6328,7 @@ namespace ts.projectSystem { file: file.path, insertString: newContent, endLine: 1, - endOffset: file.content.length, + endOffset: file.content!.length, line: 1, offset: 1 } @@ -6550,7 +6549,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; @@ -6715,7 +6714,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)); diff --git a/src/harness/unittests/typingsInstaller.ts b/src/harness/unittests/typingsInstaller.ts index b5265c5e5f290..ec7cad70bb72e 100644 --- a/src/harness/unittests/typingsInstaller.ts +++ b/src/harness/unittests/typingsInstaller.ts @@ -1419,7 +1419,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${ts.versionMajorMinor}`] = "1.3.0-next.1"; + registry.get("node")![`ts${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(), [ @@ -1507,8 +1507,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") }); @@ -1555,8 +1555,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") }); @@ -1583,8 +1583,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]); }); diff --git a/src/harness/unittests/versionCache.ts b/src/harness/unittests/versionCache.ts index 3062a55170c18..87f974be3ef37 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/virtualFileSystem.ts b/src/harness/virtualFileSystem.ts index 16267a092fce4..04f842a57889d 100644 --- a/src/harness/virtualFileSystem.ts +++ b/src/harness/virtualFileSystem.ts @@ -23,7 +23,7 @@ namespace Utils { export abstract class VirtualFileSystemContainer extends VirtualFileSystemEntry { abstract getFileSystemEntries(): VirtualFileSystemEntry[]; - getFileSystemEntry(name: string): VirtualFileSystemEntry { + getFileSystemEntry(name: string): VirtualFileSystemEntry | undefined { for (const entry of this.getFileSystemEntries()) { if (this.fileSystem.sameName(entry.name, name)) { return entry; @@ -40,13 +40,13 @@ namespace Utils { return ts.filter(this.getFileSystemEntries(), entry => entry.isFile()); } - getDirectory(name: string): VirtualDirectory { - const entry = this.getFileSystemEntry(name); + getDirectory(name: string): VirtualDirectory | undefined { + const entry = this.getFileSystemEntry(name)!; return entry.isDirectory() ? entry : undefined; } - getFile(name: string): VirtualFile { - const entry = this.getFileSystemEntry(name); + getFile(name: string): VirtualFile | undefined { + const entry = this.getFileSystemEntry(name)!; return entry.isFile() ? entry : undefined; } } @@ -58,7 +58,7 @@ namespace Utils { getFileSystemEntries() { return this.entries.slice(); } - addDirectory(name: string): VirtualDirectory { + addDirectory(name: string): VirtualDirectory | undefined { const entry = this.getFileSystemEntry(name); if (entry === undefined) { const directory = new VirtualDirectory(this.fileSystem, name); @@ -73,7 +73,7 @@ namespace Utils { } } - addFile(name: string, content?: Harness.LanguageService.ScriptInfo): VirtualFile { + addFile(name: string, content?: Harness.LanguageService.ScriptInfo): VirtualFile | undefined { const entry = this.getFileSystemEntry(name); if (entry === undefined) { const file = new VirtualFile(this.fileSystem, name); @@ -98,7 +98,7 @@ namespace Utils { useCaseSensitiveFileNames: boolean; constructor(currentDirectory: string, useCaseSensitiveFileNames: boolean) { - super(/*fileSystem*/ undefined, ""); + super(/*fileSystem*/ undefined!, ""); // TODO: GH#18217 this.fileSystem = this; this.root = new VirtualDirectory(this, ""); this.currentDirectory = currentDirectory; @@ -112,7 +112,7 @@ namespace Utils { addDirectory(path: string) { path = ts.normalizePath(path); const components = ts.getNormalizedPathComponents(path, this.currentDirectory); - let directory: VirtualDirectory = this.root; + let directory: VirtualDirectory | undefined = this.root; for (const component of components) { directory = directory.addDirectory(component); if (directory === undefined) { @@ -198,7 +198,7 @@ namespace Utils { super(currentDirectory, ignoreCase); if (files instanceof Array) { for (const file of files) { - this.addFile(file, new Harness.LanguageService.ScriptInfo(file, undefined, /*isRootFile*/false)); + this.addFile(file, new Harness.LanguageService.ScriptInfo(file, undefined!, /*isRootFile*/false)); // TODO: GH#18217 } } else { @@ -211,7 +211,7 @@ namespace Utils { readFile(path: string): string | undefined { const value = this.traversePath(path); if (value && value.isFile()) { - return value.content.content; + return value.content!.content; // TODO: GH#18217 } } diff --git a/src/harness/virtualFileSystemWithWatch.ts b/src/harness/virtualFileSystemWithWatch.ts index 93fdc6cdbc623..a8860cae1b9c4 100644 --- a/src/harness/virtualFileSystemWithWatch.ts +++ b/src/harness/virtualFileSystemWithWatch.ts @@ -470,13 +470,13 @@ interface Array {}` this.invokeFileWatcher(fileOrDirectory.fullPath, FileWatcherEventKind.Deleted); } else { - Debug.assert(fileOrDirectory.entries.length === 0 || isRenaming); + Debug.assert(fileOrDirectory.entries.length === 0 || isRenaming!); const relativePath = this.getRelativePathToDirectory(fileOrDirectory.fullPath, fileOrDirectory.fullPath); // Invoke directory and recursive directory watcher for the folder // Here we arent invoking recursive directory watchers for the base folders // since that is something we would want to do for both file as well as folder we are deleting - invokeWatcherCallbacks(this.watchedDirectories.get(fileOrDirectory.path), cb => this.directoryCallback(cb, relativePath)); - invokeWatcherCallbacks(this.watchedDirectoriesRecursive.get(fileOrDirectory.path), cb => this.directoryCallback(cb, relativePath)); + invokeWatcherCallbacks(this.watchedDirectories.get(fileOrDirectory.path)!, cb => this.directoryCallback(cb, relativePath)); + invokeWatcherCallbacks(this.watchedDirectoriesRecursive.get(fileOrDirectory.path)!, cb => this.directoryCallback(cb, relativePath)); } if (basePath !== fileOrDirectory.path) { @@ -490,7 +490,7 @@ interface Array {}` } private invokeFileWatcher(fileFullPath: string, eventKind: FileWatcherEventKind) { - const callbacks = this.watchedFiles.get(this.toPath(fileFullPath)); + const callbacks = this.watchedFiles.get(this.toPath(fileFullPath))!; invokeWatcherCallbacks(callbacks, ({ cb }) => cb(fileFullPath, eventKind)); } @@ -503,7 +503,7 @@ interface Array {}` */ private invokeDirectoryWatcher(folderFullPath: string, fileName: string) { const relativePath = this.getRelativePathToDirectory(folderFullPath, fileName); - invokeWatcherCallbacks(this.watchedDirectories.get(this.toPath(folderFullPath)), cb => this.directoryCallback(cb, relativePath)); + invokeWatcherCallbacks(this.watchedDirectories.get(this.toPath(folderFullPath))!, cb => this.directoryCallback(cb, relativePath)); this.invokeRecursiveDirectoryWatcher(folderFullPath, fileName); } @@ -516,7 +516,7 @@ interface Array {}` */ private invokeRecursiveDirectoryWatcher(fullPath: string, fileName: string) { const relativePath = this.getRelativePathToDirectory(fullPath, fileName); - invokeWatcherCallbacks(this.watchedDirectoriesRecursive.get(this.toPath(fullPath)), cb => this.directoryCallback(cb, relativePath)); + invokeWatcherCallbacks(this.watchedDirectoriesRecursive.get(this.toPath(fullPath))!, cb => this.directoryCallback(cb, relativePath)); const basePath = getDirectoryPath(fullPath); if (this.getCanonicalFileName(fullPath) !== this.getCanonicalFileName(basePath)) { this.invokeRecursiveDirectoryWatcher(basePath, fileName); @@ -527,7 +527,7 @@ interface Array {}` const fullPath = getNormalizedAbsolutePath(fileOrDirectory.path, this.currentDirectory); return { path: this.toPath(fullPath), - content: fileOrDirectory.content, + content: fileOrDirectory.content!, // TODO: GH#18217 fullPath, fileSize: fileOrDirectory.fileSize }; @@ -538,7 +538,7 @@ interface Array {}` return { path: this.toPath(fullPath), fullPath, - symLink: getNormalizedAbsolutePath(fileOrDirectory.symLink, getDirectoryPath(fullPath)) + symLink: getNormalizedAbsolutePath(fileOrDirectory.symLink!, getDirectoryPath(fullPath)) }; } @@ -551,7 +551,7 @@ interface Array {}` }; } - 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; } @@ -594,18 +594,18 @@ interface Array {}` return !!this.getRealFile(path); } - readFile(s: string): string { - const fsEntry = this.getRealFile(this.toFullPath(s)); + 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 (isFile(entry)) { return entry.fileSize ? entry.fileSize : entry.content.length; } - return undefined; + return undefined!; // TODO: GH#18217 } directoryExists(s: string) { @@ -768,7 +768,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 (isSymLink(fsEntry)) { return this.realpath(fsEntry.symLink); } @@ -777,7 +777,7 @@ interface Array {}` } readonly existMessage = "System Exit"; - exitCode: number; + exitCode: number | undefined; readonly resolvePath = (s: string) => s; readonly getExecutingFilePath = () => this.executingFilePath; readonly getCurrentDirectory = () => this.currentDirectory; 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 cee65c0e5a485..e20758a286c99 100644 --- a/src/server/client.ts +++ b/src/server/client.ts @@ -52,7 +52,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; @@ -91,10 +91,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 { @@ -135,7 +134,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); @@ -146,14 +145,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 }; } @@ -164,13 +164,13 @@ 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 }; } getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions | undefined): CompletionInfo { - const args: protocol.CompletionsRequestArgs = { ...this.createFileLocationRequestArgs(fileName, position), ...options }; + const args = { ...this.createFileLocationRequestArgs(fileName, position), ...options } as protocol.CompletionsRequestArgs; // TODO: GH#18217 const request = this.processRequest(CommandNames.Completions, args); const response = this.processResponse(request); @@ -179,7 +179,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 @@ -197,10 +197,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 { @@ -216,14 +215,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), })); @@ -237,11 +236,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): ts.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): ts.TextChange[] { @@ -251,7 +250,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[] { @@ -260,7 +259,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, @@ -277,7 +276,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, @@ -285,7 +284,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) }; } @@ -295,7 +294,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, @@ -311,7 +310,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, @@ -330,7 +329,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, @@ -361,7 +360,7 @@ namespace ts.server { } convertDiagnostic(entry: protocol.DiagnosticWithLinePosition, _fileName: string): Diagnostic { - let category: DiagnosticCategory; + let category: DiagnosticCategory | undefined; for (const id in DiagnosticCategory) { if (isString(id) && entry.category === id.toLowerCase()) { category = (DiagnosticCategory)[id]; @@ -375,7 +374,7 @@ namespace ts.server { start: entry.start, length: entry.length, messageText: entry.message, - category, + category: category!, code: entry.code }; } @@ -389,8 +388,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 }); @@ -398,17 +398,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, }; } @@ -425,7 +425,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 []; } @@ -465,7 +465,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; @@ -493,7 +493,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; @@ -509,7 +509,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, @@ -523,7 +523,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), @@ -558,7 +558,7 @@ namespace ts.server { const request = this.processRequest(CommandNames.GetCodeFixes, args); const response = this.processResponse(request); - return response.body.map(({ description, changes, fixId }) => ({ description, changes: this.convertChanges(changes, file), fixId })); + return response.body!.map(({ description, changes, fixId }) => ({ description, changes: this.convertChanges(changes, file), fixId })); } getCombinedCodeFix = notImplemented; @@ -593,7 +593,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( @@ -619,7 +619,7 @@ namespace ts.server { const renameFilename: string | undefined = response.body.renameFilename; let renameLocation: number | undefined = undefined; if (renameFilename !== undefined) { - renameLocation = this.lineOffsetToPosition(renameFilename, response.body.renameLocation); + renameLocation = this.lineOffsetToPosition(renameFilename, response.body.renameLocation!); // TODO: GH#18217 } return { @@ -663,7 +663,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 c525d5a3bc821..505ab6271b943 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -64,7 +64,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; @@ -212,13 +212,13 @@ namespace ts.server { interface FilePropertyReader { getFileName(f: T): string; getScriptKind(f: T, extraFileExtensions?: JsFileExtensionInfo[]): ScriptKind; - hasMixedContent(f: T, extraFileExtensions: JsFileExtensionInfo[]): boolean; + hasMixedContent(f: T, extraFileExtensions: JsFileExtensionInfo[] | 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) { @@ -231,18 +231,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; @@ -507,7 +507,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; @@ -591,7 +591,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); @@ -639,7 +639,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); } @@ -659,7 +659,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(); @@ -669,7 +669,7 @@ namespace ts.server { } return scriptInfo.getDefaultProject(); } - return scriptInfo && !scriptInfo.isOrphan() && scriptInfo.getDefaultProject(); + return scriptInfo && !scriptInfo.isOrphan() ? scriptInfo.getDefaultProject() : undefined; } getScriptInfoEnsuringProjectsUptoDate(uncheckedFileName: string) { @@ -704,7 +704,7 @@ namespace ts.server { } getFormatCodeOptions(file?: NormalizedPath) { - let formatCodeSettings: FormatCodeSettings; + let formatCodeSettings: FormatCodeSettings | undefined; if (file) { const info = this.getScriptInfoForNormalizedPath(file); if (info) { @@ -789,7 +789,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) { @@ -825,7 +825,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); @@ -915,7 +915,7 @@ namespace ts.server { // collect all projects that should be removed - let projectsToRemove: Project[]; + let projectsToRemove: Project[] | undefined; for (const p of info.containingProjects) { if (p.projectKind === ProjectKind.Configured) { if (info.hasMixedContent) { @@ -950,7 +950,7 @@ namespace ts.server { // collect orphaned files and assign them to inferred project just like we treat open of a file this.openFiles.forEach((projectRootPath, path) => { - const f = this.getScriptInfoForPath(path as Path); + const f = this.getScriptInfoForPath(path as Path)!; if (f.isOrphan()) { this.assignOrphanScriptInfoToInferredProject(f, projectRootPath); } @@ -985,7 +985,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 } } @@ -1075,7 +1075,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); }); @@ -1286,7 +1286,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())}`); @@ -1313,7 +1313,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) { @@ -1351,7 +1351,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; } @@ -1389,7 +1389,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); } @@ -1423,7 +1423,7 @@ namespace ts.server { } const data: ProjectInfoTelemetryEventData = { - projectId: this.host.createHash(projectKey), + projectId: this.host.createHash!(projectKey), // TODO: GH#18217 fileStats: countEachFileTypes(project.getScriptInfos()), compilerOptions: convertCompilerOptionsForTelemetry(project.getCompilationSettings()), typeAcquisition: convertTypeAcquisition(project.getTypeAcquisition()), @@ -1444,7 +1444,7 @@ namespace ts.server { return "other"; } - const configFilePath = project instanceof server.ConfiguredProject && project.getConfigFilePath(); + const configFilePath = project instanceof server.ConfiguredProject ? project.getConfigFilePath() : undefined; return getBaseConfigFileName(configFilePath) || "other"; } @@ -1465,16 +1465,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); @@ -1489,12 +1489,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); @@ -1514,7 +1514,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); } @@ -1524,7 +1524,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)) { @@ -1559,7 +1559,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. @@ -1574,7 +1574,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); @@ -1601,16 +1601,16 @@ namespace ts.server { // Update the project project.configFileSpecs = configFileSpecs; project.setProjectErrors(configFileErrors); - 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); } @@ -1643,7 +1643,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; @@ -1651,7 +1651,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; } @@ -1788,7 +1788,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); @@ -1802,7 +1802,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(); } @@ -1829,7 +1829,7 @@ namespace ts.server { if (args.file) { const info = this.getScriptInfoForNormalizedPath(toNormalizedPath(args.file)); if (info) { - info.setFormatOptions(convertFormatOptions(args.formatOptions)); + info.setFormatOptions(convertFormatOptions(args.formatOptions!)); // TODO: GH#18217 this.logger.info(`Host configuration update for file ${args.file}`); } } @@ -1900,7 +1900,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, @@ -1970,7 +1970,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); @@ -1996,7 +1996,7 @@ namespace ts.server { return this.openClientFileWithNormalizedPath(toNormalizedPath(fileName), fileContent, scriptKind, /*hasMixedContent*/ false, projectRootPath ? toNormalizedPath(projectRootPath) : undefined); } - private findExternalProjetContainingOpenScriptInfo(info: ScriptInfo): ExternalProject { + private findExternalProjetContainingOpenScriptInfo(info: ScriptInfo): ExternalProject | undefined { for (const proj of this.externalProjects) { // Ensure project structure is uptodate to check if info is present in external project proj.updateGraph(); @@ -2008,11 +2008,11 @@ 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); - let project: ConfiguredProject | ExternalProject = this.findExternalProjetContainingOpenScriptInfo(info); + const info = this.getOrCreateScriptInfoOpenedByClientForNormalizedPath(fileName, projectRootPath ? this.getNormalizedAbsolutePath(projectRootPath) : this.currentDirectory, fileContent, scriptKind, hasMixedContent)!; + let project: ConfiguredProject | ExternalProject | undefined = this.findExternalProjetContainingOpenScriptInfo(info); if (!project) { configFileName = this.getConfigFileNameForFile(info, projectRootPath); if (configFileName) { @@ -2047,7 +2047,7 @@ namespace ts.server { } Debug.assert(!info.isOrphan()); - this.openFiles.set(info.path, projectRootPath); + this.openFiles.set(info.path, projectRootPath!); // TODO: GH#18217 // Remove the configured projects that have zero references from open files. // This was postponed from closeOpenFile to after opening next file, @@ -2082,7 +2082,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)); } } @@ -2097,19 +2097,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); } @@ -2190,7 +2190,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) { @@ -2313,7 +2314,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); @@ -2333,7 +2334,7 @@ namespace ts.server { } const externalProject = this.findExternalProjectByProjectName(proj.projectFileName); - let exisingConfigFiles: string[]; + let exisingConfigFiles: string[] | undefined; if (externalProject) { externalProject.excludedFiles = excludedFiles; if (!tsConfigFiles) { @@ -2361,7 +2362,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) { diff --git a/src/server/project.ts b/src/server/project.ts index dc949b4b221fb..a31f1d389763f 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -124,7 +124,7 @@ namespace ts.server { private plugins: PluginModule[] = []; private cachedUnresolvedImportsPerFile = new UnresolvedImportsMap(); - private lastCachedUnresolvedImportsList: SortedReadonlyArray; + private lastCachedUnresolvedImportsList: SortedReadonlyArray | undefined; private lastFileExceededProgramSize: string | undefined; @@ -146,7 +146,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. */ @@ -192,10 +192,10 @@ namespace ts.server { return this.cachedUnresolvedImportsPerFile; } - public static resolveModule(moduleName: string, initialDir: string, host: ServerHost, log: (message: string) => void): {} { + 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}`); @@ -239,11 +239,11 @@ namespace ts.server { this.setInternalCompilerOptionsForEmittingJsFiles(); const host = this.projectService.host; 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 @@ -316,15 +316,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(); @@ -349,7 +349,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 { @@ -372,16 +372,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*/ @@ -476,8 +476,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); } /** @@ -571,25 +571,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) { @@ -622,17 +622,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!; }); } @@ -700,11 +698,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) { @@ -769,7 +768,7 @@ namespace ts.server { } return; } - let unresolvedImports: string[]; + let unresolvedImports: string[] | undefined; if (file.resolvedModules) { file.resolvedModules.forEach((resolvedModule, name) => { // pick unresolved non-relative names @@ -871,7 +870,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 hasChanges = !oldProgram || (this.program !== oldProgram && !(oldProgram.structureIsReused & StructureIsReused.Completely)); + const hasChanges = !oldProgram || (this.program !== oldProgram && !(oldProgram.structureIsReused! & StructureIsReused.Completely)); this.hasChangedAutomaticTypeDirectiveNames = false; if (hasChanges) { if (oldProgram) { @@ -900,12 +899,12 @@ namespace ts.server { const oldExternalFiles = this.externalFiles || emptyArray as SortedReadonlyArray; this.externalFiles = this.getExternalFiles(); - enumerateInsertsAndDeletes(this.externalFiles, oldExternalFiles, + enumerateInsertsAndDeletes(this.externalFiles, oldExternalFiles, // Ensure a ScriptInfo is created for new external files. This is performed indirectly // 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), @@ -1188,7 +1187,8 @@ namespace ts.server { ProjectKind.Inferred, projectService, documentRegistry, - /*files*/ undefined, + // TODO: GH#18217 + /*files*/ undefined!, /*lastFileExceededProgramSize*/ undefined, compilerOptions, /*compileOnSaveEnabled*/ false, @@ -1247,7 +1247,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; @@ -1255,12 +1255,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, @@ -1432,7 +1432,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; } @@ -1443,10 +1443,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 fbff4501133fe..c48c076755a29 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -1737,7 +1737,7 @@ namespace ts.server.protocol { export interface CompletionEntryIdentifier { name: string; - source: string; + source: string | undefined; } /** @@ -1781,7 +1781,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. @@ -1840,12 +1840,12 @@ namespace ts.server.protocol { /** * Documentation strings for the symbol. */ - documentation: SymbolDisplayPart[]; + documentation: SymbolDisplayPart[] | undefined; /** * JSDoc tags for the symbol. */ - tags: JSDocTagInfo[]; + tags: JSDocTagInfo[] | undefined; /** * The associated code actions for this entry diff --git a/src/server/scriptInfo.ts b/src/server/scriptInfo.ts index 6fc4f241f6511..776a36c0abc24 100644 --- a/src/server/scriptInfo.ts +++ b/src/server/scriptInfo.ts @@ -16,11 +16,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; /** @@ -117,7 +117,7 @@ namespace ts.server { public getSnapshot(): IScriptSnapshot { return this.useScriptVersionCacheIfValidOrOpen() - ? this.svc.getSnapshot() + ? this.svc!.getSnapshot() : ScriptSnapshot.fromString(this.getOrLoadText()); } @@ -131,10 +131,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); } /** @@ -147,7 +147,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 { @@ -155,7 +155,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) { @@ -177,7 +177,7 @@ namespace ts.server { } // Else if the svc is uptodate with the text, we are good - return !this.pendingReloadFromDisk && this.svc; + return this.pendingReloadFromDisk ? undefined : this.svc; } private getOrLoadText() { @@ -185,7 +185,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() { @@ -207,7 +207,7 @@ namespace ts.server { private formatCodeSettings: FormatCodeSettings; /* @internal */ - fileWatcher: FileWatcher; + fileWatcher: FileWatcher | undefined; private textStorage: TextStorage; /*@internal*/ @@ -281,7 +281,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 } } } @@ -330,7 +330,7 @@ namespace ts.server { break; case 2: if (this.containingProjects[0] === project) { - this.containingProjects[0] = this.containingProjects.pop(); + this.containingProjects[0] = this.containingProjects.pop()!; } else if (this.containingProjects[1] === project) { this.containingProjects.pop(); diff --git a/src/server/scriptVersionCache.ts b/src/server/scriptVersionCache.ts index 8a3f43a543462..dc79f3b939ab1 100644 --- a/src/server/scriptVersionCache.ts +++ b/src/server/scriptVersionCache.ts @@ -59,7 +59,7 @@ namespace ts.server { this.stack = [this.lineIndex.root]; } - insertLines(insertedText: string, suppressTrailingText: boolean) { + insertLines(insertedText: string | undefined, suppressTrailingText: boolean) { if (suppressTrailingText) { this.trailingText = ""; } @@ -76,8 +76,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(); @@ -92,7 +92,7 @@ namespace ts.server { } } if (lastZeroCount) { - branchParent.remove(lastZeroCount); + branchParent!.remove(lastZeroCount); } // path at least length two (root and leaf) @@ -163,7 +163,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(""); @@ -336,7 +336,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()); } @@ -374,7 +374,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; @@ -401,7 +401,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); } @@ -475,9 +475,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); @@ -503,7 +504,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; } @@ -704,7 +705,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 7f545ff38750d..70bd85a1d3db5 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -64,8 +64,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}'`); } } @@ -226,7 +225,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); @@ -262,7 +261,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, @@ -396,10 +395,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; @@ -523,7 +522,7 @@ namespace ts.server { const typingsInstaller = disableAutomaticTypingAcquisition ? undefined - : new NodeTypingsInstaller(telemetryEnabled, logger, host, globalTypingsCacheLocation, typingSafeListLocation, typesMapLocation, npmLocation, event); + : new NodeTypingsInstaller(telemetryEnabled, logger, host, globalTypingsCacheLocation, typingSafeListLocation, typesMapLocation!, npmLocation, event); // TODO: GH#18217 super({ host, @@ -607,7 +606,7 @@ namespace ts.server { logToFile?: boolean; } - function parseLoggingEnvironmentString(logEnvStr: string): LogOptions { + function parseLoggingEnvironmentString(logEnvStr: string | undefined): LogOptions { if (!logEnvStr) { return {}; } @@ -638,7 +637,7 @@ namespace ts.server { return logEnv; } - function getLogLevel(level: string) { + function getLogLevel(level: string | undefined) { if (level) { const l = level.toLowerCase(); for (const name in LogLevel) { @@ -663,7 +662,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 @@ -688,7 +687,7 @@ namespace ts.server { fs.stat(watchedFile.fileName, (err: any, stats: any) => { if (err) { if (err.code === "ENOENT") { - if (watchedFile.mtime.getTime() !== 0) { + if (watchedFile.mtime!.getTime() !== 0) { // TODO: GH#18217 watchedFile.mtime = new Date(0); watchedFile.callback(watchedFile.fileName, FileWatcherEventKind.Deleted); } @@ -698,7 +697,7 @@ namespace ts.server { } } else { - const oldTime = watchedFile.mtime.getTime(); + const oldTime = watchedFile.mtime!.getTime(); // TODO: GH#18217 const newTime = stats.mtime.getTime(); if (oldTime !== newTime) { watchedFile.mtime = stats.mtime; @@ -788,11 +787,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 @@ -827,7 +826,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 @@ -928,8 +927,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; } } @@ -941,7 +940,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 bff19d7bc232f..14fb2aaf6a484 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -73,10 +73,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: DiagnosticCategory[diag.category].toLowerCase(), @@ -91,12 +91,12 @@ 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 = DiagnosticCategory[diag.category].toLowerCase(); - return includeFileName ? { start, end, text, code, category, source, fileName: diag.file && diag.file.fileName } : + return includeFileName ? { start, end, text, code, category, source, fileName: (diag.file && diag.file.fileName)! } : // TODO: GH#18217 { start, end, text, code, category, source }; } @@ -181,7 +181,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; @@ -190,7 +190,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; @@ -227,7 +227,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); } @@ -318,7 +318,7 @@ namespace ts.server { protected logger: Logger; protected canUseEvents: boolean; - private eventHandler: ProjectServiceEventHandler; + private eventHandler: ProjectServiceEventHandler | undefined; constructor(opts: SessionOptions) { this.host = opts.host; @@ -419,7 +419,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); @@ -442,7 +442,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 { @@ -546,16 +546,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 }; } @@ -565,7 +565,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) : @@ -578,17 +578,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: DiagnosticCategory[d.category].toLowerCase(), 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 @@ -601,7 +601,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, @@ -609,8 +609,8 @@ namespace ts.server { category: DiagnosticCategory[d.category].toLowerCase(), 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!) }); } @@ -648,14 +648,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 }; } @@ -674,7 +674,7 @@ namespace ts.server { } private toFileSpan(fileName: string, textSpan: TextSpan, project: Project): protocol.FileSpan { - const scriptInfo = project.getScriptInfo(fileName); + const scriptInfo = project.getScriptInfo(fileName)!; return { file: fileName, @@ -723,7 +723,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)), @@ -745,15 +745,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 getDocumentHighlights(args: protocol.DocumentHighlightsRequestArgs, simplifiedResult: boolean): ReadonlyArray | ReadonlyArray { @@ -775,7 +775,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) @@ -798,7 +798,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 = { @@ -816,7 +816,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); @@ -825,16 +825,16 @@ 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); } // filter handles case when 'projects' is undefined - projects = filter(projects, p => p.languageServiceEnabled); + projects = filter(projects, p => p.languageServiceEnabled); // TODO: GH#18217 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) { @@ -844,11 +844,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); @@ -870,16 +870,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), @@ -893,7 +893,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) { @@ -912,9 +912,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 ); @@ -959,7 +959,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); @@ -972,7 +972,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); @@ -981,7 +981,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, ""); @@ -1009,7 +1009,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, @@ -1040,11 +1040,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); } @@ -1062,9 +1062,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 }; } @@ -1117,9 +1117,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; @@ -1144,9 +1144,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); @@ -1164,7 +1164,7 @@ namespace ts.server { private getFormattingEditsForRangeFull(args: protocol.FormatRequestArgs) { const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args); const options = args.options ? convertFormatOptions(args.options) : this.projectService.getFormatCodeOptions(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) { @@ -1176,12 +1176,12 @@ namespace ts.server { private getFormattingEditsAfterKeystrokeFull(args: protocol.FormatOnKeyRequestArgs) { const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args); const options = args.options ? convertFormatOptions(args.options) : this.projectService.getFormatCodeOptions(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.projectService.getFormatCodeOptions(file); const edits = languageService.getFormattingEditsAfterKeystroke(file, position, args.key, @@ -1203,7 +1203,7 @@ namespace ts.server { hasIndent++; } else if (lineText.charAt(i) === "\t") { - hasIndent += formatOptions.tabSize; + hasIndent += formatOptions.tabSize!; // TODO: GH#18217 } else { break; @@ -1236,12 +1236,12 @@ 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, args); - if (simplifiedResult) { - return mapDefined(completions && completions.entries, entry => { + if (completions && simplifiedResult) { + return mapDefined(completions.entries, entry => { 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; @@ -1257,7 +1257,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); @@ -1277,14 +1277,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.getCompilationSettings().noEmit) { result = { projectFileName: project.getProjectName(), @@ -1305,13 +1305,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) { @@ -1352,7 +1352,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); @@ -1360,14 +1360,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++; @@ -1404,13 +1404,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; } @@ -1431,13 +1431,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; } @@ -1461,7 +1461,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, @@ -1541,8 +1541,8 @@ namespace ts.server { } private extractPositionAndRange(args: protocol.FileLocationOrRangeRequestArgs, scriptInfo: ScriptInfo): { position: number, textRange: TextRange } { - let position: number = undefined; - let textRange: TextRange; + let position: number | undefined; + let textRange: TextRange | undefined; if (this.isLocation(args)) { position = getPosition(args); } @@ -1550,7 +1550,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); @@ -1559,14 +1559,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); } 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( @@ -1587,7 +1587,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) }; @@ -1610,17 +1610,17 @@ namespace ts.server { } } - 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) { 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 formatOptions = this.projectService.getFormatCodeOptions(file); - const codeActions = project.getLanguageService().getCodeFixesAtPosition(file, startPosition, endPosition, args.errorCodes, formatOptions); + const codeActions = project.getLanguageService().getCodeFixesAtPosition(file, startPosition, endPosition, args.errorCodes!, formatOptions); if (!codeActions) { return undefined; } @@ -1657,7 +1657,7 @@ namespace ts.server { } private getStartAndEndPosition(args: protocol.FileRangeRequestArgs, scriptInfo: ScriptInfo) { - let startPosition: number = undefined, endPosition: number = undefined; + let startPosition: number | undefined, endPosition: number | undefined; if (args.startPosition !== undefined) { startPosition = args.startPosition; } @@ -1679,12 +1679,12 @@ namespace ts.server { } private mapCodeAction(project: Project, { description, changes: unmappedChanges, commands, fixId }: CodeFixAction): protocol.CodeFixAction { - const changes = unmappedChanges.map(change => this.mapTextChangesToCodeEditsUsingScriptinfo(change, project.getScriptInfoForNormalizedPath(toNormalizedPath(change.fileName)))); + const changes = unmappedChanges.map(change => this.mapTextChangesToCodeEditsUsingScriptinfo(change, project.getScriptInfoForNormalizedPath(toNormalizedPath(change.fileName))!)); return { description, changes, commands, fixId }; } 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): protocol.FileCodeEdits { @@ -1702,9 +1702,9 @@ namespace ts.server { }; } - 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); @@ -1722,7 +1722,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; } @@ -1733,13 +1733,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); @@ -1772,7 +1772,7 @@ namespace ts.server { return { responseRequired: false }; } - private requiredResponse(response: {}): HandlerResponse { + private requiredResponse(response: {} | undefined): HandlerResponse { return { response, responseRequired: true }; } @@ -1816,7 +1816,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); }, @@ -1846,16 +1846,16 @@ namespace ts.server { return this.requiredResponse(this.getImplementation(request.arguments, /*simplifiedResult*/ false)); }, [CommandNames.References]: (request: protocol.FileLocationRequest) => { - return this.requiredResponse(this.getReferences(request.arguments, /*simplifiedResult*/ true)); + return this.requiredResponse(this.getReferences(request.arguments, /*simplifiedResult*/ true)!); // TODO: GH#18217 }, [CommandNames.ReferencesFull]: (request: protocol.FileLocationRequest) => { - return this.requiredResponse(this.getReferences(request.arguments, /*simplifiedResult*/ false)); + return this.requiredResponse(this.getReferences(request.arguments, /*simplifiedResult*/ false)!); // TODO: GH#18217 }, [CommandNames.Rename]: (request: protocol.Request) => { - return this.requiredResponse(this.getRenameLocations(request.arguments, /*simplifiedResult*/ true)); + return this.requiredResponse(this.getRenameLocations(request.arguments, /*simplifiedResult*/ true)!); // TODO: GH#18217 }, [CommandNames.RenameLocationsFull]: (request: protocol.RenameRequest) => { - return this.requiredResponse(this.getRenameLocations(request.arguments, /*simplifiedResult*/ false)); + return this.requiredResponse(this.getRenameLocations(request.arguments, /*simplifiedResult*/ false)!); // TODO: GH#18217 }, [CommandNames.RenameInfoFull]: (request: protocol.FileLocationRequest) => { return this.requiredResponse(this.getRenameInfo(request.arguments)); @@ -1864,15 +1864,15 @@ 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(); }, [CommandNames.Quickinfo]: (request: protocol.QuickInfoRequest) => { - return this.requiredResponse(this.getQuickInfoWorker(request.arguments, /*simplifiedResult*/ true)); + return this.requiredResponse(this.getQuickInfoWorker(request.arguments, /*simplifiedResult*/ true)!); // TODO: GH#18217 }, [CommandNames.QuickinfoFull]: (request: protocol.QuickInfoRequest) => { - return this.requiredResponse(this.getQuickInfoWorker(request.arguments, /*simplifiedResult*/ false)); + return this.requiredResponse(this.getQuickInfoWorker(request.arguments, /*simplifiedResult*/ false)!); // TODO: GH#18217 }, [CommandNames.OutliningSpans]: (request: protocol.FileRequest) => { return this.requiredResponse(this.getOutliningSpans(request.arguments)); @@ -1899,10 +1899,10 @@ namespace ts.server { return this.requiredResponse(this.getSpanOfEnclosingComment(request.arguments)); }, [CommandNames.Format]: (request: protocol.FormatRequest) => { - return this.requiredResponse(this.getFormattingEditsForRange(request.arguments)); + return this.requiredResponse(this.getFormattingEditsForRange(request.arguments)!); // TODO: GH#18217 }, [CommandNames.Formatonkey]: (request: protocol.FormatOnKeyRequest) => { - return this.requiredResponse(this.getFormattingEditsAfterKeystroke(request.arguments)); + return this.requiredResponse(this.getFormattingEditsAfterKeystroke(request.arguments)!); // TODO: GH#18217 }, [CommandNames.FormatFull]: (request: protocol.FormatRequest) => { return this.requiredResponse(this.getFormattingEditsForDocumentFull(request.arguments)); @@ -1914,10 +1914,10 @@ namespace ts.server { return this.requiredResponse(this.getFormattingEditsForRangeFull(request.arguments)); }, [CommandNames.Completions]: (request: protocol.CompletionsRequest) => { - return this.requiredResponse(this.getCompletions(request.arguments, /*simplifiedResult*/ true)); + return this.requiredResponse(this.getCompletions(request.arguments, /*simplifiedResult*/ true)!); // TODO: GH#18217 }, [CommandNames.CompletionsFull]: (request: protocol.CompletionsRequest) => { - return this.requiredResponse(this.getCompletions(request.arguments, /*simplifiedResult*/ false)); + return this.requiredResponse(this.getCompletions(request.arguments, /*simplifiedResult*/ false)!); // TODO: GH#18217 }, [CommandNames.CompletionDetails]: (request: protocol.CompletionDetailsRequest) => { return this.requiredResponse(this.getCompletionEntryDetails(request.arguments, /*simplifiedResult*/ true)); @@ -1932,10 +1932,10 @@ namespace ts.server { return this.requiredResponse(this.emitFile(request.arguments)); }, [CommandNames.SignatureHelp]: (request: protocol.SignatureHelpRequest) => { - return this.requiredResponse(this.getSignatureHelpItems(request.arguments, /*simplifiedResult*/ true)); + return this.requiredResponse(this.getSignatureHelpItems(request.arguments, /*simplifiedResult*/ true)!); // TODO: GH#18217 }, [CommandNames.SignatureHelpFull]: (request: protocol.SignatureHelpRequest) => { - return this.requiredResponse(this.getSignatureHelpItems(request.arguments, /*simplifiedResult*/ false)); + return this.requiredResponse(this.getSignatureHelpItems(request.arguments, /*simplifiedResult*/ false)!); // TODO: GH#18217 }, [CommandNames.CompilerOptionsDiagnosticsFull]: (request: protocol.CompilerOptionsDiagnosticsRequest) => { return this.requiredResponse(this.getCompilerOptionsDiagnostics(request.arguments)); @@ -1991,22 +1991,22 @@ namespace ts.server { return this.requiredResponse(this.getNavigateToItems(request.arguments, /*simplifiedResult*/ false)); }, [CommandNames.Brace]: (request: protocol.FileLocationRequest) => { - return this.requiredResponse(this.getBraceMatching(request.arguments, /*simplifiedResult*/ true)); + return this.requiredResponse(this.getBraceMatching(request.arguments, /*simplifiedResult*/ true)!); // TODO: GH#18217 }, [CommandNames.BraceFull]: (request: protocol.FileLocationRequest) => { - return this.requiredResponse(this.getBraceMatching(request.arguments, /*simplifiedResult*/ false)); + return this.requiredResponse(this.getBraceMatching(request.arguments, /*simplifiedResult*/ false)!); // TODO: GH#18217 }, [CommandNames.NavBar]: (request: protocol.FileRequest) => { - return this.requiredResponse(this.getNavigationBarItems(request.arguments, /*simplifiedResult*/ true)); + return this.requiredResponse(this.getNavigationBarItems(request.arguments, /*simplifiedResult*/ true)!); // TODO: GH#18217 }, [CommandNames.NavBarFull]: (request: protocol.FileRequest) => { - return this.requiredResponse(this.getNavigationBarItems(request.arguments, /*simplifiedResult*/ false)); + return this.requiredResponse(this.getNavigationBarItems(request.arguments, /*simplifiedResult*/ false)!); // TODO: GH#18217 }, [CommandNames.NavTree]: (request: protocol.FileRequest) => { - return this.requiredResponse(this.getNavigationTree(request.arguments, /*simplifiedResult*/ true)); + return this.requiredResponse(this.getNavigationTree(request.arguments, /*simplifiedResult*/ true)!); // TODO: GH#18217 }, [CommandNames.NavTreeFull]: (request: protocol.FileRequest) => { - return this.requiredResponse(this.getNavigationTree(request.arguments, /*simplifiedResult*/ false)); + return this.requiredResponse(this.getNavigationTree(request.arguments, /*simplifiedResult*/ false)!); // TODO: GH#18217 }, [CommandNames.Occurrences]: (request: protocol.FileLocationRequest) => { return this.requiredResponse(this.getOccurrences(request.arguments)); @@ -2029,10 +2029,10 @@ namespace ts.server { return this.notRequired(); }, [CommandNames.GetCodeFixes]: (request: protocol.CodeFixRequest) => { - return this.requiredResponse(this.getCodeFixes(request.arguments, /*simplifiedResult*/ true)); + return this.requiredResponse(this.getCodeFixes(request.arguments, /*simplifiedResult*/ true)!); // TODO: GH#18217 }, [CommandNames.GetCodeFixesFull]: (request: protocol.CodeFixRequest) => { - return this.requiredResponse(this.getCodeFixes(request.arguments, /*simplifiedResult*/ false)); + return this.requiredResponse(this.getCodeFixes(request.arguments, /*simplifiedResult*/ false)!); // TODO: GH#18217 }, [CommandNames.GetCombinedCodeFix]: (request: protocol.GetCombinedCodeFixRequest) => { return this.requiredResponse(this.getCombinedCodeFix(request.arguments, /*simplifiedResult*/ true)); @@ -2078,7 +2078,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); } @@ -2106,7 +2106,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)) { @@ -2114,7 +2114,7 @@ namespace ts.server { } } - let request: protocol.Request; + let request: protocol.Request | undefined; try { request = JSON.parse(message); const { response, responseRequired } = this.executeCommand(request); @@ -2139,7 +2139,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 a1d8f65f6e061..52d8619cd887e 100644 --- a/src/server/typingsCache.ts +++ b/src/server/typingsCache.ts @@ -10,7 +10,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; @@ -23,19 +23,19 @@ namespace ts.server { enqueueInstallTypingsRequest: noop, attach: noop, onProjectClosed: noop, - globalTypingsCacheLocation: undefined + globalTypingsCacheLocation: undefined! // TODO: GH#18217 }; class 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; } @@ -45,13 +45,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; @@ -75,7 +75,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; } @@ -96,7 +96,7 @@ namespace ts.server { return this.installer.installPackage(options); } - getTypingsForProject(project: Project, unresolvedImports: SortedReadonlyArray, forceRefresh: boolean): SortedReadonlyArray { + getTypingsForProject(project: Project, unresolvedImports: SortedReadonlyArray | undefined, forceRefresh: boolean): SortedReadonlyArray { const typeAcquisition = project.getTypeAcquisition(); if (!typeAcquisition || !typeAcquisition.enable) { diff --git a/src/server/typingsInstaller/nodeTypingsInstaller.ts b/src/server/typingsInstaller/nodeTypingsInstaller.ts index b0844b2369c24..e3e1440593de0 100644 --- a/src/server/typingsInstaller/nodeTypingsInstaller.ts +++ b/src/server/typingsInstaller/nodeTypingsInstaller.ts @@ -21,7 +21,7 @@ namespace ts.server.typingsInstaller { } writeLine = (text: string) => { try { - fs.appendFileSync(this.logFile, text + sys.newLine); + fs.appendFileSync(this.logFile!, text + sys.newLine); // TODO: GH#18217 } catch (e) { this.logEnabled = false; @@ -51,7 +51,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) { @@ -174,7 +174,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.`); } @@ -239,7 +239,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 059967ecb4d7e..109df67e32818 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; @@ -112,7 +112,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, @@ -167,8 +167,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}'`); @@ -204,7 +204,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); } @@ -233,7 +233,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; } @@ -307,7 +307,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${ts.versionMajorMinor}`] || distTags[latestDistTag]); const newTyping: JsTyping.CachedTyping = { typingLocation: typingFile, version: newVersion }; this.packageNameToTypingLocation.set(packageName, newTyping); @@ -354,7 +354,7 @@ namespace ts.server.typingsInstaller { let isInvoked = false; const watchers: FileWatcher[] = []; for (const file of files) { - const w = this.installTypingHost.watchFile(file, f => { + const w = this.installTypingHost.watchFile!(file, f => { // TODO: GH#18217 if (this.log.isEnabled()) { this.log.writeLine(`Got FS notification for ${f}, handler is already invoked '${isInvoked}'`); } @@ -387,7 +387,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 a086d95f91016..ffb8cda4ea20b 100644 --- a/src/server/utilities.ts +++ b/src/server/utilities.ts @@ -20,7 +20,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) @@ -107,7 +107,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; @@ -159,7 +159,7 @@ namespace ts.server { } export function createSortedArray(): SortedArray { - return [] as SortedArray; + return [] as any as SortedArray; // TODO: GH#19873 } } @@ -169,7 +169,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; } /** @@ -217,17 +217,17 @@ 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}`); } } } - export function getBaseConfigFileName(configFilePath: NormalizedPath): "tsconfig.json" | "jsconfig.json" | undefined { + export function getBaseConfigFileName(configFilePath: NormalizedPath | undefined): "tsconfig.json" | "jsconfig.json" | undefined { const base = getBaseFileName(configFilePath); return base === "tsconfig.json" || base === "jsconfig.json" ? base : undefined; } diff --git a/src/services/breakpoints.ts b/src/services/breakpoints.ts index efc27314a9869..b16625f7f45e3 100644 --- a/src/services/breakpoints.ts +++ b/src/services/breakpoints.ts @@ -22,12 +22,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 @@ -49,7 +50,7 @@ namespace ts.BreakpointResolver { return textSpan(startNode, findNextToken(previousTokenToFindNextEndToken, previousTokenToFindNextEndToken.parent)); } - 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); } @@ -60,16 +61,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)); } - 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 @@ -200,7 +202,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: @@ -268,7 +270,7 @@ namespace ts.BreakpointResolver { node.kind === SyntaxKind.SpreadElement || node.kind === SyntaxKind.PropertyAssignment || node.kind === SyntaxKind.ShorthandPropertyAssignment) && - isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent)) { + isArrayLiteralOrObjectLiteralDestructuringPattern(parent)) { return textSpan(node); } @@ -284,7 +286,7 @@ namespace ts.BreakpointResolver { } if (binaryExpression.operatorToken.kind === SyntaxKind.EqualsToken && - isArrayLiteralOrObjectLiteralDestructuringPattern(binaryExpression.parent)) { + isArrayLiteralOrObjectLiteralDestructuringPattern(parent)) { // Set breakpoint on assignment expression element of destructuring pattern // a = expression of // [a = expression, b, c] = someExpression or @@ -298,7 +300,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); @@ -328,25 +330,25 @@ namespace ts.BreakpointResolver { } // If this is name of property assignment, set breakpoint in the initializer - if (node.parent.kind === SyntaxKind.PropertyAssignment && + if (parent.kind === SyntaxKind.PropertyAssignment && (node.parent).name === node && - !isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent.parent)) { + !isArrayLiteralOrObjectLiteralDestructuringPattern(parent.parent)) { return spanInNode((node.parent).initializer); } // Breakpoint in type assertion goes to its operand - if (node.parent.kind === SyntaxKind.TypeAssertionExpression && (node.parent).type === node) { - return spanInNextNode((node.parent).type); + if (parent.kind === SyntaxKind.TypeAssertionExpression && (parent).type === node) { + return spanInNextNode((parent).type); } // return type of function go to previous token - if (isFunctionLike(node.parent) && (node.parent).type === node) { + if (isFunctionLike(parent) && (parent).type === node) { return spanInPreviousNode(node); } // initializer of variable/parameter declaration go to previous node - if ((node.parent.kind === SyntaxKind.VariableDeclaration || - node.parent.kind === SyntaxKind.Parameter)) { + if ((parent.kind === SyntaxKind.VariableDeclaration || + parent.kind === SyntaxKind.Parameter)) { const paramOrVarDecl = node.parent; if (paramOrVarDecl.initializer === node || paramOrVarDecl.type === node || @@ -355,7 +357,7 @@ namespace ts.BreakpointResolver { } } - if (node.parent.kind === SyntaxKind.BinaryExpression) { + if (parent.kind === SyntaxKind.BinaryExpression) { const binaryExpression = node.parent; if (isArrayLiteralOrObjectLiteralDestructuringPattern(binaryExpression.left) && (binaryExpression.right === node || @@ -371,10 +373,11 @@ namespace ts.BreakpointResolver { } function textSpanFromVariableDeclaration(variableDeclaration: VariableDeclaration): TextSpan { - if (variableDeclaration.parent.kind === SyntaxKind.VariableDeclarationList && - variableDeclaration.parent.declarations[0] === variableDeclaration) { + const parent = variableDeclaration.parent; + if (parent.kind === SyntaxKind.VariableDeclarationList && + parent.declarations[0] === variableDeclaration) { // First declaration - include let keyword - return textSpan(findPrecedingToken(variableDeclaration.pos, sourceFile, variableDeclaration.parent), variableDeclaration); + return textSpan(findPrecedingToken(variableDeclaration.pos, sourceFile, parent)!, variableDeclaration); } else { // Span only on this declaration @@ -382,9 +385,10 @@ namespace ts.BreakpointResolver { } } - function spanInVariableDeclaration(variableDeclaration: VariableDeclaration): TextSpan { + function spanInVariableDeclaration(variableDeclaration: VariableDeclaration): TextSpan | undefined { // If declaration of for in statement, just set the span in parent - if (variableDeclaration.parent.parent.kind === SyntaxKind.ForInStatement) { + const parent = variableDeclaration.parent; + if (parent.parent.kind === SyntaxKind.ForInStatement) { return spanInNode(variableDeclaration.parent.parent); } @@ -397,12 +401,11 @@ 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); } - if (variableDeclaration.parent.kind === SyntaxKind.VariableDeclarationList && - variableDeclaration.parent.declarations[0] !== variableDeclaration) { + if (parent.kind === SyntaxKind.VariableDeclarationList && parent.declarations[0] !== variableDeclaration) { // If we cannot set breakpoint on this declaration, set it on previous one // Because the variable declaration may be binding pattern and // we would like to set breakpoint in last binding element if that's the case, @@ -417,7 +420,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); @@ -445,7 +448,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; @@ -460,7 +463,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); @@ -469,7 +472,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) { @@ -493,8 +496,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) { @@ -507,7 +510,7 @@ namespace ts.BreakpointResolver { } } - function spanInForStatement(forStatement: ForStatement): TextSpan { + function spanInForStatement(forStatement: ForStatement): TextSpan | undefined { if (forStatement.initializer) { return spanInInitializerOfForLike(forStatement); } @@ -520,7 +523,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); @@ -538,7 +541,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; @@ -557,7 +560,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; @@ -575,7 +578,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 @@ -624,7 +627,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 @@ -643,7 +646,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) { @@ -658,7 +661,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: @@ -684,7 +687,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 || @@ -695,7 +698,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); } @@ -703,7 +706,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); @@ -713,7 +716,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 aff626ca9fe5c..7c9f480e93e46 100644 --- a/src/services/classifier.ts +++ b/src/services/classifier.ts @@ -224,7 +224,7 @@ namespace ts { case SyntaxKind.NoSubstitutionTemplateLiteral: return EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate; default: - throw Debug.fail("Only 'NoSubstitutionTemplateLiteral's and 'TemplateTail's can be unterminated; got SyntaxKind #" + token); + return Debug.fail("Only 'NoSubstitutionTemplateLiteral's and 'TemplateTail's can be unterminated; got SyntaxKind #" + token); } } return lastOnTemplateStack === SyntaxKind.TemplateHead ? EndOfLineState.InTemplateSubstitutionPosition : undefined; @@ -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); } } @@ -708,10 +711,10 @@ namespace ts { processJSDocTemplateTag(tag); break; case SyntaxKind.JSDocTypeTag: - processElement((tag).typeExpression); + processElement((tag).typeExpression!); break; case SyntaxKind.JSDocReturnTag: - processElement((tag).typeExpression); + processElement((tag).typeExpression!); break; } @@ -812,7 +815,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) { @@ -841,7 +844,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; } @@ -858,20 +861,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; } } @@ -882,7 +886,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. diff --git a/src/services/codeFixProvider.ts b/src/services/codeFixProvider.ts index 502f8457d8c4a..e4ea6b74bc3ef 100644 --- a/src/services/codeFixProvider.ts +++ b/src/services/codeFixProvider.ts @@ -56,7 +56,7 @@ namespace ts { if (actions && actions.length > 0) { for (const action of actions) { if (action === undefined) { - context.host.log(`Action for error code ${context.errorCode} added an invalid action entry; please log a bug`); + context.host.log!(`Action for error code ${context.errorCode} added an invalid action entry; please log a bug`); // TODO: GH#18217 } else { allActions.push(action); diff --git a/src/services/codefixes/correctQualifiedNameToIndexedAccessType.ts b/src/services/codefixes/correctQualifiedNameToIndexedAccessType.ts index de4498035becd..055c5e994c043 100644 --- a/src/services/codefixes/correctQualifiedNameToIndexedAccessType.ts +++ b/src/services/codefixes/correctQualifiedNameToIndexedAccessType.ts @@ -13,9 +13,9 @@ namespace ts.codefix { }, fixIds: [fixId], getAllCodeActions: (context) => codeFixAll(context, errorCodes, (changes, diag) => { - const q = getQualifiedName(diag.file, diag.start); + const q = getQualifiedName(diag.file!, diag.start!); if (q) { - doChange(changes, diag.file, q); + doChange(changes, diag.file!, q); } }), }); diff --git a/src/services/codefixes/fixAddMissingMember.ts b/src/services/codefixes/fixAddMissingMember.ts index 7dbbc39843fcb..b0a4050379b44 100644 --- a/src/services/codefixes/fixAddMissingMember.ts +++ b/src/services/codefixes/fixAddMissingMember.ts @@ -46,7 +46,7 @@ namespace ts.codefix { }, }); - interface Info { token: Identifier; classDeclaration: ClassLikeDeclaration; makeStatic: boolean; classDeclarationSourceFile: SourceFile; inJs: boolean; call: CallExpression; } + interface Info { token: Identifier; classDeclaration: ClassLikeDeclaration; makeStatic: boolean; classDeclarationSourceFile: SourceFile; inJs: boolean; call: CallExpression | undefined; } function getInfo(tokenSourceFile: SourceFile, tokenPos: number, checker: TypeChecker): Info | undefined { // The identifier of the missing property. eg: // this.missing = 1; @@ -84,12 +84,12 @@ namespace ts.codefix { return isClassLike(classDeclaration) ? { classDeclaration, makeStatic: hasModifier(containingClassMemberDeclaration, ModifierFlags.Static) } : undefined; } else { - const leftExpressionType = checker.getTypeAtLocation(parent.expression); + const leftExpressionType = checker.getTypeAtLocation(parent.expression)!; // TODO: GH#18217 const { symbol } = leftExpressionType; if (!(symbol && leftExpressionType.flags & TypeFlags.Object && symbol.flags & SymbolFlags.Class)) { return undefined; } - const classDeclaration = cast(first(symbol.declarations), isClassLike); + const classDeclaration = cast(first(symbol.declarations!), isClassLike); // The expression is a class symbol but the type is not the instance-side. return { classDeclaration, makeStatic: leftExpressionType !== checker.getDeclaredTypeOfSymbol(symbol) }; } @@ -107,7 +107,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); } @@ -132,11 +132,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/fixAwaitInSyncFunction.ts b/src/services/codefixes/fixAwaitInSyncFunction.ts index 883993e7b5146..f784792e463d2 100644 --- a/src/services/codefixes/fixAwaitInSyncFunction.ts +++ b/src/services/codefixes/fixAwaitInSyncFunction.ts @@ -16,7 +16,7 @@ namespace ts.codefix { }, fixIds: [fixId], getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => { - const nodes = getNodes(diag.file, diag.start); + const nodes = getNodes(diag.file!, diag.start!); if (!nodes) return; doChange(changes, context.sourceFile, nodes); }), @@ -35,7 +35,7 @@ namespace ts.codefix { function getNodes(sourceFile: SourceFile, start: number): { insertBefore: Node, returnType: TypeNode | undefined } | undefined { const token = getTokenAtPosition(sourceFile, start, /*includeJsDocComment*/ false); - const containingFunction = getContainingFunction(token); + const containingFunction = getContainingFunction(token)!; // TODO: GH#18217 let insertBefore: Node | undefined; switch (containingFunction.kind) { case SyntaxKind.MethodDeclaration: @@ -52,7 +52,7 @@ namespace ts.codefix { return; } - return { + return insertBefore && { insertBefore, returnType: getReturnType(containingFunction) }; @@ -61,7 +61,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 a28a46caf1b16..f64128a8deb80 100644 --- a/src/services/codefixes/fixCannotFindModule.ts +++ b/src/services/codefixes/fixCannotFindModule.ts @@ -10,9 +10,9 @@ namespace ts.codefix { }, fixIds: [fixId], getAllCodeActions: context => codeFixAll(context, errorCodes, (_, diag, commands) => { - const pkg = getTypesPackageNameToInstall(context.host, getModuleName(diag.file, diag.start)); + const pkg = getTypesPackageNameToInstall(context.host, getModuleName(diag.file!, diag.start!)); if (pkg) { - commands.push(getCommand(diag.file.fileName, pkg)); + commands.push(getCommand(diag.file!.fileName, pkg)); } }), }); @@ -28,7 +28,7 @@ namespace ts.codefix { function getTypesPackageNameToInstall(host: LanguageServiceHost, moduleName: string): string | undefined { const { packageName } = getPackageName(moduleName); // If !registry, registry not available yet, can't do anything. - return host.isKnownTypesPackageName(packageName) ? getTypesPackageName(packageName) : undefined; + return host.isKnownTypesPackageName!(packageName) ? getTypesPackageName(packageName) : undefined; // TODO: GH#18217 } export function tryGetCodeActionForInstallPackageTypes(host: LanguageServiceHost, fileName: string, moduleName: string): CodeAction | undefined { diff --git a/src/services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts b/src/services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts index 786d61d798d80..d088fcef2ae6a 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): 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 c295d4fb3c73f..68e21a78e24b0 100644 --- a/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts +++ b/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts @@ -22,7 +22,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); } } @@ -45,9 +45,9 @@ namespace ts.codefix { // so duplicates cannot occur. const implementedType = checker.getTypeAtLocation(implementedTypeNode) as InterfaceType; const implementedTypeSymbols = checker.getPropertiesOfType(implementedType); - const nonPrivateMembers = implementedTypeSymbols.filter(symbol => !(getModifierFlags(symbol.valueDeclaration) & ModifierFlags.Private)); + const nonPrivateMembers = implementedTypeSymbols.filter(symbol => !(getModifierFlags(symbol.valueDeclaration!) & ModifierFlags.Private)); - const classType = checker.getTypeAtLocation(classDeclaration); + const classType = checker.getTypeAtLocation(classDeclaration)!; if (!checker.getIndexTypeOfType(classType, IndexKind.Number)) { createMissingIndexSignatureDeclaration(implementedType, IndexKind.Number); @@ -61,7 +61,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 8d47e74d8a42e..32414f86c67e0 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/fixConstructorForDerivedNeedSuperCall.ts b/src/services/codefixes/fixConstructorForDerivedNeedSuperCall.ts index 8fe2e8458a86b..32a825511fa4e 100644 --- a/src/services/codefixes/fixConstructorForDerivedNeedSuperCall.ts +++ b/src/services/codefixes/fixConstructorForDerivedNeedSuperCall.ts @@ -12,7 +12,7 @@ namespace ts.codefix { }, fixIds: [fixId], getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => - doChange(changes, context.sourceFile, getNode(diag.file, diag.start!))), + doChange(changes, context.sourceFile, getNode(diag.file!, diag.start!))), }); function getNode(sourceFile: SourceFile, pos: number): ConstructorDeclaration { diff --git a/src/services/codefixes/fixExtendsInterfaceBecomesImplements.ts b/src/services/codefixes/fixExtendsInterfaceBecomesImplements.ts index 551662210c149..042cd8673ab19 100644 --- a/src/services/codefixes/fixExtendsInterfaceBecomesImplements.ts +++ b/src/services/codefixes/fixExtendsInterfaceBecomesImplements.ts @@ -14,15 +14,15 @@ namespace ts.codefix { }, fixIds: [fixId], getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => { - const nodes = getNodes(diag.file, diag.start!); - if (nodes) doChanges(changes, diag.file, nodes.extendsToken, nodes.heritageClauses); + const nodes = getNodes(diag.file!, diag.start!); + if (nodes) doChanges(changes, diag.file!, nodes.extendsToken, nodes.heritageClauses); }), }); 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 e71c06399c2df..291afc8a0c0c2 100644 --- a/src/services/codefixes/fixForgottenThisPropertyAccess.ts +++ b/src/services/codefixes/fixForgottenThisPropertyAccess.ts @@ -15,7 +15,7 @@ namespace ts.codefix { }, fixIds: [fixId], getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => { - doChange(changes, context.sourceFile, getNode(diag.file, diag.start!)); + doChange(changes, context.sourceFile, getNode(diag.file!, diag.start!)); }), }); diff --git a/src/services/codefixes/fixInvalidImportSyntax.ts b/src/services/codefixes/fixInvalidImportSyntax.ts index e6f18cf5bd7c6..a18f0138197d5 100644 --- a/src/services/codefixes/fixInvalidImportSyntax.ts +++ b/src/services/codefixes/fixInvalidImportSyntax.ts @@ -71,12 +71,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: CodeAction[] = []; - 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 3158e90ce965a..735359442b399 100644 --- a/src/services/codefixes/fixJSDocTypes.ts +++ b/src/services/codefixes/fixJSDocTypes.ts @@ -34,7 +34,7 @@ namespace ts.codefix { const { fixId, program, sourceFile } = context; const checker = program.getTypeChecker(); return codeFixAllWithTextChanges(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; @@ -43,7 +43,7 @@ namespace ts.codefix { } }); - 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 729f14e9ef946..fb32380b91b4b 100644 --- a/src/services/codefixes/fixSpelling.ts +++ b/src/services/codefixes/fixSpelling.ts @@ -29,10 +29,10 @@ namespace ts.codefix { // ^^^^^^^ const node = getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); // TODO: GH#15852 - 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 { diff --git a/src/services/codefixes/fixUnusedIdentifier.ts b/src/services/codefixes/fixUnusedIdentifier.ts index de053c2fe8f3b..80b4376c8de87 100644 --- a/src/services/codefixes/fixUnusedIdentifier.ts +++ b/src/services/codefixes/fixUnusedIdentifier.ts @@ -106,7 +106,7 @@ namespace ts.codefix { break; case SyntaxKind.TypeParameter: - const typeParameters = (parent.parent).typeParameters; + const typeParameters = (parent.parent).typeParameters!; if (typeParameters.length === 1) { const previousToken = getTokenAtPosition(sourceFile, typeParameters.pos - 1, /*includeJsDocComment*/ false); const nextToken = getTokenAtPosition(sourceFile, typeParameters.end, /*includeJsDocComment*/ false); @@ -130,7 +130,7 @@ namespace ts.codefix { oldFunction, oldFunction.modifiers, oldFunction.typeParameters, - /*parameters*/ undefined, + /*parameters*/ undefined!, // TODO: GH#18217 oldFunction.type, oldFunction.equalsGreaterThanToken, oldFunction.body); @@ -149,7 +149,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; @@ -171,15 +171,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; @@ -208,7 +208,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 6a45c66ca816d..842f69866c99f 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, 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, out); @@ -74,7 +74,7 @@ namespace ts.codefix { if (declarations.length > signatures.length) { const signature = checker.getSignatureFromDeclaration(declarations[declarations.length - 1] as SignatureDeclaration); - outputMethod(signature, modifiers, name, createStubbedMethodBody()); + outputMethod(signature!, modifiers, name, createStubbedMethodBody()); // TODO: GH#18217 } else { Debug.assert(declarations.length === signatures.length); @@ -83,13 +83,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; @@ -104,7 +112,7 @@ namespace ts.codefix { } function getSynthesizedDeepClones(nodes: NodeArray | undefined): NodeArray | undefined { - return nodes && createNodeArray(nodes.map(getSynthesizedDeepClone)); + return nodes && createNodeArray(nodes.map(getSynthesizedDeepClone)); } export function createMethodFromCallExpression({ typeArguments, arguments: args }: CallExpression, methodName: string, inJs: boolean, makeStatic: boolean): MethodDeclaration { @@ -115,7 +123,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()); @@ -182,7 +190,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 9f9bc959bf0d6..c396f7251113b 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -24,7 +24,7 @@ namespace ts.codefix { } interface ImportCodeFixContext extends SymbolContext { - symbolToken: Node; + symbolToken: Node | undefined; program: Program; checker: TypeChecker; compilerOptions: CompilerOptions; @@ -134,8 +134,8 @@ namespace ts.codefix { const useExistingImportActions = !context.symbolToken || !isIdentifier(context.symbolToken) ? emptyArray : mapDefined(existingImports, ({ declaration }) => { 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))) { return getCodeActionForUseExistingNamespaceImport(namespace.text, context, context.symbolToken as Identifier); } } @@ -250,7 +250,7 @@ namespace ts.codefix { const { baseUrl, paths, rootDirs } = options; const addJsExtension = usesJsExtensionOnImports(sourceFile); const choicesForEachExportingModule = flatMap(moduleSymbols, ({ moduleSymbol, importKind }) => { - const modulePathsGroups = getAllModulePaths(program, moduleSymbol.valueDeclaration.getSourceFile()).map(moduleFileName => { + const modulePathsGroups = getAllModulePaths(program, moduleSymbol.valueDeclaration!.getSourceFile()).map(moduleFileName => { const sourceDirectory = getDirectoryPath(sourceFile.fileName); const global = tryGetModuleNameFromAmbientModule(moduleSymbol) || tryGetModuleNameFromTypeRoots(options, host, getCanonicalFileName, moduleFileName, addJsExtension) @@ -339,7 +339,7 @@ namespace ts.codefix { } function tryGetModuleNameFromAmbientModule(moduleSymbol: Symbol): string | undefined { - const decl = moduleSymbol.valueDeclaration; + const decl = moduleSymbol.valueDeclaration!; if (isModuleDeclaration(decl) && isStringLiteral(decl.name)) { return decl.name.text; } @@ -390,7 +390,7 @@ namespace ts.codefix { ): string | undefined { const roots = getEffectiveTypeRoots(options, host); return firstDefined(roots, unNormalizedTypeRoot => { - const typeRoot = toPath(unNormalizedTypeRoot, /*basePath*/ undefined, getCanonicalFileName); + const typeRoot = toPath(unNormalizedTypeRoot, /*basePath*/ undefined!, getCanonicalFileName); // TODO: GH#18217 if (startsWith(moduleFileName, typeRoot)) { return removeExtensionAndIndexPostFix(moduleFileName.substring(typeRoot.length + 1), options, addJsExtension); } @@ -426,10 +426,10 @@ namespace ts.codefix { function getDirectoryOrExtensionlessFileName(path: string): string { // If the file is the main module, it can be imported by the package name - const packageRootPath = path.substring(0, parts.packageRootIndex); + 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)!); // TODO: GH#18217 if (packageJsonContent) { const mainFileRelative = packageJsonContent.typings || packageJsonContent.types || packageJsonContent.main; if (mainFileRelative) { @@ -445,18 +445,18 @@ namespace ts.codefix { const fullModulePathWithoutExtension = removeFileExtension(path); // If the file is /index, it can be imported by its directory name - if (getCanonicalFileName(fullModulePathWithoutExtension.substring(parts.fileNameIndex)) === "/index") { - return fullModulePathWithoutExtension.substring(0, parts.fileNameIndex); + if (getCanonicalFileName(fullModulePathWithoutExtension.substring(parts!.fileNameIndex)) === "/index") { + return fullModulePathWithoutExtension.substring(0, parts!.fileNameIndex); } return fullModulePathWithoutExtension; } function getNodeResolvablePath(path: string): string { - const basePath = path.substring(0, parts.topLevelNodeModulesIndex); + const basePath = path.substring(0, parts!.topLevelNodeModulesIndex); if (sourceDirectory.indexOf(basePath) === 0) { // if node_modules folder is in this folder or any of its parent folders, no need to keep it. - return path.substring(parts.topLevelPackageNameIndex + 1); + return path.substring(parts!.topLevelPackageNameIndex + 1); } else { return getRelativePath(path, sourceDirectory, getCanonicalFileName); @@ -524,7 +524,7 @@ namespace ts.codefix { 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; }); } @@ -559,7 +559,7 @@ namespace ts.codefix { ): CodeFixAction[] { 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); @@ -589,7 +589,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 => @@ -623,7 +623,7 @@ namespace ts.codefix { } } - function getCodeActionForUseExistingNamespaceImport(namespacePrefix: string, context: SymbolContext, symbolToken: Identifier): CodeFixAction { + function getCodeActionForUseExistingNamespaceImport(namespacePrefix: string, context: SymbolContext, symbolToken: Identifier): CodeFixAction | undefined { const { symbolName, sourceFile } = context; /** @@ -641,13 +641,13 @@ namespace ts.codefix { return createCodeAction(Diagnostics.Change_0_to_1, [symbolName, `${namespacePrefix}.${symbolName}`], changes); } - function getImportCodeActions(context: CodeFixContext): CodeAction[] { + function getImportCodeActions(context: CodeFixContext): CodeAction[] | 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): CodeAction[] { + function getActionsForUMDImport(context: CodeFixContext): CodeAction[] | undefined { const token = getTokenAtPosition(context.sourceFile, context.span.start, /*includeJsDocComment*/ false); const checker = context.program.getTypeChecker(); @@ -669,10 +669,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)); } } @@ -703,7 +703,7 @@ namespace ts.codefix { } } - function getActionsForNonUMDImport(context: CodeFixContext): CodeAction[] { + function getActionsForNonUMDImport(context: CodeFixContext): CodeAction[] | undefined { // This will always be an Identifier, since the diagnostics we fix only fail on identifiers. const { sourceFile, span, program, cancellationToken } = context; const checker = program.getTypeChecker(); @@ -736,7 +736,7 @@ namespace ts.codefix { if (( localSymbol && localSymbol.escapedName === symbolName || getEscapedNameForExportDefault(defaultExport) === symbolName || - moduleSymbolToValidIdentifier(moduleSymbol, compilerOptions.target) === symbolName + moduleSymbolToValidIdentifier(moduleSymbol, compilerOptions.target!) === symbolName ) && checkSymbolHasMeaning(localSymbol || defaultExport, currentTokenMeaning)) { addSymbol(moduleSymbol, localSymbol || defaultExport, ImportKind.Default); } @@ -749,7 +749,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; @@ -786,7 +786,7 @@ namespace ts.codefix { } for (const sourceFile of allSourceFiles) { if (isExternalOrCommonJsModule(sourceFile)) { - cb(sourceFile.symbol, sourceFile); + cb(sourceFile.symbol!, sourceFile); } } } diff --git a/src/services/codefixes/inferFromUsage.ts b/src/services/codefixes/inferFromUsage.ts index e17c518361199..03c35cb97f05a 100644 --- a/src/services/codefixes/inferFromUsage.ts +++ b/src/services/codefixes/inferFromUsage.ts @@ -34,7 +34,7 @@ namespace ts.codefix { if (!fix) return undefined; const { declaration, textChanges } = fix; - const name = getNameOfDeclaration(declaration); + const name = getNameOfDeclaration(declaration)!; const description = formatStringFromArgs(getLocaleSpecificMessage(getDiagnostic(errorCode, token)), [name.getText()]); return [{ description, changes: [{ fileName: sourceFile.fileName, textChanges }], fixId }]; }, @@ -52,7 +52,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: @@ -109,7 +109,7 @@ namespace ts.codefix { return isSetAccessor(containingFunction) ? getCodeActionForSetAccessor(containingFunction, program, cancellationToken) : undefined; default: - throw Debug.fail(String(errorCode)); + return Debug.fail(String(errorCode)); } } @@ -181,12 +181,13 @@ namespace ts.codefix { } const type = inferTypeForVariableFromUsage(getAccessorDeclaration.name, program, cancellationToken); - const closeParenToken = findChildOfKind(getAccessorDeclaration, SyntaxKind.CloseParenToken, sourceFile); + const closeParenToken = findChildOfKind(getAccessorDeclaration, SyntaxKind.CloseParenToken, sourceFile)!; return makeFix(getAccessorDeclaration, closeParenToken.getEnd(), type, program); } function makeFix(declaration: Declaration, start: number, type: Type | undefined, program: Program): Fix | undefined { - return type && { declaration, textChanges: [makeChange(declaration, start, type, program)] }; + const change = type && makeChange(declaration, start, type, program); + return change && { declaration, textChanges: [change] }; } function makeChange(declaration: Declaration, start: number, type: Type | undefined, program: Program): TextChange | undefined { @@ -226,7 +227,7 @@ namespace ts.codefix { const writeText: (text: string) => void = text => str += text; return { - getText: () => typeIsAccessible ? str : undefined, + getText: () => typeIsAccessible ? str : undefined!, // TODO: GH#18217 writeKeyword: writeText, writeOperator: writeText, writePunctuation: writeText, @@ -249,7 +250,8 @@ namespace ts.codefix { decreaseIndent: noop, clear: () => { str = ""; typeIsAccessible = true; }, trackSymbol: (symbol, declaration, meaning) => { - if (checker.isSymbolAccessible(symbol, declaration, meaning, /*shouldComputeAliasToMarkVisible*/ false).accessibility !== SymbolAccessibility.Accessible) { + // TODO: GH#18217 + if (checker.isSymbolAccessible(symbol, declaration, meaning!, /*shouldComputeAliasToMarkVisible*/ false).accessibility !== SymbolAccessibility.Accessible) { typeIsAccessible = false; } }, @@ -437,7 +439,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); } @@ -448,7 +450,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); } @@ -508,7 +510,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)!); } } @@ -537,7 +539,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) { @@ -563,19 +565,19 @@ namespace ts.codefix { return checker.getWidenedType(checker.getUnionType(map(usageContext.candidateTypes, 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) => { @@ -598,14 +600,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; @@ -642,17 +644,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/completions.ts b/src/services/completions.ts index c49f758392aef..fcd686a1982e3 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -52,7 +52,7 @@ namespace ts.Completions { return getLabelCompletionAtPosition(contextToken.parent); } - const completionData = getCompletionData(typeChecker, log, sourceFile, position, allSourceFiles, options, compilerOptions.target); + const completionData = getCompletionData(typeChecker, log, sourceFile, position, allSourceFiles, options, compilerOptions.target!); if (!completionData) { return undefined; } @@ -105,7 +105,7 @@ namespace ts.Completions { return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, entries }; } - function completionInfoFromData(sourceFile: SourceFile, typeChecker: TypeChecker, compilerOptions: CompilerOptions, log: Log, completionData: CompletionData, includeInsertTextCompletions: boolean): CompletionInfo { + function completionInfoFromData(sourceFile: SourceFile, typeChecker: TypeChecker, compilerOptions: CompilerOptions, log: Log, completionData: CompletionData, includeInsertTextCompletions: boolean): CompletionInfo | undefined { const { symbols, completionKind, isNewIdentifierLocation, location, propertyAccessToConvert, keywordFilters, symbolToOriginInfoMap, recommendedCompletion, isJsxInitializer } = completionData; if (sourceFile.languageVariant === LanguageVariant.JSX && location && location.parent && isJsxClosingElement(location.parent)) { @@ -127,15 +127,15 @@ namespace ts.Completions { const entries: CompletionEntry[] = []; if (isSourceFileJavaScript(sourceFile)) { - const uniqueNames = getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, compilerOptions.target, log, completionKind, includeInsertTextCompletions, propertyAccessToConvert, isJsxInitializer, recommendedCompletion, symbolToOriginInfoMap); - getJavaScriptCompletionEntries(sourceFile, location.pos, uniqueNames, compilerOptions.target, entries); + const uniqueNames = getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, compilerOptions.target!, log, completionKind, includeInsertTextCompletions, 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, includeInsertTextCompletions, propertyAccessToConvert, isJsxInitializer, recommendedCompletion, symbolToOriginInfoMap); + getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, compilerOptions.target!, log, completionKind, includeInsertTextCompletions, propertyAccessToConvert, isJsxInitializer, recommendedCompletion, symbolToOriginInfoMap); } // TODO add filter for keyword based on type/value/namespace and also location @@ -187,7 +187,7 @@ namespace ts.Completions { function createCompletionEntry( symbol: Symbol, - location: Node, + location: Node | undefined, sourceFile: SourceFile, typeChecker: TypeChecker, target: ScriptTarget, @@ -241,7 +241,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), @@ -257,7 +257,7 @@ namespace ts.Completions { return JSON.stringify(text); } - 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; } @@ -273,7 +273,7 @@ namespace ts.Completions { function getCompletionEntriesFromSymbols( symbols: ReadonlyArray, entries: Push, - location: Node, + location: Node | undefined, sourceFile: SourceFile, typeChecker: TypeChecker, target: ScriptTarget, @@ -293,7 +293,7 @@ namespace ts.Completions { const uniques = createMap(); for (const symbol of symbols) { const origin = symbolToOriginInfoMap ? symbolToOriginInfoMap[getSymbolId(symbol)] : undefined; - const entry = createCompletionEntry(symbol, location, sourceFile, typeChecker, target, kind, origin, recommendedCompletion, propertyAccessToConvert, isJsxInitializer, includeInsertTextCompletions); + const entry = createCompletionEntry(symbol, location, sourceFile, typeChecker, target, kind, origin, recommendedCompletion, propertyAccessToConvert, isJsxInitializer!, includeInsertTextCompletions!); if (!entry) { continue; } @@ -304,7 +304,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); } @@ -386,7 +386,7 @@ namespace ts.Completions { // '/*completion position*/' // }); const type = typeChecker.getContextualType(node.parent.parent); - return { kind: StringLiteralCompletionKind.Properties, symbols: type && type.getApparentProperties() }; + return { kind: StringLiteralCompletionKind.Properties, symbols: (type && type.getApparentProperties())! }; // TODO: GH#18217 } return fromContextualType(); @@ -399,7 +399,7 @@ namespace ts.Completions { // } // let a: A; // a['/*completion position*/'] - return { kind: StringLiteralCompletionKind.Properties, symbols: typeChecker.getTypeAtLocation(expression).getApparentProperties() }; + return { kind: StringLiteralCompletionKind.Properties, symbols: typeChecker.getTypeAtLocation(expression)!.getApparentProperties() }; // TODO: GH#18217 } return undefined; } @@ -415,7 +415,7 @@ namespace ts.Completions { const candidates: Signature[] = []; typeChecker.getResolvedSignature(argumentInfo.invocation, candidates, argumentInfo.argumentCount); const uniques = createMap(); - return { kind: StringLiteralCompletionKind.Types, types: flatMap(candidates, candidate => getStringLiteralTypes(typeChecker.getParameterType(candidate, argumentInfo.argumentIndex), typeChecker, uniques)) }; + return { kind: StringLiteralCompletionKind.Types, types: flatMap(candidates, candidate => getStringLiteralTypes(typeChecker.getParameterType(candidate, argumentInfo.argumentIndex!), typeChecker, uniques)) }; // TODO: GH#18217 } return fromContextualType(); } @@ -443,7 +443,7 @@ namespace ts.Completions { } } - function getStringLiteralTypes(type: Type, typeChecker: TypeChecker, uniques = createMap()): ReadonlyArray { + function getStringLiteralTypes(type: Type | undefined, typeChecker: TypeChecker, uniques = createMap()): ReadonlyArray { if (type && type.flags & TypeFlags.TypeParameter) { type = type.getConstraint(); } @@ -457,9 +457,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( @@ -471,7 +471,7 @@ namespace ts.Completions { { name, source }: CompletionEntryIdentifier, allSourceFiles: ReadonlyArray, ): SymbolCompletion | { type: "request", request: Request } | { type: "none" } { - const completionData = getCompletionData(typeChecker, log, sourceFile, position, allSourceFiles, { includeExternalModuleExports: true, includeInsertTextCompletions: true }, compilerOptions.target); + const completionData = getCompletionData(typeChecker, log, sourceFile, position, allSourceFiles, { includeExternalModuleExports: true, includeInsertTextCompletions: true }, compilerOptions.target!); if (!completionData) { return { type: "none" }; } @@ -485,9 +485,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 === name && getSourceFromOrigin(origin) === source ? { type: "symbol" as "symbol", symbol, location, symbolToOriginInfoMap, previousToken, isJsxInitializer } : undefined; }) || { type: "none" }; } @@ -495,7 +495,7 @@ namespace ts.Completions { function getSymbolName(symbol: Symbol, origin: SymbolOriginInfo | undefined, target: ScriptTarget): string { return origin && origin.type === "export" && origin.isDefaultExport && symbol.escapedName === InternalSymbolName.Default // Name of "export default foo;" is "foo". Name of "export default 0" is the filename converted to camelCase. - ? firstDefined(symbol.declarations, d => isExportAssignment(d) && isIdentifier(d.expression) ? d.expression.text : undefined) + ? firstDefined(symbol.declarations!, d => isExportAssignment(d) && isIdentifier(d.expression) ? d.expression.text : undefined) // TODO: GH#18217 || codefix.moduleSymbolToValidIdentifier(origin.moduleSymbol, target) : symbol.name; } @@ -516,7 +516,7 @@ namespace ts.Completions { host: LanguageServiceHost, formatContext: formatting.FormatContext, getCanonicalFileName: GetCanonicalFileName, - ): CompletionEntryDetails { + ): CompletionEntryDetails | undefined { const typeChecker = program.getTypeChecker(); const { name } = entryId; // Compute all the completion symbols again. @@ -539,7 +539,7 @@ namespace ts.Completions { const { symbol, location, symbolToOriginInfoMap, previousToken } = symbolCompletion; const { codeActions, sourceDisplay } = getCompletionEntryCodeActionsAndSourceDisplay(symbolToOriginInfoMap, symbol, program, typeChecker, host, compilerOptions, sourceFile, previousToken, formatContext, getCanonicalFileName, allSourceFiles); const kindModifiers = SymbolDisplay.getSymbolModifiers(symbol); - const { displayParts, documentation, symbolKind, tags } = SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker, symbol, sourceFile, location, location, SemanticMeaning.All); + const { displayParts, documentation, symbolKind, tags } = SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker, symbol, sourceFile, location, location!, SemanticMeaning.All); // TODO: GH#18217 return { name, kindModifiers, kind: symbolKind, displayParts, documentation, tags, codeActions, source: sourceDisplay }; } case "none": { @@ -573,7 +573,7 @@ namespace ts.Completions { host: LanguageServiceHost, compilerOptions: CompilerOptions, sourceFile: SourceFile, - previousToken: Node, + previousToken: Node | undefined, formatContext: formatting.FormatContext, getCanonicalFileName: GetCanonicalFileName, allSourceFiles: ReadonlyArray, @@ -592,7 +592,7 @@ namespace ts.Completions { host: LanguageServiceHost, compilerOptions: CompilerOptions, sourceFile: SourceFile, - previousToken: Node, + previousToken: Node | undefined, formatContext: formatting.FormatContext, getCanonicalFileName: GetCanonicalFileName, allSourceFiles: ReadonlyArray @@ -603,7 +603,7 @@ namespace ts.Completions { exportedSymbol, moduleSymbol, sourceFile, - getSymbolName(symbol, symbolOriginInfo, compilerOptions.target), + getSymbolName(symbol, symbolOriginInfo, compilerOptions.target!), host, program, checker, @@ -674,7 +674,7 @@ namespace ts.Completions { case SyntaxKind.EqualsToken: switch (parent.kind) { case ts.SyntaxKind.VariableDeclaration: - return checker.getContextualType((parent as VariableDeclaration).initializer); + return checker.getContextualType((parent as VariableDeclaration).initializer!); // TODO: GH#18217 case ts.SyntaxKind.BinaryExpression: return checker.getTypeAtLocation((parent as BinaryExpression).left); case ts.SyntaxKind.JsxAttribute: @@ -692,7 +692,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) @@ -718,7 +718,7 @@ namespace ts.Completions { } } - function getSwitchedType(caseClause: ts.CaseClause, checker: ts.TypeChecker): ts.Type { + function getSwitchedType(caseClause: ts.CaseClause, checker: ts.TypeChecker): ts.Type | undefined { return checker.getTypeAtLocation(caseClause.parent.parent.expression); } @@ -729,7 +729,7 @@ namespace ts.Completions { } function isModuleSymbol(symbol: Symbol): boolean { - return symbol.declarations.some(d => d.kind === SyntaxKind.SourceFile); + return symbol.declarations!.some(d => d.kind === SyntaxKind.SourceFile); } function getCompletionData( @@ -816,7 +816,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. @@ -827,7 +827,7 @@ namespace ts.Completions { // Skip this partial identifier and adjust the contextToken to the token that precedes it. if (contextToken && position <= contextToken.end && isWord(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)); } @@ -983,6 +983,8 @@ namespace ts.Completions { case SyntaxKind.JSDocTypeTag: case SyntaxKind.JSDocTypedefTag: return true; + default: + return false; } } @@ -1014,7 +1016,7 @@ namespace ts.Completions { } // If the module is merged with a value, we must get the type of the class and add its propertes (for inherited static methods). - if (!isTypeLocation && symbol.declarations.some(d => d.kind !== SyntaxKind.SourceFile && d.kind !== SyntaxKind.ModuleDeclaration && d.kind !== SyntaxKind.EnumDeclaration)) { + if (!isTypeLocation && symbol.declarations!.some(d => d.kind !== SyntaxKind.SourceFile && d.kind !== SyntaxKind.ModuleDeclaration && d.kind !== SyntaxKind.EnumDeclaration)) { addTypeProperties(typeChecker.getTypeOfSymbolAtLocation(symbol, node)); } @@ -1024,7 +1026,7 @@ namespace ts.Completions { } if (!isTypeLocation) { - addTypeProperties(typeChecker.getTypeAtLocation(node)); + addTypeProperties(typeChecker.getTypeAtLocation(node)!); } } @@ -1047,10 +1049,10 @@ namespace ts.Completions { } function tryGetGlobalSymbols(): boolean { - let objectLikeContainer: ObjectLiteralExpression | BindingPattern; - let namedImportsOrExports: NamedImportsOrExports; - let classLikeContainer: ClassLikeDeclaration; - let jsxContainer: JsxOpeningLikeElement; + let objectLikeContainer: ObjectLiteralExpression | BindingPattern | undefined; + let namedImportsOrExports: NamedImportsOrExports | undefined; + let classLikeContainer: ClassLikeDeclaration | undefined; + let jsxContainer: JsxOpeningLikeElement | undefined; if (objectLikeContainer = tryGetObjectLikeCompletionContainer(contextToken)) { return tryGetObjectLikeCompletionSymbols(objectLikeContainer); @@ -1079,11 +1081,9 @@ namespace ts.Completions { } if (jsxContainer = tryGetContainingJsxElement(contextToken)) { - let attrsType: Type; if ((jsxContainer.kind === SyntaxKind.JsxSelfClosingElement) || (jsxContainer.kind === SyntaxKind.JsxOpeningElement)) { // Cursor is inside a JSX self-closing element or opening element - attrsType = typeChecker.getAllAttributesTypeFromJsxOpeningLikeElement(jsxContainer); - + const attrsType = typeChecker.getAllAttributesTypeFromJsxOpeningLikeElement(jsxContainer); if (attrsType) { symbols = filterJsxAttributes(typeChecker.getPropertiesOfType(attrsType), jsxContainer.attributes.properties); completionKind = CompletionKind.MemberLike; @@ -1243,8 +1243,9 @@ namespace ts.Completions { const exportedSymbols = typeChecker.getExportsOfModule(symbol); // If the exported symbols contains type, // symbol can be referenced at locations where type is allowed - return forEach(exportedSymbols, symbolCanBeReferencedAtTypeLocation); + return some(exportedSymbols, symbolCanBeReferencedAtTypeLocation); } + return false; } function getSymbolsFromOtherSourceFileExports(symbols: Symbol[], tokenText: string, target: ScriptTarget): void { @@ -1258,7 +1259,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; } @@ -1305,8 +1306,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; } @@ -1334,13 +1335,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) { @@ -1436,8 +1437,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) { // We are completing on contextual types, but may also include properties @@ -1454,7 +1455,7 @@ namespace ts.Completions { isNewIdentifierLocation = false; const rootDeclaration = getRootDeclaration(objectLikeContainer.parent); - if (!isVariableLike(rootDeclaration)) throw Debug.fail("Root declaration is not variable-like."); + if (!isVariableLike(rootDeclaration)) return Debug.fail("Root declaration is not variable-like."); // We don't want to complete using the type acquired by the shape // of the binding pattern; we are only interested in types acquired @@ -1542,7 +1543,7 @@ namespace ts.Completions { const implementsTypeNodes = getClassImplementsHeritageClauseElements(classLikeDeclaration); if (baseTypeNode || implementsTypeNodes) { 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()) { @@ -1557,18 +1558,18 @@ namespace ts.Completions { // No member list for private methods if (!(classElementModifierFlags & ModifierFlags.Private)) { - let baseClassTypeToGetPropertiesFrom: Type; + let baseClassTypeToGetPropertiesFrom: Type | undefined; if (baseTypeNode) { baseClassTypeToGetPropertiesFrom = typeChecker.getTypeAtLocation(baseTypeNode); if (classElementModifierFlags & ModifierFlags.Static) { // Use static class to get property symbols from baseClassTypeToGetPropertiesFrom = typeChecker.getTypeOfSymbolAtLocation( - baseClassTypeToGetPropertiesFrom.symbol, classLikeDeclaration); + baseClassTypeToGetPropertiesFrom!.symbol!, classLikeDeclaration); } } const implementedInterfaceTypePropertySymbols = (classElementModifierFlags & ModifierFlags.Static) ? emptyArray : - flatMap(implementsTypeNodes || emptyArray, typeNode => typeChecker.getPropertiesOfType(typeChecker.getTypeAtLocation(typeNode))); + flatMap(implementsTypeNodes || emptyArray, typeNode => typeChecker.getPropertiesOfType(typeChecker.getTypeAtLocation(typeNode)!)); // List of property symbols of base type that are not private and already implemented symbols = filterClassMembersList( @@ -1586,7 +1587,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 = { | @@ -1606,7 +1607,7 @@ namespace ts.Completions { * Returns the containing list of named imports or exports of a context token, * on the condition that one exists and that the context implies completion should be given. */ - function tryGetNamedImportsOrExportsForCompletion(contextToken: Node): NamedImportsOrExports { + function tryGetNamedImportsOrExportsForCompletion(contextToken: Node): NamedImportsOrExports | undefined { if (contextToken) { switch (contextToken.kind) { case SyntaxKind.OpenBraceToken: // import { | @@ -1640,19 +1641,20 @@ 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 tryGetClassLikeCompletionContainer(contextToken: Node): ClassLikeDeclaration { + function tryGetClassLikeCompletionContainer(contextToken: Node): ClassLikeDeclaration | undefined { if (contextToken) { + const parent = contextToken.parent; switch (contextToken.kind) { case SyntaxKind.OpenBraceToken: // class c { | - if (isClassLike(contextToken.parent)) { - return contextToken.parent; + if (isClassLike(parent)) { + return parent; } break; // class c {getValue(): number, | } case SyntaxKind.CommaToken: - if (isClassLike(contextToken.parent)) { - return contextToken.parent; + if (isClassLike(parent)) { + return parent; } break; @@ -1674,7 +1676,7 @@ namespace ts.Completions { if (isFromClassElementDeclaration(contextToken) && (isClassMemberCompletionKeyword(contextToken.kind) || isClassMemberCompletionKeywordText(contextToken.getText()))) { - return contextToken.parent.parent as ClassLikeDeclaration; + return parent.parent as ClassLikeDeclaration; } } } @@ -1690,23 +1692,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) => { @@ -1717,12 +1720,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) { @@ -1789,7 +1793,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 || @@ -1802,9 +1807,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 [.| @@ -1826,9 +1831,9 @@ namespace ts.Completions { case SyntaxKind.SemicolonToken: return containingNodeKind === SyntaxKind.PropertySignature && - contextToken.parent && contextToken.parent.parent && - (contextToken.parent.parent.kind === SyntaxKind.InterfaceDeclaration || // interface a { f; | - contextToken.parent.parent.kind === SyntaxKind.TypeLiteral); // const x : { a; | + !!parent.parent && + (parent.parent.kind === SyntaxKind.InterfaceDeclaration || // interface a { f; | + parent.parent.kind === SyntaxKind.TypeLiteral); // const x : { a; | case SyntaxKind.LessThanToken: return containingNodeKind === SyntaxKind.ClassDeclaration || // class A< | @@ -1838,17 +1843,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 || @@ -1986,23 +1990,23 @@ 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 { // TODO: Account for computed property name // NOTE: if one only performs this step when m.name is an identifier, // things like '__proto__' are not filtered out. - const name = getNameOfDeclaration(m); + const name = getNameOfDeclaration(m)!; // TODO: GH#18217 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)); @@ -2046,7 +2050,7 @@ namespace ts.Completions { continue; } - const existingName = getPropertyNameForPropertyNameNode(m.name); + const existingName = getPropertyNameForPropertyNameNode(m.name!); if (existingName) { existingMemberNames.set(existingName, true); } @@ -2145,7 +2149,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" @@ -2155,7 +2159,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. @@ -2174,7 +2178,7 @@ namespace ts.Completions { })); } - function isClassMemberCompletionKeyword(kind: SyntaxKind) { + function isClassMemberCompletionKeyword(kind: SyntaxKind | undefined): boolean { switch (kind) { case SyntaxKind.PublicKeyword: case SyntaxKind.ProtectedKeyword: @@ -2187,6 +2191,8 @@ namespace ts.Completions { case SyntaxKind.SetKeyword: case SyntaxKind.AsyncKeyword: return true; + default: + return false; } } @@ -2194,13 +2200,15 @@ namespace ts.Completions { return isClassMemberCompletionKeyword(stringToToken(text)); } - function isConstructorParameterCompletionKeyword(kind: SyntaxKind) { + function isConstructorParameterCompletionKeyword(kind: SyntaxKind | undefined): boolean { switch (kind) { case SyntaxKind.PublicKeyword: case SyntaxKind.PrivateKeyword: case SyntaxKind.ProtectedKeyword: case SyntaxKind.ReadonlyKeyword: return true; + default: + return false; } } diff --git a/src/services/documentHighlights.ts b/src/services/documentHighlights.ts index 6d3094fc19049..a6dcdf5d13c04 100644 --- a/src/services/documentHighlights.ts +++ b/src/services/documentHighlights.ts @@ -2,10 +2,10 @@ namespace ts.DocumentHighlights { export function getDocumentHighlights(program: Program, cancellationToken: CancellationToken, sourceFile: SourceFile, position: number, sourceFilesToSearch: ReadonlyArray): DocumentHighlights[] | undefined { const node = getTouchingWord(sourceFile, position, /*includeJsDocComment*/ true); - - if (node.parent && (isJsxOpeningElement(node.parent) && node.parent.tagName === node || isJsxClosingElement(node.parent))) { + const { parent } = node; + if (parent && (isJsxOpeningElement(parent) && parent.tagName === node || isJsxClosingElement(parent))) { // For a JSX element, just highlight the matching tag, not all references. - const { openingElement, closingElement } = node.parent.parent; + const { openingElement, closingElement } = parent.parent; const highlightSpans = [openingElement, closingElement].map(({ tagName }) => getHighlightSpanForNode(tagName, sourceFile)); return [{ fileName: sourceFile.fileName, highlightSpans }]; } @@ -28,7 +28,7 @@ namespace ts.DocumentHighlights { return arrayFrom(map.entries(), ([fileName, highlightSpans]) => ({ fileName, highlightSpans })); } - function getSyntacticDocumentHighlights(node: Node, sourceFile: SourceFile): DocumentHighlights[] { + function getSyntacticDocumentHighlights(node: Node, sourceFile: SourceFile): DocumentHighlights[] | undefined { const highlightSpans = getHighlightSpans(node, sourceFile); if (!highlightSpans || highlightSpans.length === 0) { return undefined; @@ -75,7 +75,7 @@ namespace ts.DocumentHighlights { } function getFromAllDeclarations(nodeTest: (node: Node) => node is T, keywords: ReadonlyArray): HighlightSpan[] | undefined { - return useParent(node.parent, nodeTest, decl => mapDefined(decl.symbol.declarations, d => + return useParent(node.parent, nodeTest, decl => mapDefined(decl.symbol!.declarations, d => nodeTest(d) ? find(d.getChildren(sourceFile), c => contains(keywords, c.kind)) : undefined)); } @@ -100,7 +100,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); @@ -111,7 +111,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) { @@ -150,11 +150,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: @@ -180,14 +179,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) { @@ -205,9 +204,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; @@ -241,7 +239,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(); @@ -256,14 +254,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) { @@ -286,15 +284,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); } }); }); @@ -305,21 +303,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) { @@ -355,7 +353,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)!); }); diff --git a/src/services/documentRegistry.ts b/src/services/documentRegistry.ts index 81742018fb7dd..f9e0ca8656a04 100644 --- a/src/services/documentRegistry.ts +++ b/src/services/documentRegistry.ts @@ -117,12 +117,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; references: string[]; }[] = []; entries.forEach((entry, name) => { sourceFiles.push({ @@ -174,7 +174,7 @@ namespace ts { let entry = bucket.get(path); if (!entry) { // Have never seen this file with these settings. Create a new source file for it. - const sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, /*setNodeParents*/ false, scriptKind); + const sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target!, version, /*setNodeParents*/ false, scriptKind); // TODO: GH#18217 entry = { sourceFile, @@ -189,7 +189,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 we're acquiring, then this is the first time this LS is asking for this document. @@ -215,7 +215,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 8100a021fb8ba..81f77864da0e1 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -44,12 +44,14 @@ namespace ts.FindAllReferences { export function findReferencedSymbols(program: Program, cancellationToken: CancellationToken, sourceFiles: ReadonlyArray, sourceFile: SourceFile, position: number): ReferencedSymbol[] | undefined { const referencedSymbols = findAllReferencedSymbols(program, cancellationToken, sourceFiles, sourceFile, position); const checker = program.getTypeChecker(); - return !referencedSymbols || !referencedSymbols.length ? undefined : mapDefined(referencedSymbols, ({ definition, references }) => + return !referencedSymbols || !referencedSymbols.length ? undefined : mapDefined(referencedSymbols, ({ definition, references }) => { // Only include referenced symbols that have a valid definition. - definition && { definition: definitionToReferencedSymbolDefinitionInfo(definition, checker), references: references.map(toReferenceEntry) }); + const info = definition && definitionToReferencedSymbolDefinitionInfo(definition, checker); + return info && { definition: info, references: references.map(toReferenceEntry) }; + }); } - 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); @@ -73,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 { @@ -96,12 +98,12 @@ namespace ts.FindAllReferences { return Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options); } - 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): ReferencedSymbolDefinitionInfo | undefined { - const info = (() => { + const info: { node: Node, name: string, kind: ScriptElementKind, displayParts: SymbolDisplayPart[] } = (() => { switch (def.type) { case "symbol": { const { symbol, node } = def; @@ -115,7 +117,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": { @@ -123,7 +125,7 @@ namespace ts.FindAllReferences { const symbol = checker.getSymbolAtLocation(node); const displayParts = symbol && SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind( checker, symbol, node.getSourceFile(), getContainerNode(node), node).displayParts; - return { node, name: "this", kind: ScriptElementKind.variableElement, displayParts }; + return { node, name: "this", kind: ScriptElementKind.variableElement, displayParts: displayParts! }; // TODO: GH#18217 } case "string": { const { node } = def; @@ -245,7 +247,7 @@ namespace ts.FindAllReferences.Core { export function getReferencedSymbolsForNode(position: number, node: Node, program: Program, sourceFiles: ReadonlyArray, cancellationToken: CancellationToken, options: Options = {}): SymbolAndEntries[] | undefined { if (isSourceFile(node)) { const reference = GoToDefinition.getReferenceAtPosition(node, position, program); - return reference && getReferencedSymbolsForModule(program, program.getTypeChecker().getMergedSymbol(reference.file.symbol), sourceFiles); + return reference && getReferencedSymbolsForModule(program, program.getTypeChecker().getMergedSymbol(reference.file.symbol!), sourceFiles); } if (!options.implementations) { @@ -304,7 +306,7 @@ namespace ts.FindAllReferences.Core { } }); - for (const decl of symbol.declarations) { + for (const decl of symbol.declarations!) { switch (decl.kind) { case ts.SyntaxKind.SourceFile: // Don't include the source file itself. (This may not be ideal behavior, but awkward to include an entire file as a reference.) @@ -318,7 +320,7 @@ namespace ts.FindAllReferences.Core { } return [{ - definition: { type: "symbol", symbol, node: symbol.valueDeclaration }, + definition: { type: "symbol", symbol, node: symbol.valueDeclaration! }, references }]; } @@ -359,7 +361,7 @@ namespace ts.FindAllReferences.Core { symbol = skipPastExportOrImportSpecifierOrUnion(symbol, node, checker) || symbol; // Compute the meaning from the location and the symbol it references - const searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(node), symbol.declarations); + const searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(node), symbol.declarations!); const result: SymbolAndEntries[] = []; const state = new State(sourceFiles, getSpecialSearchKind(node), checker, cancellationToken, searchMeaning, options, result); @@ -369,7 +371,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: populateSearchSymbolSet(symbol, node, checker, options.implementations) }); + const search = state.createSearch(node, symbol, /*comingFrom*/ undefined, { allSearchSymbols: populateSearchSymbolSet(symbol, node, checker, !!options.implementations) }); // 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). @@ -412,7 +414,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. @@ -500,7 +502,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.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`. */ @@ -514,7 +516,7 @@ namespace ts.FindAllReferences.Core { allSearchSymbols = undefined, } = searchOptions; const escapedText = escapeLeadingUnderscores(text); - const parents = this.options.implementations && getParentSymbolsOfPropertyAccess(location, symbol, this.checker); + const parents = this.options.implementations ? getParentSymbolsOfPropertyAccess(location, symbol, this.checker) : undefined; return { location, symbol, comingFrom, text, escapedText, parents, includes: referenceSymbol => allSearchSymbols ? contains(allSearchSymbols, referenceSymbol) : referenceSymbol === symbol, @@ -595,7 +597,7 @@ namespace ts.FindAllReferences.Core { // Go to the symbol we imported from and find references for it. function searchForImportedSymbol(symbol: Symbol, state: State): void { - for (const declaration of symbol.declarations) { + for (const declaration of symbol.declarations!) { getReferencesInSourceFile(declaration.getSourceFile(), state.createSearch(declaration, symbol, ImportExport.Import), state); } } @@ -608,8 +610,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 | undefined { @@ -679,7 +682,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 +709,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 } function getPossibleSymbolReferencePositions(sourceFile: SourceFile, symbolName: string, container: Node = sourceFile): ReadonlyArray { @@ -781,11 +784,11 @@ namespace ts.FindAllReferences.Core { } } - function getAllReferencesForKeyword(sourceFiles: ReadonlyArray, keywordKind: ts.SyntaxKind, cancellationToken: CancellationToken): SymbolAndEntries[] { + function getAllReferencesForKeyword(sourceFiles: ReadonlyArray, keywordKind: ts.SyntaxKind, cancellationToken: CancellationToken): SymbolAndEntries[] | undefined { const references: NodeEntry[] = []; for (const sourceFile of sourceFiles) { cancellationToken.throwIfCancellationRequested(); - addReferencesForKeywordInFile(sourceFile, keywordKind, tokenToString(keywordKind), references); + addReferencesForKeywordInFile(sourceFile, keywordKind, tokenToString(keywordKind)!, references); } return references.length ? [{ definition: { type: "keyword", node: references[0].node }, references }] : undefined; } @@ -847,7 +850,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; @@ -915,7 +918,7 @@ namespace ts.FindAllReferences.Core { const exportKind = referenceLocation.originalKeywordKind === ts.SyntaxKind.DefaultKeyword ? ExportKind.Default : ExportKind.Named; const exportInfo = getExportInfo(referenceSymbol, exportKind, state.checker); Debug.assert(!!exportInfo); - searchForImportsOfExport(referenceLocation, referenceSymbol, exportInfo, state); + searchForImportsOfExport(referenceLocation, referenceSymbol, exportInfo!, state); } // At `export { x } from "foo"`, also search for the imported symbol `"foo".x`. @@ -965,7 +968,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 @@ -974,7 +977,7 @@ namespace ts.FindAllReferences.Core { * position of property accessing, the referenceEntry of such position will be handled in the first case. */ if (!(flags & SymbolFlags.Transient) && search.includes(shorthandValueSymbol)) { - addReference(getNameOfDeclaration(valueDeclaration), shorthandValueSymbol, search.location, state); + addReference(getNameOfDeclaration(valueDeclaration!)!, shorthandValueSymbol, search.location, state); } } @@ -1024,7 +1027,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) { pusher(node); } @@ -1035,8 +1038,8 @@ namespace ts.FindAllReferences.Core { } } - function getPropertyAccessExpressionFromRightHandSide(node: Node): PropertyAccessExpression { - return isRightSideOfPropertyAccess(node) && node.parent; + function getPropertyAccessExpressionFromRightHandSide(node: Node): PropertyAccessExpression | undefined { + return isRightSideOfPropertyAccess(node) ? node.parent : undefined; } /** @@ -1044,13 +1047,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, ts.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; @@ -1067,13 +1070,13 @@ 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 symbol = cls.symbol!; + const ctr = symbol.members!.get(InternalSymbolName.Constructor); if (!ctr) { return; } - for (const decl of ctr.declarations) { + for (const decl of ctr.declarations!) { Debug.assert(decl.kind === SyntaxKind.Constructor); const body = (decl).body; if (body) { @@ -1113,11 +1116,11 @@ namespace ts.FindAllReferences.Core { const containingTypeReference = getContainingTypeReference(refNode); if (containingTypeReference && state.markSeenContainingTypeReference(containingTypeReference)) { const parent = containingTypeReference.parent; - if (hasType(parent) && parent.type === containingTypeReference && hasInitializer(parent) && isImplementationExpression(parent.initializer)) { - addReference(parent.initializer); + if (hasType(parent) && parent.type === containingTypeReference && hasInitializer(parent) && isImplementationExpression(parent.initializer!)) { + addReference(parent.initializer!); } else if (isFunctionLike(parent) && parent.type === containingTypeReference && (parent as FunctionLikeDeclaration).body) { - const body = (parent as FunctionLikeDeclaration).body; + const body = (parent as FunctionLikeDeclaration).body!; // TODO: GH#18217 if (body.kind === SyntaxKind.Block) { forEachReturnStatement(body, returnStatement => { if (returnStatement.expression && isImplementationExpression(returnStatement.expression)) { @@ -1147,8 +1150,8 @@ namespace ts.FindAllReferences.Core { return result; } - function getContainingTypeReference(node: Node): Node { - let topLevelTypeReference: Node = undefined; + function getContainingTypeReference(node: Node): Node | undefined { + let topLevelTypeReference: Node | undefined; while (node) { if (isTypeNode(node)) { @@ -1160,7 +1163,7 @@ namespace ts.FindAllReferences.Core { return topLevelTypeReference; } - function getContainingClassIfInHeritageClause(node: Node): ClassLikeDeclaration { + function getContainingClassIfInHeritageClause(node: Node): ClassLikeDeclaration | undefined { if (node && node.parent) { if (node.kind === SyntaxKind.ExpressionWithTypeArguments && node.parent.kind === SyntaxKind.HeritageClause @@ -1230,7 +1233,7 @@ namespace ts.FindAllReferences.Core { // Set the key so that we don't infinitely recurse cachedResults.set(key, false); - const inherits = forEach(symbol.getDeclarations(), declaration => { + const inherits = some(symbol.getDeclarations(), declaration => { if (isClassLike(declaration)) { if (parentIsInterface) { const interfaceReferences = getClassImplementsHeritageClauseElements(declaration); @@ -1242,11 +1245,11 @@ namespace ts.FindAllReferences.Core { } } } - return searchTypeReference(getClassExtendsHeritageClauseElement(declaration)); + return searchTypeReference(getClassExtendsHeritageClauseElement(declaration)!); // TODO: GH#18217 } else if (declaration.kind === SyntaxKind.InterfaceDeclaration) { if (parentIsInterface) { - return forEach(getInterfaceBaseTypeNodes(declaration), searchTypeReference); + return some(getInterfaceBaseTypeNodes(declaration), searchTypeReference); } } return false; @@ -1267,7 +1270,7 @@ namespace ts.FindAllReferences.Core { } } - function getReferencesForSuperKeyword(superKeyword: Node): SymbolAndEntries[] { + function getReferencesForSuperKeyword(superKeyword: Node): SymbolAndEntries[] | undefined { let searchSpaceNode = getSuperContainer(superKeyword, /*stopOnFunctions*/ false); if (!searchSpaceNode) { return undefined; @@ -1311,10 +1314,10 @@ namespace ts.FindAllReferences.Core { } } - return [{ definition: { type: "symbol", symbol: searchSpaceNode.symbol, node: superKeyword }, references }]; + return [{ definition: { type: "symbol", symbol: searchSpaceNode.symbol!, node: superKeyword }, 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. @@ -1508,7 +1511,7 @@ namespace ts.FindAllReferences.Core { } } - function getParameterPropertySymbols(symbol: Symbol, checker: TypeChecker): Symbol[] { + function getParameterPropertySymbols(symbol: Symbol, checker: TypeChecker): ReadonlyArray | undefined { return symbol.valueDeclaration && isParameter(symbol.valueDeclaration) && isParameterPropertyDeclaration(symbol.valueDeclaration) ? checker.getSymbolsOfParameterPropertyDeclaration(symbol.valueDeclaration, symbol.name) : undefined; @@ -1545,7 +1548,7 @@ namespace ts.FindAllReferences.Core { if (symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) { forEach(symbol.getDeclarations(), declaration => { if (isClassLike(declaration)) { - getPropertySymbolFromTypeReference(getClassExtendsHeritageClauseElement(declaration)); + getPropertySymbolFromTypeReference(getClassExtendsHeritageClauseElement(declaration)!); // TODO: GH#18217 forEach(getClassImplementsHeritageClauseElements(declaration), getPropertySymbolFromTypeReference); } else if (declaration.kind === SyntaxKind.InterfaceDeclaration) { @@ -1566,7 +1569,7 @@ namespace ts.FindAllReferences.Core { // Visit the typeReference as well to see if it directly or indirectly use that property previousIterationSymbolsCache.set(symbol.escapedName, symbol); - getPropertySymbolsFromBaseTypes(type.symbol, propertyName, result, previousIterationSymbolsCache, checker); + getPropertySymbolsFromBaseTypes(type.symbol!, propertyName, result, previousIterationSymbolsCache, checker); } } } @@ -1631,7 +1634,7 @@ namespace ts.FindAllReferences.Core { // parent symbol if (rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) { // Parents will only be defined if implementations is true - if (search.parents && !some(search.parents, parent => explicitlyInheritsFrom(rootSymbol.parent, parent, state.inheritsFromCache, checker))) { + if (search.parents && !some(search.parents, parent => explicitlyInheritsFrom(rootSymbol.parent!, parent, state.inheritsFromCache, checker))) { return undefined; } @@ -1645,16 +1648,17 @@ namespace ts.FindAllReferences.Core { } } - function getNameFromObjectLiteralElement(node: ObjectLiteralElement): string { - if (node.name.kind === SyntaxKind.ComputedPropertyName) { - const nameExpression = node.name.expression; + function getNameFromObjectLiteralElement(node: ObjectLiteralElement): string | undefined { + const name = node.name!; // TODO: GH#18217 + if (name.kind === SyntaxKind.ComputedPropertyName) { + const nameExpression = name.expression; // treat computed property names where expression is string/numeric literal as just string/numeric literal if (isStringOrNumericLiteral(nameExpression)) { return nameExpression.text; } return undefined; } - return getTextOfIdentifierOrLiteral(node.name); + return getTextOfIdentifierOrLiteral(name); } /** Gets all symbols for one property. Does not get symbols for every property. */ @@ -1663,7 +1667,7 @@ namespace ts.FindAllReferences.Core { const name = getNameFromObjectLiteralElement(node); const symbol = contextualType && name && contextualType.getProperty(name); return symbol ? [symbol] : - contextualType && contextualType.flags & TypeFlags.Union ? mapDefined((contextualType).types, t => t.getProperty(name)) : emptyArray; + contextualType && contextualType.flags & TypeFlags.Union ? mapDefined((contextualType).types, t => t.getProperty(name!)) : emptyArray; // TODO: GH#18217 } /** @@ -1708,7 +1712,7 @@ namespace ts.FindAllReferences.Core { } else if (node.kind === SyntaxKind.VariableDeclaration) { const parentStatement = getParentStatementOfVariableDeclaration(node); - return parentStatement && hasModifier(parentStatement, ModifierFlags.Ambient); + return !!parentStatement && hasModifier(parentStatement, ModifierFlags.Ambient); } else if (isFunctionLike(node)) { return !!(node as FunctionLikeDeclaration).body || hasModifier(node, ModifierFlags.Ambient); @@ -1725,7 +1729,7 @@ namespace ts.FindAllReferences.Core { return false; } - function getParentStatementOfVariableDeclaration(node: VariableDeclaration): VariableStatement { + function getParentStatementOfVariableDeclaration(node: VariableDeclaration): VariableStatement | undefined { if (node.parent && node.parent.parent && node.parent.parent.kind === SyntaxKind.VariableStatement) { Debug.assert(node.parent.kind === SyntaxKind.VariableDeclarationList); return node.parent.parent; @@ -1733,11 +1737,11 @@ namespace ts.FindAllReferences.Core { } export function getReferenceEntriesForShorthandPropertyAssignment(node: Node, checker: TypeChecker, addReference: (node: Node) => void): void { - const refSymbol = checker.getSymbolAtLocation(node); - const shorthandSymbol = checker.getShorthandAssignmentValueSymbol(refSymbol.valueDeclaration); + 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 3ed602d17fbbd..93a3e8c279169 100644 --- a/src/services/formatting/formatting.ts +++ b/src/services/formatting/formatting.ts @@ -19,9 +19,9 @@ namespace ts.formatting { } export interface TokenInfo { - leadingTrivia: TextRangeWithTriviaKind[]; + leadingTrivia: TextRangeWithTriviaKind[] | undefined; token: TextRangeWithKind; - trailingTrivia: TextRangeWithTriviaKind[]; + trailingTrivia: TextRangeWithTriviaKind[] | undefined; } const enum Constants { @@ -125,7 +125,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 }; @@ -179,11 +179,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; } @@ -200,7 +200,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: @@ -240,8 +240,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; @@ -259,12 +259,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; } @@ -321,7 +321,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) { @@ -329,7 +329,7 @@ namespace ts.formatting { } if (SmartIndenter.shouldIndentChildNode(n, child)) { - return options.indentSize; + return options.indentSize!; // TODO: GH#18217 } previousLine = line; @@ -354,7 +354,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 []; } @@ -418,7 +418,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(); } } @@ -470,7 +470,7 @@ namespace ts.formatting { parentDynamicIndentation: DynamicIndentation, effectiveParentStartLine: number ): { indentation: number, delta: number } { - const delta = SmartIndenter.shouldIndentChildNode(node) ? options.indentSize : 0; + const delta = SmartIndenter.shouldIndentChildNode(node) ? options.indentSize! : 0; if (effectiveParentStartLine === startLine) { // if node is located on the same line with the parent @@ -478,7 +478,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) { @@ -517,7 +517,7 @@ namespace ts.formatting { // falls through case SyntaxKind.PropertyDeclaration: case SyntaxKind.Parameter: - return getNameOfDeclaration(node).kind; + return getNameOfDeclaration(node)!.kind; } } @@ -542,8 +542,8 @@ namespace ts.formatting { getDelta, recomputeIndentation: lineAdded => { if (node.parent && SmartIndenter.shouldIndentChildNode(node.parent, node)) { - indentation += lineAdded ? options.indentSize : -options.indentSize; - delta = SmartIndenter.shouldIndentChildNode(node) ? options.indentSize : 0; + indentation += lineAdded ? options.indentSize! : -options.indentSize!; + delta = SmartIndenter.shouldIndentChildNode(node) ? options.indentSize! : 0; } } }; @@ -860,6 +860,7 @@ namespace ts.formatting { } } + // TODO: GH#18217 use an enum instead of `boolean | undefined` function processRange(range: TextRangeWithKind, rangeStart: LineAndCharacter, parent: Node, @@ -939,7 +940,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 @@ -959,7 +960,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!; // TODO: GH#18217 } else { column++; @@ -1119,7 +1120,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!); // TODO: GH#18217 return onLaterLine ? LineAction.None : LineAction.LineAdded; } break; @@ -1236,8 +1237,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 @@ -1245,13 +1246,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! }; // TODO: GH#18217 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!); // TODO: GH#18217 + const spaces = indentation - tabs * options.tabSize!; let tabString: string; if (!internedTabsIndentation) { @@ -1269,14 +1270,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!); // TODO: GH#18217 + 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 2ba987e4af39c..c033c8e02fc30 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: ts.FormatCodeSettings) { } diff --git a/src/services/formatting/formattingScanner.ts b/src/services/formatting/formattingScanner.ts index 9b9c956f670a6..11a7d85ef81b0 100644 --- a/src/services/formatting/formattingScanner.ts +++ b/src/services/formatting/formattingScanner.ts @@ -10,7 +10,7 @@ namespace ts.formatting { advance(): void; isOnToken(): boolean; readTokenInfo(n: Node): TokenInfo; - getCurrentLeadingTrivia(): TextRangeWithKind[]; + getCurrentLeadingTrivia(): TextRangeWithKind[] | undefined; lastTrailingTriviaWasNewLine(): boolean; skipToEndOf(node: Node): void; } @@ -57,7 +57,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 815237df22869..6aa27660f4551 100644 --- a/src/services/formatting/rules.ts +++ b/src/services/formatting/rules.ts @@ -667,7 +667,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 f124c444f6d69..95aff36f45bde 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(current, previous, /*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(parent, current, isNextChild) && !parentAndChildShareLine) { - indentationDelta += options.indentSize; + indentationDelta += options.indentSize!; // TODO: GH#18217 } // 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; @@ -325,11 +327,11 @@ namespace ts.formatting { 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) { switch (node.parent.kind) { case SyntaxKind.TypeReference: - return getListIfStartEndIsInListRange((node.parent).typeArguments, node.getStart(sourceFile), node.getEnd()); + return getListIfStartEndIsInListRange((node.parent).typeArguments!, node.getStart(sourceFile), node.getEnd()); case SyntaxKind.ObjectLiteralExpression: return (node.parent).properties; case SyntaxKind.ArrayLiteralExpression: @@ -344,15 +346,15 @@ namespace ts.formatting { case SyntaxKind.ConstructorType: case SyntaxKind.ConstructSignature: { const start = node.getStart(sourceFile); - return getListIfStartEndIsInListRange((node.parent).typeParameters, start, node.getEnd()) || + return getListIfStartEndIsInListRange((node.parent).typeParameters!, start, node.getEnd()) || getListIfStartEndIsInListRange((node.parent).parameters, start, node.getEnd()); } case SyntaxKind.ClassDeclaration: - return getListIfStartEndIsInListRange((node.parent).typeParameters, node.getStart(sourceFile), node.getEnd()); + return getListIfStartEndIsInListRange((node.parent).typeParameters!, node.getStart(sourceFile), node.getEnd()); case SyntaxKind.NewExpression: case SyntaxKind.CallExpression: { const start = node.getStart(sourceFile); - return getListIfStartEndIsInListRange((node.parent).typeArguments, start, node.getEnd()) || + return getListIfStartEndIsInListRange((node.parent).typeArguments!, start, node.getEnd()) || getListIfStartEndIsInListRange((node.parent).arguments, start, node.getEnd()); } case SyntaxKind.VariableDeclarationList: @@ -463,7 +465,7 @@ namespace ts.formatting { } if (ch === CharacterCodes.tab) { - column += options.tabSize + (column % options.tabSize); + column += options.tabSize! + (column % options.tabSize!); // TODO: GH#18217 } else { column++; @@ -552,7 +554,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: @@ -583,7 +585,7 @@ namespace ts.formatting { case SyntaxKind.ModuleBlock: return true; default: - throw Debug.fail(); + return Debug.fail(); } case SyntaxKind.ContinueStatement: case SyntaxKind.BreakStatement: diff --git a/src/services/goToDefinition.ts b/src/services/goToDefinition.ts index 6be00efd53f69..1754e9e06a30d 100644 --- a/src/services/goToDefinition.ts +++ b/src/services/goToDefinition.ts @@ -1,6 +1,6 @@ /* @internal */ namespace ts.GoToDefinition { - export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile, position: number): DefinitionInfo[] { + export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile, position: number): DefinitionInfo[] | undefined { const reference = getReferenceAtPosition(sourceFile, position, program); if (reference) { return [getDefinitionInfoForFileReference(reference.fileName, reference.file.fileName)]; @@ -10,12 +10,13 @@ namespace ts.GoToDefinition { if (node === sourceFile) { return undefined; } + const { parent } = node; // Labels if (isJumpStatementTarget(node)) { const labelName = (node).text; - const label = getTargetLabel((node.parent), labelName); - return label ? [createDefinitionInfoFromName(label, ScriptElementKind.label, labelName, /*containerName*/ undefined)] : undefined; + const label = getTargetLabel((parent), labelName); + return label ? [createDefinitionInfoFromName(label, ScriptElementKind.label, labelName, /*containerName*/ undefined!)] : undefined; // TODO: GH#18217 } const typeChecker = program.getTypeChecker(); @@ -37,7 +38,7 @@ namespace ts.GoToDefinition { // get the aliased symbol instead. This allows for goto def on an import e.g. // import {A, B} from "mod"; // to jump to the implementation directly. - if (symbol.flags & SymbolFlags.Alias && shouldSkipAlias(node, symbol.declarations[0])) { + if (symbol.flags & SymbolFlags.Alias && shouldSkipAlias(node, symbol.declarations![0])) { const aliased = typeChecker.getAliasedSymbol(symbol); if (aliased.declarations) { symbol = aliased; @@ -49,8 +50,8 @@ namespace ts.GoToDefinition { // go to the declaration of the property name (in this case stay at the same position). However, if go-to-definition // is performed at the location of property access, we would like to go to definition of the property in the short-hand // assignment. This case and others are handled by the following code. - if (node.parent.kind === SyntaxKind.ShorthandPropertyAssignment) { - const shorthandSymbol = typeChecker.getShorthandAssignmentValueSymbol(symbol.valueDeclaration); + if (parent.kind === SyntaxKind.ShorthandPropertyAssignment) { + const shorthandSymbol = typeChecker.getShorthandAssignmentValueSymbol(symbol.valueDeclaration!); if (!shorthandSymbol) { return []; } @@ -58,7 +59,7 @@ namespace ts.GoToDefinition { const shorthandDeclarations = shorthandSymbol.getDeclarations(); const shorthandSymbolKind = SymbolDisplay.getSymbolKind(typeChecker, shorthandSymbol, node); const shorthandSymbolName = typeChecker.symbolToString(shorthandSymbol); - const shorthandContainerName = typeChecker.symbolToString(symbol.parent, node); + const shorthandContainerName = typeChecker.symbolToString(symbol.parent!, node); return map(shorthandDeclarations, declaration => createDefinitionInfo(declaration, shorthandSymbolKind, shorthandSymbolName, shorthandContainerName)); } @@ -74,9 +75,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) { @@ -112,7 +113,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 }; } @@ -120,7 +121,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; @@ -139,7 +140,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) { @@ -181,7 +182,7 @@ namespace ts.GoToDefinition { } } - function getDefinitionFromSymbol(typeChecker: TypeChecker, symbol: Symbol, node: Node): DefinitionInfo[] { + function getDefinitionFromSymbol(typeChecker: TypeChecker, symbol: Symbol, node: Node): DefinitionInfo[] | undefined { const { symbolName, symbolKind, containerName } = getSymbolInfo(typeChecker, symbol, node); return getConstructSignatureDefinition() || getCallSignatureDefinition() || map(symbol.declarations, declaration => createDefinitionInfo(declaration, symbolKind, symbolName, containerName)); @@ -189,7 +190,7 @@ namespace ts.GoToDefinition { // Applicable only if we are in a new expression, or we are on a constructor declaration // and in either case the symbol has a construct signature definition, i.e. class if (symbol.flags & SymbolFlags.Class && (isNewExpressionTarget(node) || node.kind === SyntaxKind.ConstructorKeyword)) { - const cls = find(symbol.declarations, isClassLike) || Debug.fail("Expected declaration to have at least one class-like declaration"); + const cls = find(symbol.declarations!, isClassLike) || Debug.fail("Expected declaration to have at least one class-like declaration"); return getSignatureDefinition(cls.members, /*selectConstructors*/ true); } } @@ -237,7 +238,7 @@ namespace ts.GoToDefinition { textSpan: createTextSpanFromNode(name, sourceFile), kind: symbolKind, name: symbolName, - containerKind: undefined, + containerKind: undefined!, // TODO: GH#18217 containerName }; } @@ -251,7 +252,7 @@ namespace ts.GoToDefinition { } function createDefinitionFromSignatureDeclaration(typeChecker: TypeChecker, decl: SignatureDeclaration): DefinitionInfo { - const { symbolName, symbolKind, containerName } = getSymbolInfo(typeChecker, decl.symbol, decl); + const { symbolName, symbolKind, containerName } = getSymbolInfo(typeChecker, decl.symbol!, decl); return createDefinitionInfo(decl, symbolKind, symbolName, containerName); } @@ -270,8 +271,8 @@ namespace ts.GoToDefinition { textSpan: createTextSpanFromBounds(0, 0), kind: ScriptElementKind.scriptElement, name, - containerName: undefined, - containerKind: undefined + containerName: undefined!, + containerKind: undefined!, // TODO: GH#18217 }; } @@ -279,7 +280,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 a9e2f20272638..7d13734e7be90 100644 --- a/src/services/importTracker.ts +++ b/src/services/importTracker.ts @@ -48,7 +48,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); @@ -61,14 +61,14 @@ namespace ts.FindAllReferences { } // Module augmentations may use this module's exports without importing it. - for (const decl of exportingModuleSymbol.declarations) { + for (const decl of exportingModuleSymbol.declarations!) { if (isExternalModuleAugmentation(decl)) { addIndirectUser(decl as SourceFileLike); } } // 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 { @@ -84,7 +84,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 ts.VariableDeclaration; if (name.kind === SyntaxKind.Identifier) { @@ -153,7 +153,7 @@ namespace ts.FindAllReferences { Debug.assert(!isAvailableThroughGlobal); const isNew = markSeenIndirectUser(sourceFileLike); if (isNew) { - indirectUserDeclarations.push(sourceFileLike); + indirectUserDeclarations!.push(sourceFileLike); // TODO: GH#18217 } return isNew; } @@ -164,7 +164,7 @@ namespace ts.FindAllReferences { return; } - const moduleSymbol = checker.getMergedSymbol(sourceFileLike.symbol); + const moduleSymbol = checker.getMergedSymbol(sourceFileLike.symbol!); Debug.assert(!!(moduleSymbol.flags & SymbolFlags.Module)); const directImports = getDirectImports(moduleSymbol); if (directImports) { @@ -213,7 +213,7 @@ namespace ts.FindAllReferences { } // Ignore if there's a grammar error - if (decl.moduleSpecifier.kind !== SyntaxKind.StringLiteral) { + if (decl.moduleSpecifier!.kind !== SyntaxKind.StringLiteral) { return; } @@ -234,7 +234,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 @@ -242,13 +242,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 === symbolName(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 (!isForRename && exportKind === ExportKind.Default) { - searchForNamedImport(namedBindings as NamedImports | undefined); + searchForNamedImport(namedBindings as NamedImports | undefined); // tslint:disable-line no-unnecessary-type-assertion (TODO: GH#18217) } } } @@ -261,7 +261,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)!); } } @@ -281,13 +281,13 @@ namespace ts.FindAllReferences { singleReferences.push(propertyName); if (!isForRename) { // If renaming `foo`, don't touch `bar`, just `foo`. // 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); } } @@ -303,7 +303,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 (statement.kind !== SyntaxKind.ExportDeclaration) return; const { exportClause, moduleSpecifier } = statement as ExportDeclaration; @@ -326,7 +326,7 @@ namespace ts.FindAllReferences { const refs: ModuleReference[] = []; const checker = program.getTypeChecker(); for (const referencingFile of sourceFiles) { - const searchSourceFile = searchModuleSymbol.valueDeclaration; + const searchSourceFile = searchModuleSymbol.valueDeclaration!; if (searchSourceFile.kind === ts.SyntaxKind.SourceFile) { for (const ref of referencingFile.referencedFiles) { if (program.getSourceFileFromReference(referencingFile, ref) === searchSourceFile) { @@ -374,8 +374,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))); } @@ -402,7 +402,7 @@ namespace ts.FindAllReferences { const decl = statement as ImportEqualsDeclaration; const { moduleReference } = decl; if (moduleReference.kind === SyntaxKind.ExternalModuleReference && - moduleReference.expression.kind === SyntaxKind.StringLiteral) { + moduleReference.expression!.kind === SyntaxKind.StringLiteral) { action(decl, moduleReference.expression as StringLiteral); } break; @@ -422,7 +422,7 @@ namespace ts.FindAllReferences { case SyntaxKind.ExternalModuleReference: return (decl as ExternalModuleReference).parent; default: - Debug.fail("Unexpected module specifier parent: " + decl.kind); + return Debug.fail("Unexpected module specifier parent: " + decl.kind); } } @@ -448,13 +448,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 { @@ -470,7 +471,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 { @@ -482,21 +483,21 @@ 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); } } function getExportAssignmentExport(ex: ExportAssignment): ExportedSymbol { // Get the symbol for the `export =` node; its parent is the module it's the export of. - const exportingModuleSymbol = Debug.assertDefined(ex.symbol.parent, "Expected export symbol to have a parent"); + const exportingModuleSymbol = Debug.assertDefined(ex.symbol!.parent, "Expected export symbol to have a parent"); const exportKind = ex.isExportEquals ? ExportKind.ExportEquals : ExportKind.Default; return { kind: ImportExport.Export, symbol, exportInfo: { exportingModuleSymbol, exportKind } }; } @@ -516,8 +517,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); } @@ -547,13 +548,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; } } @@ -563,7 +564,7 @@ namespace ts.FindAllReferences { return Debug.assertDefined(checker.getImmediateAliasedSymbol(importedSymbol)); } - const decl = importedSymbol.valueDeclaration; + const decl = importedSymbol.valueDeclaration!; if (isExportAssignment(decl)) { // `export = class {}` return Debug.assertDefined(decl.expression.symbol); } @@ -620,7 +621,7 @@ namespace ts.FindAllReferences { return forEach(symbol.declarations, decl => { const name = getNameOfDeclaration(decl); - return name && name.kind === SyntaxKind.Identifier && name.escapedText; + return name && name.kind === SyntaxKind.Identifier ? name.escapedText : undefined; }); } @@ -630,7 +631,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)!; } } } @@ -638,7 +639,7 @@ namespace ts.FindAllReferences { } function getContainingModuleSymbol(importer: Importer, checker: TypeChecker): Symbol { - return checker.getMergedSymbol(getSourceFileLikeForImportDeclaration(importer).symbol); + return checker.getMergedSymbol(getSourceFileLikeForImportDeclaration(importer).symbol!); } function getSourceFileLikeForImportDeclaration(node: ImporterOrCallExpression): SourceFileLike { @@ -647,7 +648,6 @@ namespace ts.FindAllReferences { } const { parent } = node; - if (parent.kind === SyntaxKind.SourceFile) { return parent as SourceFile; } @@ -660,6 +660,6 @@ namespace ts.FindAllReferences { } function isExternalModuleImportEquals({ moduleReference }: ImportEqualsDeclaration): boolean { - return moduleReference.kind === SyntaxKind.ExternalModuleReference && moduleReference.expression.kind === SyntaxKind.StringLiteral; + return moduleReference.kind === SyntaxKind.ExternalModuleReference && moduleReference.expression!.kind === SyntaxKind.StringLiteral; } } diff --git a/src/services/jsDoc.ts b/src/services/jsDoc.ts index cf3c9606fb471..c0267e96e4727 100644 --- a/src/services/jsDoc.ts +++ b/src/services/jsDoc.ts @@ -96,7 +96,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.JSDocPropertyTag: case SyntaxKind.JSDocParameterTag: @@ -124,7 +124,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: T[], callback: (element: T, index: number) => U): U { + function forEachUnique(array: T[] | 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) { @@ -181,13 +181,13 @@ namespace ts.JsDoc { const nameThusFar = tag.name.text; const jsdoc = tag.parent; const fn = jsdoc.parent; - if (!ts.isFunctionLike(fn)) return []; + if (!isFunctionLike(fn)) return []; return mapDefined(fn.parameters, param => { 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; } @@ -322,7 +322,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 }; } diff --git a/src/services/jsTyping.ts b/src/services/jsTyping.ts index bd6c2e5cb9f9c..e60bc5cc2c681 100644 --- a/src/services/jsTyping.ts +++ b/src/services/jsTyping.ts @@ -13,7 +13,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 { @@ -34,7 +34,7 @@ namespace ts.JsTyping { /* @internal */ export function isTypingUpToDate(cachedTyping: JsTyping.CachedTyping, availableTypingVersions: MapLike) { - const availableVersion = Semver.parse(getProperty(availableTypingVersions, `ts${ts.versionMajorMinor}`) || getProperty(availableTypingVersions, "latest")); + const availableVersion = Semver.parse(getProperty(availableTypingVersions, `ts${ts.versionMajorMinor}`) || getProperty(availableTypingVersions, "latest")!); return !availableVersion.greaterThan(cachedTyping.version); } @@ -128,7 +128,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); @@ -136,7 +136,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); } }); @@ -163,7 +163,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) { @@ -318,9 +318,9 @@ namespace ts.JsTyping { case PackageNameValidationResult.NameContainsNonURISafeCharacters: return `Package name '${typing}' contains non URI safe characters`; case PackageNameValidationResult.Ok: - throw Debug.fail(); // Shouldn't have called this. + 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 21d8a79275992..2ebfe71585b52 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); let rawItems: RawNavigateToItem[] = []; @@ -48,7 +48,7 @@ namespace ts.NavigateTo { // It was a match! If the pattern has dots in it, then also see if the // declaration container matches as well. - let containerMatches = matches; + let containerMatches: ReadonlyArray | undefined = matches; if (patternMatcher.patternContainsDots) { containerMatches = patternMatcher.getMatches(getContainers(declaration), name); if (!containerMatches) { @@ -67,7 +67,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: @@ -125,12 +125,12 @@ namespace ts.NavigateTo { return false; } - function getContainers(declaration: Declaration): string[] { + function getContainers(declaration: Declaration): string[] | undefined { const containers: string[] = []; // First, if we started with a computed property name, then add all but the last // portion into the container array. - const name = getNameOfDeclaration(declaration); + const name = getNameOfDeclaration(declaration)!; // TODO: GH#18217 if (name.kind === SyntaxKind.ComputedPropertyName) { if (!tryAddComputedPropertyName(name.expression, containers, /*includeLastPortion*/ false)) { return undefined; @@ -138,14 +138,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; @@ -185,7 +185,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 cdc7b2b186435..50bcde88540f2 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -67,10 +67,10 @@ namespace ts.NavigationBar { } function reset() { - curSourceFile = undefined; - curCancellationToken = undefined; + curSourceFile = undefined!; + curCancellationToken = undefined!; parentsStack = []; - parent = undefined; + parent = undefined!; emptyChildItemArray = []; } @@ -136,17 +136,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)) { @@ -368,7 +368,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. */ @@ -392,7 +393,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)); } @@ -408,7 +409,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: @@ -534,7 +535,7 @@ namespace ts.NavigationBar { return false; } - switch (navigationBarNodeKind(item.parent)) { + switch (navigationBarNodeKind(item.parent!)) { case SyntaxKind.ModuleBlock: case SyntaxKind.SourceFile: case SyntaxKind.MethodDeclaration: @@ -544,8 +545,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; }); @@ -624,7 +625,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 e75db1aa59d45..f62e9a5c8ef12 100644 --- a/src/services/organizeImports.ts +++ b/src/services/organizeImports.ts @@ -14,7 +14,7 @@ namespace ts.OrganizeImports { return []; } - const oldImportGroups = group(oldImportDecls, importDecl => getExternalModuleName(importDecl.moduleSpecifier)); + const oldImportGroups = group(oldImportDecls, importDecl => getExternalModuleName(importDecl.moduleSpecifier)!); // TODO: GH#18217 const sortedImportGroups = stableSort(oldImportGroups, (group1, group2) => compareModuleSpecifiers(group1[0].moduleSpecifier, group2[0].moduleSpecifier)); @@ -192,7 +192,7 @@ namespace ts.OrganizeImports { const name1 = getExternalModuleName(m1); const name2 = getExternalModuleName(m2); return compareBooleans(name1 === undefined, name2 === undefined) || - compareBooleans(isExternalModuleNameRelative(name1), isExternalModuleNameRelative(name2)) || + compareBooleans(isExternalModuleNameRelative(name1!), isExternalModuleNameRelative(name2!)) || compareStringsCaseSensitive(name1, name2); } } \ No newline at end of file diff --git a/src/services/pathCompletions.ts b/src/services/pathCompletions.ts index fd639aef81764..c380c44ea908d 100644 --- a/src/services/pathCompletions.ts +++ b/src/services/pathCompletions.ts @@ -45,10 +45,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); @@ -157,9 +157,9 @@ namespace ts.Completions.PathCompletions { const absolute = isRootedDiskPath(baseUrl) ? baseUrl : combinePaths(projectDir, baseUrl); getCompletionEntriesForDirectoryFragment(fragment, normalizePath(absolute), fileExtensions, /*includeExtensions*/ false, span, 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)) { @@ -173,7 +173,7 @@ namespace ts.Completions.PathCompletions { if (compilerOptions.moduleResolution === ts.ModuleResolutionKind.NodeJs) { forEachAncestorDirectory(scriptPath, ancestor => { const nodeModules = combinePaths(ancestor, "node_modules"); - if (host.directoryExists(nodeModules)) { + if (host.directoryExists!(nodeModules)) { // TODO: GH#18217 getCompletionEntriesForDirectoryFragment(fragment, nodeModules, fileExtensions, /*includeExtensions*/ false, span, host, /*exclude*/ undefined, result); } }); @@ -268,7 +268,7 @@ namespace ts.Completions.PathCompletions { // after the last '/' that appears in the fragment because that's where the replacement span // starts if (isNestedModule) { - const moduleNameWithSeperator = ensureTrailingDirectorySeparator(moduleNameFragment); + const moduleNameWithSeperator = ensureTrailingDirectorySeparator(moduleNameFragment!); nonRelativeModuleNames = map(nonRelativeModuleNames, nonRelativeModuleName => { return removePrefix(nonRelativeModuleName, moduleNameWithSeperator); }); @@ -276,11 +276,11 @@ namespace ts.Completions.PathCompletions { if (!options.moduleResolution || options.moduleResolution === ModuleResolutionKind.NodeJs) { - for (const visibleModule of enumerateNodeModulesVisibleToScript(host, scriptPath)) { + for (const visibleModule of enumerateNodeModulesVisibleToScript(host, scriptPath)!) { // TODO: GH#18217 if (!isNestedModule) { nonRelativeModuleNames.push(visibleModule.moduleName); } - else if (startsWith(visibleModule.moduleName, moduleNameFragment)) { + else if (startsWith(visibleModule.moduleName, moduleNameFragment!)) { // TODO: GH#18217 const nestedFiles = tryReadDirectory(host, visibleModule.moduleDir, supportedTypeScriptExtensions, /*exclude*/ undefined, /*include*/ ["./*"]); if (nestedFiles) { for (let f of nestedFiles) { @@ -293,7 +293,7 @@ namespace ts.Completions.PathCompletions { } } - return deduplicate(nonRelativeModuleNames, equateStringsCaseSensitive, compareStringsCaseSensitive); + return deduplicate(nonRelativeModuleNames, equateStringsCaseSensitive, compareStringsCaseSensitive); } export function getTripleSlashReferenceCompletion(sourceFile: SourceFile, position: number, compilerOptions: CompilerOptions, host: LanguageServiceHost): PathCompletion[] | undefined { @@ -337,7 +337,7 @@ namespace ts.Completions.PathCompletions { } } else if (host.getDirectories) { - let typeRoots: ReadonlyArray; + let typeRoots: ReadonlyArray | undefined; try { typeRoots = getEffectiveTypeRoots(options, host); } @@ -393,7 +393,7 @@ namespace ts.Completions.PathCompletions { return paths; } - function enumerateNodeModulesVisibleToScript(host: LanguageServiceHost, scriptPath: string) { + function enumerateNodeModulesVisibleToScript(host: LanguageServiceHost, scriptPath: string): VisibleModuleInfo[] | undefined { const result: VisibleModuleInfo[] = []; if (host.readFile && host.fileExists) { @@ -513,10 +513,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 db957816146bb..7196df2a0a2e9 100644 --- a/src/services/patternMatcher.ts +++ b/src/services/patternMatcher.ts @@ -42,12 +42,12 @@ namespace ts { // this will return a successful match, having only tested "SK" against "SyntaxKind". At // that point a call can be made to 'getMatches("SyntaxKind", "ts.compiler")', with the // work to create 'ts.compiler' only being done once the first match succeeded. - getMatchesForLastSegmentOfPattern(candidate: string): PatternMatch[]; + getMatchesForLastSegmentOfPattern(candidate: string): PatternMatch[] | undefined; // Fully checks a candidate, with an dotted container, against the search pattern. // The candidate must match the last part of the search pattern, and the dotted container // must match the preceding segments of the pattern. - getMatches(candidateContainers: string[], candidate: string): PatternMatch[] | undefined; + getMatches(candidateContainers: string[] | undefined, candidate: string): PatternMatch[] | undefined; // Whether or not the pattern contained dots or not. Clients can use this to determine // If they should call getMatches, or if getMatchesForLastSegmentOfPattern is sufficient. @@ -131,15 +131,15 @@ namespace ts { return invalidPattern || !candidate; } - function getMatchesForLastSegmentOfPattern(candidate: string): PatternMatch[] { + function getMatchesForLastSegmentOfPattern(candidate: string): PatternMatch[] | undefined { if (skipMatch(candidate)) { return undefined; } - return matchSegment(candidate, lastOrUndefined(dotSeparatedSegments)); + return matchSegment(candidate, last(dotSeparatedSegments)); } - function getMatches(candidateContainers: string[], candidate: string): PatternMatch[] | undefined { + function getMatches(candidateContainers: string[] | undefined, candidate: string): PatternMatch[] | undefined { if (skipMatch(candidate)) { return undefined; } @@ -147,7 +147,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)); + const candidateMatch = matchSegment(candidate, last(dotSeparatedSegments)); if (!candidateMatch) { return undefined; } @@ -195,7 +195,7 @@ namespace ts { return spans; } - function matchTextChunk(candidate: string, chunk: TextChunk, punctuationStripped: boolean): PatternMatch { + function matchTextChunk(candidate: string, chunk: TextChunk, punctuationStripped: boolean): PatternMatch | undefined { const index = indexOfIgnoringCase(candidate, chunk.textLowerCase); if (index === 0) { if (chunk.text.length === candidate.length) { @@ -283,7 +283,7 @@ namespace ts { return false; } - function matchSegment(candidate: string, segment: Segment): PatternMatch[] { + function matchSegment(candidate: string, segment: Segment): 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 @@ -336,7 +336,7 @@ namespace ts { // Only if all words have some sort of match is the pattern considered matched. const subWordTextChunks = segment.subWordTextChunks; - let matches: PatternMatch[] = undefined; + let matches: PatternMatch[] | undefined; for (const subWordTextChunk of subWordTextChunks) { // Try to match the candidate with this word @@ -383,7 +383,7 @@ namespace ts { return true; } - function tryCamelCaseMatch(candidate: string, candidateParts: TextSpan[], chunk: TextChunk, ignoreCase: boolean): number { + function tryCamelCaseMatch(candidate: string, candidateParts: TextSpan[], chunk: TextChunk, ignoreCase: boolean): number | undefined { const chunkCharacterSpans = chunk.characterSpans; // Note: we may have more pattern parts than candidate parts. This is because multiple @@ -393,8 +393,8 @@ namespace ts { let currentCandidate = 0; let currentChunkSpan = 0; - let firstMatch: number = undefined; - let contiguous: boolean = undefined; + 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 a99683d45effa..9858db04ef99d 100644 --- a/src/services/preProcess.ts +++ b/src/services/preProcess.ts @@ -3,7 +3,7 @@ namespace ts { const referencedFiles: FileReference[] = []; const typeReferenceDirectives: FileReference[] = []; const importedFiles: FileReference[] = []; - let ambientExternalModules: { ref: FileReference, depth: number }[]; + let ambientExternalModules: { ref: FileReference, depth: number }[] | undefined; let isNoDefaultLib = false; let braceNesting = 0; // assume that text represent an external module if it contains at least one top level import/export @@ -27,7 +27,7 @@ namespace ts { const comment = sourceText.substring(commentRange.pos, commentRange.end); const referencePathMatchResult = getFileReferenceFromReferencePath(comment, commentRange); if (referencePathMatchResult) { - isNoDefaultLib = referencePathMatchResult.isNoDefaultLib; + isNoDefaultLib = !!referencePathMatchResult.isNoDefaultLib; const fileReference = referencePathMatchResult.fileReference; if (fileReference) { const collection = referencePathMatchResult.isTypeReferenceDirective @@ -341,7 +341,7 @@ namespace ts { } 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) { diff --git a/src/services/refactors/annotateWithTypeFromJSDoc.ts b/src/services/refactors/annotateWithTypeFromJSDoc.ts index 3258da4636a51..eb52eacefc5b2 100644 --- a/src/services/refactors/annotateWithTypeFromJSDoc.ts +++ b/src/services/refactors/annotateWithTypeFromJSDoc.ts @@ -32,7 +32,7 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { } } - function hasUsableJSDoc(decl: DeclarationWithType): boolean { + function hasUsableJSDoc(decl: DeclarationWithType | undefined): boolean { if (!decl) { return false; } @@ -67,7 +67,7 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { function getEditsForAnnotation(context: RefactorContext): RefactorEditInfo | undefined { const sourceFile = context.file; const token = getTokenAtPosition(sourceFile, context.startPosition, /*includeJsDocComment*/ false); - const decl = findAncestor(token, isDeclarationWithType); + const decl = findAncestor(token, isDeclarationWithType)!; // TODO: GH#18217 const jsdocType = getJSDocType(decl); if (!decl || !jsdocType || decl.type) { return Debug.fail(`!decl || !jsdocType || decl.type: !${decl} || !${jsdocType} || ${decl.type}`); @@ -87,7 +87,7 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { function getEditsForFunctionAnnotation(context: RefactorContext): RefactorEditInfo | undefined { const sourceFile = context.file; const token = getTokenAtPosition(sourceFile, context.startPosition, /*includeJsDocComment*/ false); - const decl = findAncestor(token, isFunctionLikeDeclaration); + const decl = findAncestor(token, isFunctionLikeDeclaration)!; // TODO:GH#18217 const changeTracker = textChanges.ChangeTracker.fromContext(context); const functionWithType = addTypesToFunctionLike(decl); suppressLeadingAndTrailingTrivia(functionWithType); @@ -145,7 +145,7 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { } } - function transformJSDocType(node: Node): Node | undefined { + function transformJSDocType(node: Node | undefined): Node | undefined { if (node === undefined) { return undefined; } @@ -168,7 +168,7 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { case SyntaxKind.TypeReference: return transformJSDocTypeReference(node as TypeReferenceNode); default: - const visited = visitEachChild(node, transformJSDocType, /*context*/ undefined) as TypeNode; + const visited = visitEachChild(node, transformJSDocType, /*context*/ undefined!) as TypeNode; // TODO: GH#18217 setEmitFlags(visited, EmitFlags.SingleLine); return visited; } @@ -193,7 +193,7 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { 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); @@ -236,11 +236,11 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { /*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/refactors/convertFunctionToEs6Class.ts b/src/services/refactors/convertFunctionToEs6Class.ts index ddb13c3e04ce7..969e04bc91267 100644 --- a/src/services/refactors/convertFunctionToEs6Class.ts +++ b/src/services/refactors/convertFunctionToEs6Class.ts @@ -17,7 +17,7 @@ namespace ts.refactor.convertFunctionToES6Class { } if (isDeclarationOfFunctionOrClassExpression(symbol)) { - symbol = (symbol.valueDeclaration as VariableDeclaration).initializer.symbol; + symbol = (symbol.valueDeclaration as VariableDeclaration).initializer!.symbol!; } if ((symbol.flags & SymbolFlags.Function) && symbol.members && (symbol.members.size > 0)) { @@ -43,7 +43,7 @@ namespace ts.refactor.convertFunctionToES6Class { } const { file: sourceFile } = context; - const ctorSymbol = getConstructorSymbol(context); + const ctorSymbol = getConstructorSymbol(context)!; const deletedNodes: Node[] = []; const deletes: (() => any)[] = []; @@ -52,11 +52,11 @@ namespace ts.refactor.convertFunctionToES6Class { return undefined; } - const ctorDeclaration = ctorSymbol.valueDeclaration; + const ctorDeclaration = ctorSymbol.valueDeclaration!; const changeTracker = textChanges.ChangeTracker.fromContext(context); let precedingNode: Node; - let newClassDeclaration: ClassDeclaration; + let newClassDeclaration: ClassDeclaration | undefined; switch (ctorDeclaration.kind) { case SyntaxKind.FunctionDeclaration: precedingNode = ctorDeclaration; @@ -74,6 +74,9 @@ namespace ts.refactor.convertFunctionToES6Class { } newClassDeclaration = createClassFromVariableDeclaration(ctorDeclaration as VariableDeclaration); break; + + default: + return Debug.fail(); } if (!newClassDeclaration) { @@ -136,7 +139,7 @@ namespace ts.refactor.convertFunctionToES6Class { return isFunctionLike(source); } - function createClassElement(symbol: Symbol, modifiers: Modifier[]): ClassElement { + function createClassElement(symbol: Symbol, modifiers: Modifier[] | undefined): ClassElement | undefined { // both properties and methods are bound as property symbols if (!(symbol.flags & SymbolFlags.Property)) { return; @@ -219,7 +222,7 @@ namespace ts.refactor.convertFunctionToES6Class { }); } - 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; @@ -229,7 +232,7 @@ namespace ts.refactor.convertFunctionToES6Class { return undefined; } - const memberElements = createClassElementsFromSymbol(initializer.symbol); + const memberElements = createClassElementsFromSymbol(initializer.symbol!); if (initializer.body) { memberElements.unshift(createConstructor(/*decorators*/ undefined, /*modifiers*/ undefined, initializer.parameters, initializer.body)); } @@ -259,7 +262,7 @@ namespace ts.refactor.convertFunctionToES6Class { } } - function getConstructorSymbol({ startPosition, file, program }: RefactorContext): Symbol { + function getConstructorSymbol({ startPosition, file, program }: RefactorContext): Symbol | undefined { const checker = program.getTypeChecker(); const token = getTokenAtPosition(file, startPosition, /*includeJsDocComment*/ false); return checker.getSymbolAtLocation(token); diff --git a/src/services/refactors/convertToEs6Module.ts b/src/services/refactors/convertToEs6Module.ts index 6ed9cbec2ee97..e1a2023e5aca3 100644 --- a/src/services/refactors/convertToEs6Module.ts +++ b/src/services/refactors/convertToEs6Module.ts @@ -71,7 +71,7 @@ namespace ts.refactor { const { file, program } = context; Debug.assert(isSourceFileJavaScript(file)); const edits = textChanges.ChangeTracker.with(context, changes => { - const moduleExportsChangedToDefault = convertFileToEs6Module(file, program.getTypeChecker(), changes, program.getCompilerOptions().target); + const moduleExportsChangedToDefault = convertFileToEs6Module(file, program.getTypeChecker(), changes, program.getCompilerOptions().target!); if (moduleExportsChangedToDefault) { for (const importingFile of program.getSourceFiles()) { fixImportOfModuleExports(importingFile, file, changes); @@ -197,7 +197,8 @@ namespace ts.refactor { const { declarationList } = statement; let foundImport = false; const newNodes = flatMap(declarationList.declarations, decl => { - const { name, initializer } = decl; + const { name } = decl; + const initializer = decl.initializer!; // TODO: GH#18217 if (isExportsOrModuleExportsOrAlias(sourceFile, initializer)) { // `const alias = module.exports;` can be removed. foundImport = true; @@ -238,7 +239,7 @@ namespace ts.refactor { // `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); } } @@ -291,7 +292,7 @@ namespace ts.refactor { case SyntaxKind.SpreadAssignment: return undefined; case SyntaxKind.PropertyAssignment: - return !isIdentifier(prop.name) ? undefined : convertExportsDotXEquals(prop.name.text, prop.initializer); + return !isIdentifier(prop.name) ? undefined : convertExportsDotXEquals(prop.name.text, prop.initializer!); // TODO: GH#18217 case SyntaxKind.MethodDeclaration: return !isIdentifier(prop.name) ? undefined : functionExpressionToDeclaration(prop.name.text, [createToken(SyntaxKind.ExportKeyword)], prop); default: @@ -356,7 +357,7 @@ namespace ts.refactor { // `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) @@ -394,7 +395,7 @@ namespace ts.refactor { function exportConst() { // `exports.x = 0;` --> `export const x = 0;` - return makeConst(modifiers, createIdentifier(name), exported); + return makeConst(modifiers, createIdentifier(name!), exported); // TODO: GH#18217 } } @@ -417,7 +418,7 @@ namespace ts.refactor { 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)]; } @@ -437,7 +438,7 @@ namespace ts.refactor { case SyntaxKind.Identifier: return convertSingleIdentifierImport(file, name, moduleSpecifier, changes, checker, identifiers); default: - Debug.assertNever(name); + return Debug.assertNever(name); } } @@ -452,7 +453,7 @@ namespace ts.refactor { // 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; @@ -539,7 +540,7 @@ namespace ts.refactor { 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 { @@ -558,7 +559,7 @@ namespace ts.refactor { : makeImport(/*name*/ undefined, [makeImportSpecifier(propertyName, localName)], moduleSpecifier); } - function makeImport(name: Identifier | undefined, namedImports: ReadonlyArray, moduleSpecifier: string): ImportDeclaration { + function makeImport(name: Identifier | undefined, namedImports: ReadonlyArray | undefined, moduleSpecifier: string): ImportDeclaration { const importClause = (name || namedImports) && createImportClause(name, namedImports && createNamedImports(namedImports)); return createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, importClause, createLiteral(moduleSpecifier)); } diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index 65c9fd6268c3e..d6f257c4540c1 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -13,7 +13,7 @@ namespace ts.refactor.extractSymbol { export function getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] | undefined { const rangeToExtract = getRangeToExtract(context.file, { start: context.startPosition, length: getRefactorContextLength(context) }); - const targetRange: TargetRange = rangeToExtract.targetRange; + const targetRange = rangeToExtract.targetRange; if (targetRange === undefined) { return undefined; } @@ -91,7 +91,7 @@ namespace ts.refactor.extractSymbol { /* Exported for tests */ export function getEditsForAction(context: RefactorContext, actionName: string): RefactorEditInfo | undefined { const rangeToExtract = getRangeToExtract(context.file, { start: context.startPosition, length: getRefactorContextLength(context) }); - const targetRange: TargetRange = rangeToExtract.targetRange; + const targetRange = rangeToExtract.targetRange!; // TODO:GH#18217 const parsedFunctionIndexMatch = /^function_scope_(\d+)$/.exec(actionName); if (parsedFunctionIndexMatch) { @@ -223,7 +223,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) { @@ -260,13 +261,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; @@ -282,7 +283,7 @@ namespace ts.refactor.extractSymbol { } } if (numInitializers === 1) { - return lastInitializer; + return lastInitializer!; } // No special handling if there are multiple initializers. } @@ -312,7 +313,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; } @@ -351,12 +352,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[]; @@ -373,25 +374,28 @@ 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); + declarations.push(node.symbol!); } // 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; } } @@ -401,13 +405,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 (node.parent.kind === SyntaxKind.SourceFile && (node.parent as ts.SourceFile).externalModuleIndicator === undefined) { // You cannot extract global declarations - (errors || (errors = [])).push(createDiagnosticForNode(node, Messages.functionWillNotBeVisibleInTheNewScope)); + (errors || (errors = [] as Diagnostic[])).push(createDiagnosticForNode(node, Messages.functionWillNotBeVisibleInTheNewScope)); } break; } @@ -463,13 +467,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; @@ -485,7 +489,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: @@ -498,7 +502,7 @@ namespace ts.refactor.extractSymbol { } } - function getStatementOrExpressionRange(node: Node): Statement[] | Expression { + function getStatementOrExpressionRange(node: Node): Statement[] | Expression | undefined { if (isStatement(node)) { return [node]; } @@ -540,7 +544,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. @@ -560,7 +564,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); } @@ -568,7 +572,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; @@ -648,7 +652,7 @@ namespace ts.refactor.extractSymbol { enclosingTextRange, sourceFile, context.program.getTypeChecker(), - context.cancellationToken); + context.cancellationToken!); return { scopes, readsAndWrites }; } @@ -682,7 +686,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 { @@ -730,12 +734,12 @@ namespace ts.refactor.extractSymbol { const functionName = createIdentifier(functionNameText); - let returnType: TypeNode = undefined; + let returnType: TypeNode | undefined; const parameters: ParameterDeclaration[] = []; const callArguments: Identifier[] = []; - let writes: UsageEntry[]; + let writes: UsageEntry[] | undefined; usagesInScope.forEach((usage, name) => { - let typeNode: TypeNode = undefined; + 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) {" @@ -775,7 +779,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)); @@ -872,14 +876,14 @@ 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); typeElements.push(createPropertySignature( /*modifiers*/ undefined, - /*name*/ variableDeclaration.symbol.name, + /*name*/ variableDeclaration.symbol!.name, /*questionToken*/ undefined, /*type*/ variableType, /*initializer*/ undefined)); @@ -914,7 +918,7 @@ namespace ts.refactor.extractSymbol { newNodes.push(createVariableStatement( /*modifiers*/ undefined, createVariableDeclarationList( - [createVariableDeclaration(variableDeclaration.symbol.name, getTypeDeepCloneUnionUndefined(variableDeclaration.type))], + [createVariableDeclaration(variableDeclaration.symbol!.name, getTypeDeepCloneUnionUndefined(variableDeclaration.type))], flags))); } } @@ -1017,7 +1021,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); @@ -1043,7 +1047,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)); @@ -1189,7 +1193,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 { @@ -1197,13 +1201,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 @@ -1233,7 +1237,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); @@ -1266,7 +1270,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; } @@ -1297,7 +1301,7 @@ namespace ts.refactor.extractSymbol { const members = scope.members; Debug.assert(members.length > 0); // There must be at least one child, since we extracted from one. - let prevMember: ClassElement | undefined = undefined; + let prevMember: ClassElement | undefined; let allProperties = true; for (const member of members) { if (member.pos > maxPos) { @@ -1316,7 +1320,7 @@ namespace ts.refactor.extractSymbol { } Debug.assert(prevMember !== undefined); // If the loop didn't return, then it did set prevMember. - return prevMember; + return prevMember!; } function getNodeToInsertConstantBefore(node: Node, scope: Scope): Statement { @@ -1347,25 +1351,23 @@ namespace ts.refactor.extractSymbol { // There must be at least one statement since we started in one. Debug.assert(prevStatement !== undefined); - return prevStatement; + return 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 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); @@ -1447,7 +1449,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); } @@ -1487,7 +1489,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); } @@ -1582,14 +1584,8 @@ namespace ts.refactor.extractSymbol { node.typeParameters.length > 0; } - function isInGenericContext(node: Node) { - for (; node; node = node.parent) { - if (hasTypeParameters(node)) { - return true; - } - } - - return false; + function isInGenericContext(node: Node): boolean { + return !!findAncestor(node, hasTypeParameters); } function recordTypeParameterUsages(type: Type) { @@ -1608,7 +1604,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); } @@ -1751,7 +1747,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); @@ -1779,7 +1775,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; } @@ -1797,7 +1793,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) { @@ -1822,15 +1818,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: @@ -1838,9 +1835,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/useDefaultImport.ts b/src/services/refactors/useDefaultImport.ts index 080092e16ab6a..13898e09d7caf 100644 --- a/src/services/refactors/useDefaultImport.ts +++ b/src/services/refactors/useDefaultImport.ts @@ -63,14 +63,19 @@ namespace ts.refactor.installTypesForPackage { case SyntaxKind.ImportEqualsDeclaration: const eq = node as ImportEqualsDeclaration; const { moduleReference } = eq; - return moduleReference.kind === SyntaxKind.ExternalModuleReference && isStringLiteral(moduleReference.expression) - ? { importStatement: eq, name: eq.name, moduleSpecifier: moduleReference.expression } - : undefined; + if (moduleReference.kind === SyntaxKind.ExternalModuleReference) { + const moduleSpecifier = moduleReference.expression!; + if (isStringLiteral(moduleSpecifier)) { + return { importStatement: eq, name: eq.name, moduleSpecifier }; + } + } + return undefined; case SyntaxKind.ImportDeclaration: const d = node as ImportDeclaration; const { importClause } = d; - return importClause && !importClause.name && importClause.namedBindings.kind === SyntaxKind.NamespaceImport && isStringLiteral(d.moduleSpecifier) - ? { importStatement: d, name: importClause.namedBindings.name, moduleSpecifier: d.moduleSpecifier } + const namedBindings = (importClause && importClause.namedBindings)!; // TODO: GH#18217 + return importClause && !importClause.name && namedBindings.kind === SyntaxKind.NamespaceImport && isStringLiteral(d.moduleSpecifier) + ? { importStatement: d, name: namedBindings.name, moduleSpecifier: d.moduleSpecifier } : undefined; // For known child node kinds of convertible imports, try again with parent node. case SyntaxKind.NamespaceImport: diff --git a/src/services/rename.ts b/src/services/rename.ts index ca46a93f3c979..11efea2dc6d55 100644 --- a/src/services/rename.ts +++ b/src/services/rename.ts @@ -34,7 +34,7 @@ namespace ts.Rename { // Cannot rename `default` as in `import { default as foo } from "./someModule"; if (node.kind === SyntaxKind.Identifier && (node as Identifier).originalKeywordKind === SyntaxKind.DefaultKeyword && - symbol.parent.flags & ts.SymbolFlags.Module) { + symbol.parent!.flags & ts.SymbolFlags.Module) { // TODO: GH#18217 return undefined; } @@ -74,14 +74,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 fe7606fd8ad16..f9af534a1ed99 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -34,7 +34,7 @@ namespace ts { /** The version of the language service API */ export const servicesVersion = "0.7"; - 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); @@ -58,8 +58,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; } @@ -217,20 +217,20 @@ namespace ts { return this._children; } - 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 = ts.find(children, kid => kid.kind < SyntaxKind.FirstJSDocNode || kid.kind > SyntaxKind.LastJSDocNode); + const child = ts.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); @@ -242,7 +242,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); } } @@ -260,7 +260,7 @@ namespace ts { this.pos = pos; this.end = end; this.flags = NodeFlags.None; - this.parent = undefined; + this.parent = undefined!; } public getSourceFile(): SourceFile { @@ -307,22 +307,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; } } @@ -470,7 +470,7 @@ namespace ts { return this.checker.getIndexTypeOfType(this, IndexKind.Number); } getBaseTypes(): BaseType[] | undefined { - return this.flags & TypeFlags.Object && this.objectFlags & (ObjectFlags.Class | ObjectFlags.Interface) + return this.flags & TypeFlags.Object && this.objectFlags! & (ObjectFlags.Class | ObjectFlags.Interface) ? this.checker.getBaseTypes(this) : undefined; } @@ -528,7 +528,7 @@ namespace ts { this.documentationComment = JsDoc.getJsDocCommentsFromDeclarations([this.declaration]); if (this.documentationComment.length === 0 || hasJSDocInheritDocTag(this.declaration)) { - const inheritedDocs = findInheritedJSDocComments(this.declaration, this.declaration.symbol.getName(), this.checker); + const inheritedDocs = findInheritedJSDocComments(this.declaration, this.declaration.symbol!.getName(), this.checker); if (this.documentationComment.length > 0) { inheritedDocs.push(ts.lineBreakPart()); } @@ -676,7 +676,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(); } @@ -799,7 +799,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; @@ -905,7 +905,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(""); } @@ -985,7 +985,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[] { @@ -996,12 +996,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 } } @@ -1025,7 +1025,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 @@ -1062,7 +1062,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) { @@ -1121,11 +1121,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 { @@ -1173,7 +1173,7 @@ namespace ts { let lastProjectVersion: string; let lastTypesRootVersion = 0; - const useCaseSensitivefileNames = host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(); + const useCaseSensitivefileNames = !!host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(); const cancellationToken = new CancellationTokenObject(host.getCancellationToken && host.getCancellationToken()); const currentDirectory = host.getCurrentDirectory(); @@ -1214,7 +1214,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; } @@ -1225,7 +1225,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; } @@ -1258,7 +1258,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); }, @@ -1270,15 +1270,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); }; } @@ -1287,19 +1287,19 @@ 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!; // Make sure all the nodes in the program are both bound, and have their parent // pointers set property. 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 @@ -1309,11 +1309,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 @@ -1375,16 +1375,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 @@ -1421,7 +1421,7 @@ namespace ts { return [...program.getOptionsDiagnostics(cancellationToken), ...program.getGlobalDiagnostics(cancellationToken)]; } - function getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions = { includeExternalModuleExports: false, includeInsertTextCompletions: false }): CompletionInfo { + function getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions = { includeExternalModuleExports: false, includeInsertTextCompletions: false }): CompletionInfo | undefined { synchronizeHostData(); return Completions.getCompletionsAtPosition( host, @@ -1434,7 +1434,7 @@ namespace ts { options); } - function getCompletionEntryDetails(fileName: string, position: number, name: string, formattingOptions?: FormatCodeSettings, source?: string): CompletionEntryDetails { + function getCompletionEntryDetails(fileName: string, position: number, name: string, formattingOptions?: FormatCodeSettings, source?: string): CompletionEntryDetails | undefined { synchronizeHostData(); return Completions.getCompletionEntryDetails( program, @@ -1445,11 +1445,11 @@ namespace ts { { name, source }, program.getSourceFiles(), host, - formattingOptions && formatting.getFormatContext(formattingOptions), + (formattingOptions && formatting.getFormatContext(formattingOptions))!, // TODO: GH#18217 getCanonicalFileName); } - 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.getTypeChecker(), @@ -1461,7 +1461,7 @@ namespace ts { program.getSourceFiles()); } - function getQuickInfoAtPosition(fileName: string, position: number): QuickInfo { + function getQuickInfoAtPosition(fileName: string, position: number): QuickInfo | undefined { synchronizeHostData(); const sourceFile = getValidSourceFile(fileName); @@ -1515,14 +1515,14 @@ namespace ts { } function getSymbolAtLocationForQuickInfo(node: Node, checker: TypeChecker): Symbol | undefined { - if ((isIdentifier(node) || isStringLiteral(node)) - && isPropertyAssignment(node.parent) - && node.parent.name === node) { - const type = checker.getContextualType(node.parent.parent); - if (type) { - const property = checker.getPropertyOfType(type, getTextOfIdentifierOrLiteral(node)); - if (property) { - return property; + if ((isIdentifier(node) || isStringLiteral(node))) { + if (isPropertyAssignment(node.parent) && node.parent.name === node) { + const type = checker.getContextualType(node.parent.parent); + if (type) { + const property = checker.getPropertyOfType(type, getTextOfIdentifierOrLiteral(node)); + if (property) { + return property; + } } } } @@ -1530,29 +1530,29 @@ namespace ts { } /// Goto definition - function getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] { + function getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] | undefined { synchronizeHostData(); return GoToDefinition.getDefinitionAtPosition(program, getValidSourceFile(fileName), position); } - function getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan { + function getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan | undefined { synchronizeHostData(); return GoToDefinition.getDefinitionAndBoundSpan(program, getValidSourceFile(fileName), position); } - function getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] { + function getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] | undefined { synchronizeHostData(); return GoToDefinition.getTypeDefinitionAtPosition(program.getTypeChecker(), getValidSourceFile(fileName), position); } /// Goto implementation - function getImplementationAtPosition(fileName: string, position: number): ImplementationLocation[] { + function getImplementationAtPosition(fileName: string, position: number): ImplementationLocation[] | undefined { synchronizeHostData(); return 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 { const canonicalFileName = getCanonicalFileName(normalizeSlashes(fileName)); return flatMap(getDocumentHighlights(fileName, position, [fileName]), entry => entry.highlightSpans.map(highlightSpan => { Debug.assert(getCanonicalFileName(normalizeSlashes(entry.fileName)) === canonicalFileName); // Get occurrences only supports reporting occurrences for the file queried. @@ -1566,22 +1566,22 @@ namespace ts { })); } - function getDocumentHighlights(fileName: string, position: number, filesToSearch: ReadonlyArray): DocumentHighlights[] { + function getDocumentHighlights(fileName: string, position: number, filesToSearch: ReadonlyArray): DocumentHighlights[] | undefined { synchronizeHostData(); const sourceFilesToSearch = map(filesToSearch, f => Debug.assertDefined(program.getSourceFile(f))); const sourceFile = getValidSourceFile(fileName); 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. @@ -1600,20 +1600,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 ts.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); @@ -1625,7 +1625,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); @@ -1642,14 +1642,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) { @@ -1667,7 +1667,7 @@ namespace ts { // Cant create the text span default: - return; + return undefined; } let nodeForStartPos = node; @@ -1699,7 +1699,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); @@ -1860,7 +1860,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. } } @@ -1905,7 +1905,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 = ts.formatting.getRangeOfEnclosingComment(sourceFile, position, onlyMultiLine); return range && createTextSpanFromRange(range); @@ -1931,7 +1931,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(); @@ -1964,7 +1964,7 @@ namespace ts { continue; } - let descriptor: TodoCommentDescriptor = undefined; + let descriptor: TodoCommentDescriptor | undefined; for (let i = 0; i < descriptors.length; i++) { if (matchArray[i + firstDescriptorCaptureIndex]) { descriptor = descriptors[i]; @@ -1974,12 +1974,12 @@ namespace ts { // We don't want to match something like 'TODOBY', so we make sure a non // letter/digit follows the match. - if (isLetterOrDigit(fileContents.charCodeAt(matchPosition + descriptor.text.length))) { + if (isLetterOrDigit(fileContents.charCodeAt(matchPosition + descriptor!.text.length))) { continue; } const message = matchArray[2]; - result.push({ descriptor, message, position: matchPosition }); + result.push({ descriptor: descriptor!, message, position: matchPosition }); } } @@ -2072,7 +2072,7 @@ namespace ts { endPosition, program: getProgram(), host, - formatContext: formatting.getFormatContext(formatOptions), + formatContext: formatting.getFormatContext(formatOptions!), // TODO: GH#18217 cancellationToken, }; } @@ -2092,7 +2092,7 @@ namespace ts { synchronizeHostData(); const file = getValidSourceFile(fileName); - return refactor.getEditsForRefactor(getRefactorContext(file, positionOrRange, formatOptions), refactorName, actionName); + return refactor.getEditsForRefactor(getRefactorContext(file, positionOrRange, formatOptions), refactorName, actionName)!; // TODO: GH#18217 } return { @@ -2155,7 +2155,7 @@ namespace ts { initializeNameTable(sourceFile); } - return sourceFile.nameTable; + return sourceFile.nameTable!; // TODO: GH#18217 } function initializeNameTable(sourceFile: SourceFile): void { @@ -2168,7 +2168,7 @@ namespace ts { forEachChild(node, walk); if (hasJSDocNodes(node)) { - for (const jsDoc of node.jsDoc) { + for (const jsDoc of node.jsDoc!) { forEachChild(jsDoc, walk); } } @@ -2192,7 +2192,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: @@ -2211,8 +2211,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 11e397f526aa3..0f85544881cf8 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -307,14 +307,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); } @@ -323,7 +323,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)`? } } } @@ -342,10 +342,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 }); }; } @@ -354,8 +354,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 }; } } @@ -379,7 +379,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(); @@ -412,14 +412,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; @@ -464,7 +464,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), @@ -497,13 +497,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), @@ -529,7 +529,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(); @@ -539,7 +539,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) { @@ -552,7 +552,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 /// TODO: no need for the tolowerCase call category: DiagnosticCategory[diagnostic.category].toLowerCase(), code: diagnostic.code @@ -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); } @@ -1030,14 +1030,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) { @@ -1115,7 +1115,7 @@ namespace ts { ); } - private convertFileReferences(refs: FileReference[]): ShimsFileReference[] { + private convertFileReferences(refs: FileReference[]): ShimsFileReference[] | undefined { if (!refs) { return undefined; } @@ -1226,7 +1226,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 250127ecfc620..41892705f59dc 100644 --- a/src/services/signatureHelp.ts +++ b/src/services/signatureHelp.ts @@ -17,7 +17,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 @@ -48,10 +48,10 @@ namespace ts.SignatureHelp { return undefined; } - return createSignatureHelpItems(candidates, resolvedSignature, argumentInfo, typeChecker); + return createSignatureHelpItems(candidates, resolvedSignature!, argumentInfo, typeChecker); } - function createJavaScriptSignatureHelpItems(argumentInfo: ArgumentListInfo, program: Program): SignatureHelpItems { + function createJavaScriptSignatureHelpItems(argumentInfo: ArgumentListInfo, program: Program): SignatureHelpItems | undefined { if (argumentInfo.invocation.kind !== SyntaxKind.CallExpression) { return undefined; } @@ -91,9 +91,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: @@ -113,7 +113,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; } @@ -129,22 +129,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); @@ -153,7 +153,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; @@ -229,7 +229,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++; } @@ -305,7 +305,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); } @@ -314,7 +314,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; @@ -370,8 +370,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); @@ -380,7 +380,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); } }); @@ -416,17 +416,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); }); @@ -440,12 +440,12 @@ 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); }); return { - name: typeParameter.symbol.name, + name: typeParameter.symbol!.name, documentation: emptyArray, displayParts, isOptional: false diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts index 135e906143fbe..93c0088560c1e 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -107,23 +107,23 @@ 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 = ts.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 documentationFromAlias: SymbolDisplayPart[] | 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) { @@ -132,7 +132,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) { @@ -144,24 +144,24 @@ 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; } else if (isCallExpressionTarget(location) || isNewExpressionTarget(location)) { callExpressionLike = location.parent; } - else if (location.parent && isJsxOpeningLikeElement(location.parent) && isFunctionLike(symbol.valueDeclaration)) { + else if (location.parent && isJsxOpeningLikeElement(location.parent) && isFunctionLike(symbol.valueDeclaration!)) { callExpressionLike = location.parent; } 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 @@ -173,7 +173,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; @@ -200,8 +200,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 (!(type.flags & TypeFlags.Object && (type).objectFlags & ObjectFlags.Anonymous) && type.symbol) { - addRange(displayParts, symbolToDisplayParts(typeChecker, type.symbol, enclosingDeclaration, /*meaning*/ undefined, SymbolFormatFlags.AllowAnyNodeKind | SymbolFormatFlags.WriteTypeParametersOrArguments)); + if (!(type!.flags & TypeFlags.Object && (type).objectFlags & ObjectFlags.Anonymous) && type!.symbol) { + addRange(displayParts, symbolToDisplayParts(typeChecker, type!.symbol!, enclosingDeclaration, /*meaning*/ undefined, SymbolFormatFlags.AllowAnyNodeKind | SymbolFormatFlags.WriteTypeParametersOrArguments)); displayParts.push(lineBreakPart()); } if (useConstructSignatures) { @@ -223,13 +223,13 @@ namespace ts.SymbolDisplay { // get the signature from the declaration and write it const functionDeclaration = location.parent; // Use function declaration to write the signatures only if the symbol corresponding to this declaration - const locationIsSymbolDeclaration = find(symbol.declarations, declaration => + const locationIsSymbolDeclaration = find(symbol.declarations!, declaration => // TODO: GH#18217 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]; @@ -238,12 +238,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); @@ -320,18 +320,18 @@ namespace ts.SymbolDisplay { // Method/function type parameter const decl = getDeclarationOfKind(symbol, SyntaxKind.TypeParameter); Debug.assert(decl !== undefined); - const declaration = decl.parent; + 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()); } else if (declaration.kind !== SyntaxKind.CallSignature && (declaration).name) { - addFullSymbolName(declaration.symbol); + addFullSymbolName(declaration.symbol!); } addRange(displayParts, signatureToDisplayParts(typeChecker, signature, sourceFile, TypeFormatFlags.WriteTypeArgumentsOfSignature)); } @@ -342,8 +342,8 @@ namespace ts.SymbolDisplay { addInPrefix(); displayParts.push(keywordPart(SyntaxKind.TypeKeyword)); displayParts.push(spacePart()); - addFullSymbolName(declaration.symbol); - writeTypeParametersOfSymbol(declaration.symbol, sourceFile); + addFullSymbolName(declaration.symbol!); + writeTypeParametersOfSymbol(declaration.symbol!, sourceFile); } } } @@ -351,7 +351,7 @@ namespace ts.SymbolDisplay { if (symbolFlags & SymbolFlags.EnumMember) { symbolKind = ScriptElementKind.enumMemberElement; addPrefixForAnyFunctionOrVar(symbol, "enum member"); - const declaration = symbol.declarations[0]; + const declaration = symbol.declarations![0]; if (declaration.kind === SyntaxKind.EnumMember) { const constantValue = typeChecker.getConstantValue(declaration); if (constantValue !== undefined) { @@ -390,7 +390,7 @@ namespace ts.SymbolDisplay { } } - switch (symbol.declarations[0].kind) { + switch (symbol.declarations![0].kind) { case SyntaxKind.NamespaceExportDeclaration: displayParts.push(keywordPart(SyntaxKind.ExportKeyword)); displayParts.push(spacePart()); @@ -399,7 +399,7 @@ namespace ts.SymbolDisplay { case SyntaxKind.ExportAssignment: displayParts.push(keywordPart(SyntaxKind.ExportKeyword)); displayParts.push(spacePart()); - displayParts.push(keywordPart((symbol.declarations[0] as ExportAssignment).isExportEquals ? SyntaxKind.EqualsToken : SyntaxKind.DefaultKeyword)); + displayParts.push(keywordPart((symbol.declarations![0] as ExportAssignment).isExportEquals ? SyntaxKind.EqualsToken : SyntaxKind.DefaultKeyword)); break; default: displayParts.push(keywordPart(SyntaxKind.ImportKeyword)); @@ -453,7 +453,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); @@ -488,7 +488,7 @@ namespace ts.SymbolDisplay { // there documentation comments might be attached to the right hand side symbol of their declarations. // The pattern of such special property access is that the parent symbol is the symbol of the file. if (symbol.parent && forEach(symbol.parent.declarations, declaration => declaration.kind === SyntaxKind.SourceFile)) { - for (const declaration of symbol.declarations) { + for (const declaration of symbol.declarations!) { if (!declaration.parent || declaration.parent.kind !== SyntaxKind.BinaryExpression) { continue; } @@ -579,7 +579,7 @@ namespace ts.SymbolDisplay { } function addSignatureDisplayParts(signature: Signature, allSignatures: Signature[], flags?: TypeFormatFlags) { - addRange(displayParts, signatureToDisplayParts(typeChecker, signature, enclosingDeclaration, flags | TypeFormatFlags.WriteTypeArgumentsOfSignature)); + addRange(displayParts, signatureToDisplayParts(typeChecker, signature, enclosingDeclaration, flags! | TypeFormatFlags.WriteTypeArgumentsOfSignature)); if (allSignatures.length > 1) { displayParts.push(spacePart()); displayParts.push(punctuationPart(SyntaxKind.OpenParenToken)); @@ -593,7 +593,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 04a20bbbbb88c..2bcd87f6158c5 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -178,8 +178,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) { @@ -350,13 +350,13 @@ namespace ts.textChanges { else if (isVariableDeclaration(before)) { // insert `x = 1, ` into `const x = 1, y = 2; return { suffix: ", " }; } - throw Debug.failBadSyntaxKind(before); // We haven't handled this kind of node yet -- add it + return Debug.failBadSyntaxKind(before); // We haven't handled this kind of node yet -- add it } 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); @@ -364,9 +364,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); @@ -374,13 +374,13 @@ namespace ts.textChanges { } private replaceConstructorBody(sourceFile: SourceFile, ctr: ConstructorDeclaration, statements: ReadonlyArray): void { - this.replaceNode(sourceFile, ctr.body, createBlock(statements, /*multiLine*/ true), { useNonAdjustedEndPosition: true }); + this.replaceNode(sourceFile, ctr.body!, createBlock(statements, /*multiLine*/ true), { useNonAdjustedEndPosition: 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 }); } @@ -434,7 +434,7 @@ namespace ts.textChanges { else if (isVariableDeclaration(node)) { return { prefix: ", " }; } - throw Debug.failBadSyntaxKind(node); // We haven't handled this kind of node yet -- add it + return Debug.failBadSyntaxKind(node); // We haven't handled this kind of node yet -- add it } /** @@ -478,7 +478,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: @@ -519,7 +519,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 @@ -701,7 +701,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); diff --git a/src/services/transform.ts b/src/services/transform.ts index 07fc3c759e22e..1c1106c56b7e3 100644 --- a/src/services/transform.ts +++ b/src/services/transform.ts @@ -9,7 +9,7 @@ namespace ts { */ export function transform(source: T | T[], transformers: TransformerFactory[], compilerOptions?: CompilerOptions) { const diagnostics: Diagnostic[] = []; - 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..93a768d74b8de 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 = { @@ -108,7 +108,7 @@ namespace ts { Debug.assert(outputText !== undefined, "Output generation failed"); - return { outputText, diagnostics, sourceMapText }; + return { outputText: outputText!, diagnostics, sourceMapText }; } /* diff --git a/src/services/types.ts b/src/services/types.ts index 60e33c200ad71..25a0845f38e45 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; } @@ -65,8 +65,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; @@ -127,7 +127,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; @@ -142,7 +142,7 @@ namespace ts { referencedFiles: FileReference[]; typeReferenceDirectives: FileReference[]; importedFiles: FileReference[]; - ambientExternalModules: string[]; + ambientExternalModules: string[] | undefined; isLibFile: boolean; } @@ -242,7 +242,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, @@ -250,31 +250,31 @@ namespace ts { name: string, options: FormatCodeOptions | FormatCodeSettings | undefined, source: string | 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[]; @@ -289,11 +289,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; getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: ReadonlyArray, formatOptions: FormatCodeSettings): ReadonlyArray; getCombinedCodeFix(scope: CombinedCodeFixScope, fixId: {}, formatOptions: FormatCodeSettings): CombinedCodeActions; @@ -676,14 +676,14 @@ namespace ts { kind: ScriptElementKind; kindModifiers: string; textSpan: TextSpan; - displayParts: SymbolDisplayPart[]; - documentation: SymbolDisplayPart[]; - tags: JSDocTagInfo[]; + displayParts: SymbolDisplayPart[] | undefined; + documentation: SymbolDisplayPart[] | undefined; + tags: JSDocTagInfo[] | undefined; } export interface RenameInfo { canRename: boolean; - localizedErrorMessage: string; + localizedErrorMessage: string | undefined; displayName: string; fullDisplayName: string; kind: ScriptElementKind; @@ -742,7 +742,7 @@ namespace ts { export interface CompletionEntry { name: string; kind: ScriptElementKind; - kindModifiers: string; // see ScriptElementKindModifier, comma separated + kindModifiers: string | undefined; // see ScriptElementKindModifier, comma separated sortText: string; insertText?: string; /** @@ -761,8 +761,8 @@ namespace ts { kind: ScriptElementKind; kindModifiers: string; // see ScriptElementKindModifier, comma separated displayParts: SymbolDisplayPart[]; - documentation: SymbolDisplayPart[]; - tags: JSDocTagInfo[]; + documentation: SymbolDisplayPart[] | undefined; + tags: JSDocTagInfo[] | undefined; codeActions?: CodeAction[]; source?: SymbolDisplayPart[]; } diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 6ece5e018b34c..23befbb7bab0a 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -195,16 +195,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; @@ -265,6 +265,8 @@ namespace ts { return true; case SyntaxKind.LiteralType: return node.parent.parent.kind === SyntaxKind.IndexedAccessType; + default: + return false; } } @@ -273,7 +275,7 @@ namespace ts { getExternalModuleImportEqualsDeclarationExpression(node.parent.parent) === node; } - export function getContainerNode(node: Node): Declaration { + export function getContainerNode(node: Node): Declaration | undefined { if (node.kind === SyntaxKind.JSDocTypedefTag) { // 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. @@ -438,8 +440,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; } @@ -495,7 +497,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) { @@ -579,18 +581,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 @@ -658,12 +660,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)) { @@ -708,7 +710,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); @@ -719,10 +721,10 @@ namespace ts { return findPrecedingToken(position, file); } - export function findNextToken(previousToken: Node, parent: Node): Node { + export function findNextToken(previousToken: Node, parent: Node): 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; @@ -947,7 +949,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; } @@ -1241,15 +1243,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) { @@ -1290,25 +1292,25 @@ namespace ts { export function typeToDisplayParts(typechecker: TypeChecker, type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): SymbolDisplayPart[] { return mapToDisplayParts(writer => { - typechecker.writeType(type, enclosingDeclaration, flags | TypeFormatFlags.MultilineObjectLiterals, writer); + typechecker.writeType(type, enclosingDeclaration, flags! | TypeFormatFlags.MultilineObjectLiterals, writer); }); } export function symbolToDisplayParts(typeChecker: TypeChecker, symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): SymbolDisplayPart[] { return mapToDisplayParts(writer => { - typeChecker.writeSymbol(symbol, enclosingDeclaration, meaning, flags | SymbolFormatFlags.UseAliasDefinedOutsideCurrentScope, writer); + typeChecker.writeSymbol(symbol, enclosingDeclaration, meaning, flags! | SymbolFormatFlags.UseAliasDefinedOutsideCurrentScope, writer); }); } export function signatureToDisplayParts(typechecker: TypeChecker, signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags): SymbolDisplayPart[] { - flags |= TypeFormatFlags.UseAliasDefinedOutsideCurrentScope | TypeFormatFlags.MultilineObjectLiterals | TypeFormatFlags.WriteTypeArgumentsOfSignature | TypeFormatFlags.OmitParameterModifiers; + flags! |= TypeFormatFlags.UseAliasDefinedOutsideCurrentScope | TypeFormatFlags.MultilineObjectLiterals | TypeFormatFlags.WriteTypeArgumentsOfSignature | TypeFormatFlags.OmitParameterModifiers; return mapToDisplayParts(writer => { typechecker.writeSignature(signature, enclosingDeclaration, flags, /*signatureKind*/ undefined, writer); }); } 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; } @@ -1332,7 +1334,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 { @@ -1358,6 +1360,8 @@ 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): T; + export function getSynthesizedDeepClone(node: T | undefined): T | undefined; export function getSynthesizedDeepClone(node: T | undefined): T | undefined { if (node === undefined) { return undefined; @@ -1382,13 +1386,15 @@ namespace ts { // 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): NodeArray; + export function getSynthesizedDeepClones(nodes: NodeArray | undefined): NodeArray | undefined; export function getSynthesizedDeepClones(nodes: NodeArray | undefined): NodeArray | undefined { - return nodes && createNodeArray(nodes.map(getSynthesizedDeepClone), nodes.hasTrailingComma); + return nodes && createNodeArray(nodes.map(getSynthesizedDeepClone), nodes.hasTrailingComma); } /** @@ -1413,7 +1419,7 @@ namespace ts { function suppressTrailing(node: Node) { addEmitFlags(node, EmitFlags.NoTrailingComments); - let lastChild: Node = undefined; + let lastChild: Node | undefined; forEachChild( node, child => (lastChild = child, undefined), 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 8739616ce14ec..cfdf1b2d547c2 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -452,7 +452,7 @@ declare namespace ts { flags: NodeFlags; decorators?: NodeArray; modifiers?: ModifiersArray; - parent?: Node; + parent: Node; } interface JSDocContainer { } @@ -517,12 +517,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; @@ -545,7 +545,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; @@ -553,12 +553,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; @@ -567,7 +567,7 @@ declare namespace ts { } interface BindingElement extends NamedDeclaration { kind: SyntaxKind.BindingElement; - parent?: BindingPattern; + parent: BindingPattern; propertyName?: PropertyName; dotDotDotToken?: DotDotDotToken; name: BindingName; @@ -598,7 +598,7 @@ declare namespace ts { kind: SyntaxKind.PropertyAssignment; name: PropertyName; questionToken?: QuestionToken; - initializer: Expression; + initializer: Expression | undefined; } interface ShorthandPropertyAssignment extends ObjectLiteralElement, JSDocContainer { parent: ObjectLiteralExpression; @@ -619,12 +619,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; @@ -652,41 +652,41 @@ declare namespace ts { } interface MethodSignature extends SignatureDeclarationBase, TypeElement { kind: SyntaxKind.MethodSignature; - parent?: ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode; + parent: ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode; 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?: ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode; + parent: ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode; } interface TypeNode extends Node { _typeNodeBrand: any; @@ -712,7 +712,7 @@ declare namespace ts { } interface TypePredicateNode extends TypeNode { kind: SyntaxKind.TypePredicate; - parent?: SignatureDeclaration; + parent: SignatureDeclaration; parameterName: Identifier | ThisTypeNode; type: TypeNode; } @@ -941,15 +941,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 { @@ -959,7 +959,7 @@ declare namespace ts { } interface TemplateSpan extends Node { kind: SyntaxKind.TemplateSpan; - parent?: TemplateExpression; + parent: TemplateExpression; expression: Expression; literal: TemplateMiddle | TemplateTail; } @@ -973,7 +973,7 @@ declare namespace ts { } interface SpreadElement extends Expression { kind: SyntaxKind.SpreadElement; - parent?: ArrayLiteralExpression | CallExpression | NewExpression; + parent: ArrayLiteralExpression | CallExpression | NewExpression; expression: Expression; } /** @@ -1026,7 +1026,7 @@ declare namespace ts { } interface ExpressionWithTypeArguments extends TypeNode { kind: SyntaxKind.ExpressionWithTypeArguments; - parent?: HeritageClause; + parent: HeritageClause; expression: LeftHandSideExpression; typeArguments?: NodeArray; } @@ -1072,11 +1072,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; attributes: JsxAttributes; } @@ -1093,38 +1093,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 { @@ -1225,18 +1225,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; @@ -1247,7 +1247,7 @@ declare namespace ts { } interface ThrowStatement extends Statement { kind: SyntaxKind.ThrowStatement; - expression: Expression; + expression: Expression | undefined; } interface TryStatement extends Statement { kind: SyntaxKind.TryStatement; @@ -1257,7 +1257,7 @@ declare namespace ts { } interface CatchClause extends Node { kind: SyntaxKind.CatchClause; - parent?: TryStatement; + parent: TryStatement; variableDeclaration?: VariableDeclaration; block: Block; } @@ -1296,7 +1296,7 @@ declare namespace ts { } interface HeritageClause extends Node { kind: SyntaxKind.HeritageClause; - parent?: InterfaceDeclaration | ClassLikeDeclaration; + parent: InterfaceDeclaration | ClassLikeDeclaration; token: SyntaxKind.ExtendsKeyword | SyntaxKind.ImplementsKeyword; types: NodeArray; } @@ -1308,7 +1308,7 @@ declare namespace ts { } interface EnumMember extends NamedDeclaration, JSDocContainer { kind: SyntaxKind.EnumMember; - parent?: EnumDeclaration; + parent: EnumDeclaration; name: PropertyName; initializer?: Expression; } @@ -1321,7 +1321,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; } @@ -1333,11 +1333,11 @@ declare namespace ts { type JSDocNamespaceBody = Identifier | JSDocNamespaceDeclaration; interface JSDocNamespaceDeclaration extends ModuleDeclaration { name: Identifier; - body: JSDocNamespaceBody; + body: JSDocNamespaceBody | undefined; } interface ModuleBlock extends Node, Statement { kind: SyntaxKind.ModuleBlock; - parent?: ModuleDeclaration; + parent: ModuleDeclaration; statements: NodeArray; } type ModuleReference = EntityName | ExternalModuleReference; @@ -1348,18 +1348,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; + 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; @@ -1367,13 +1367,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 { @@ -1382,7 +1382,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. */ @@ -1390,24 +1390,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; } @@ -1418,7 +1418,7 @@ declare namespace ts { */ interface ExportAssignment extends DeclarationStatement { kind: SyntaxKind.ExportAssignment; - parent?: SourceFile; + parent: SourceFile; isExportEquals?: boolean; expression: Expression; } @@ -1473,7 +1473,7 @@ declare namespace ts { type JSDocTypeReferencingNode = JSDocVariadicType | JSDocOptionalType | JSDocNullableType | JSDocNonNullableType; interface JSDoc extends Node { kind: SyntaxKind.JSDocComment; - parent?: HasJSDoc; + parent: HasJSDoc; tags: NodeArray | undefined; comment: string | undefined; } @@ -1505,11 +1505,11 @@ declare namespace ts { } interface JSDocReturnTag extends JSDocTag { kind: SyntaxKind.JSDocReturnTag; - typeExpression: JSDocTypeExpression; + typeExpression: JSDocTypeExpression | undefined; } interface JSDocTypeTag extends JSDocTag { kind: SyntaxKind.JSDocTypeTag; - typeExpression: JSDocTypeExpression; + typeExpression: JSDocTypeExpression | undefined; } interface JSDocTypedefTag extends JSDocTag, NamedDeclaration { parent: JSDoc; @@ -1574,7 +1574,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; @@ -1601,7 +1601,7 @@ declare namespace ts { } interface AmdDependency { path: string; - name: string; + name: string | undefined; } interface SourceFile extends Declaration { kind: SyntaxKind.SourceFile; @@ -1610,7 +1610,7 @@ declare namespace ts { fileName: string; text: string; amdDependencies: ReadonlyArray; - moduleName: string; + moduleName: string | undefined; referencedFiles: ReadonlyArray; typeReferenceDirectives: ReadonlyArray; languageVariant: LanguageVariant; @@ -1748,7 +1748,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; @@ -1780,7 +1780,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; @@ -1797,9 +1797,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: FunctionLike): boolean | undefined; isUndefinedSymbol(symbol: Symbol): boolean; @@ -2139,18 +2140,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 | undefined; + declaredNumberIndexInfo: IndexInfo | undefined; } /** * Type references (ObjectFlags.Reference). When a class or interface has type parameters or @@ -2229,10 +2230,10 @@ declare namespace ts { } interface InferenceInfo { typeParameter: TypeParameter; - candidates: Type[]; - contraCandidates: Type[]; - inferredType: Type; - priority: InferencePriority; + candidates: Type[] | undefined; + contraCandidates: Type[] | undefined; + inferredType: Type | undefined; + priority: InferencePriority | undefined; topLevel: boolean; isFixed: boolean; } @@ -2523,7 +2524,7 @@ declare namespace ts { packageId?: PackageId; } interface ResolvedTypeReferenceDirectiveWithFailedLookupLocations { - readonly resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective; + readonly resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective | undefined; readonly failedLookupLocations: ReadonlyArray; } interface CompilerHost extends ModuleResolutionHost { @@ -2542,7 +2543,7 @@ 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)[]; + resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[]; getEnvironmentVariable?(name: string): string; createHash?(data: string): string; } @@ -2607,7 +2608,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. */ @@ -2738,7 +2739,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, @@ -2941,7 +2942,7 @@ declare namespace ts { * Vn. */ function collapseTextChangeRangesAcrossMultipleVersions(changes: ReadonlyArray): TextChangeRange; - function getTypeParameterOwner(d: Declaration): Declaration; + function getTypeParameterOwner(d: Declaration): Declaration | undefined; function isParameterPropertyDeclaration(node: Node): boolean; function isEmptyBindingPattern(node: BindingName): node is BindingPattern; function isEmptyBindingElement(node: BindingElement): boolean; @@ -2959,6 +2960,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. * @@ -2979,7 +2982,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. * @@ -2997,6 +3000,9 @@ declare namespace ts { */ function unescapeIdentifier(id: string): string; function getNameOfJSDocTypedef(declaration: JSDocTypedefTag): Identifier | undefined; + function isNamedDeclaration(node: Node): node is NamedDeclaration & { + name: DeclarationName; + }; function getNameOfDeclaration(declaration: Declaration | Expression): DeclarationName | undefined; /** * Gets the JSDoc parameter tags for the node if present. @@ -3049,7 +3055,7 @@ declare namespace ts { */ function getJSDocReturnType(node: Node): TypeNode | undefined; /** Get all JSDoc tags related to a node, including those on parent nodes. */ - function getJSDocTags(node: Node): ReadonlyArray | undefined; + function getJSDocTags(node: Node): ReadonlyArray; /** Gets all JSDoc tags of a specified kind, or undefined if not present. */ function getAllJSDocTagsOfKind(node: Node, kind: SyntaxKind): ReadonlyArray | undefined; } @@ -3280,8 +3286,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; @@ -3307,9 +3313,9 @@ declare namespace ts { 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 createNode(kind: SyntaxKind, pos?: number, end?: number): Node; @@ -3328,7 +3334,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 @@ -3427,7 +3433,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; @@ -3500,7 +3506,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; @@ -3537,11 +3543,11 @@ 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 createElementAccess(expression: Expression, index: number | Expression | undefined): 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; @@ -3551,7 +3557,7 @@ declare namespace ts { 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; @@ -3581,15 +3587,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; @@ -3616,8 +3622,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; @@ -3641,8 +3647,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; @@ -3660,7 +3666,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; @@ -3669,7 +3675,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; @@ -3797,10 +3803,10 @@ 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; /** * Gets the constant value to emit for an expression. @@ -3841,7 +3847,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. * @@ -3850,7 +3856,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. * @@ -3860,7 +3866,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. * @@ -3880,7 +3886,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. @@ -3929,7 +3935,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; /** * Create a new 'Program' instance. A Program is an immutable collection of 'SourceFile's and a 'CompilerOptions' * that represent a compilation unit. @@ -3959,8 +3965,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 { @@ -4039,7 +4045,7 @@ declare namespace ts { referencedFiles: FileReference[]; typeReferenceDirectives: FileReference[]; importedFiles: FileReference[]; - ambientExternalModules: string[]; + ambientExternalModules: string[] | undefined; isLibFile: boolean; } interface HostCancellationToken { @@ -4095,24 +4101,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, options: FormatCodeOptions | FormatCodeSettings | undefined, source: string | 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, options: FormatCodeOptions | FormatCodeSettings | undefined, source: string | 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; @@ -4123,9 +4129,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; getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: ReadonlyArray, formatOptions: FormatCodeSettings): ReadonlyArray; getCombinedCodeFix(scope: CombinedCodeFixScope, fixId: {}, formatOptions: FormatCodeSettings): CombinedCodeActions; applyCodeActionCommand(action: CodeActionCommand): Promise; @@ -4448,13 +4454,13 @@ declare namespace ts { kind: ScriptElementKind; kindModifiers: string; textSpan: TextSpan; - displayParts: SymbolDisplayPart[]; - documentation: SymbolDisplayPart[]; - tags: JSDocTagInfo[]; + displayParts: SymbolDisplayPart[] | undefined; + documentation: SymbolDisplayPart[] | undefined; + tags: JSDocTagInfo[] | undefined; } interface RenameInfo { canRename: boolean; - localizedErrorMessage: string; + localizedErrorMessage: string | undefined; displayName: string; fullDisplayName: string; kind: ScriptElementKind; @@ -4506,7 +4512,7 @@ declare namespace ts { interface CompletionEntry { name: string; kind: ScriptElementKind; - kindModifiers: string; + kindModifiers: string | undefined; sortText: string; insertText?: string; /** @@ -4524,8 +4530,8 @@ declare namespace ts { kind: ScriptElementKind; kindModifiers: string; displayParts: SymbolDisplayPart[]; - documentation: SymbolDisplayPart[]; - tags: JSDocTagInfo[]; + documentation: SymbolDisplayPart[] | undefined; + tags: JSDocTagInfo[] | undefined; codeActions?: CodeAction[]; source?: SymbolDisplayPart[]; } @@ -4822,12 +4828,12 @@ declare namespace ts { /** The version of the language service API */ const servicesVersion = "0.7"; 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): LanguageService; /** * Get the path of the default library files (lib.d.ts) as distributed with the typescript @@ -4976,7 +4982,7 @@ declare namespace ts.server { startGroup(): void; endGroup(): void; msg(s: string, type?: Msg): void; - getLogFileName(): string; + getLogFileName(): string | undefined; } enum Msg { Err = "Err", @@ -5002,7 +5008,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; @@ -6340,7 +6346,7 @@ declare namespace ts.server.protocol { } interface CompletionEntryIdentifier { name: string; - source: string; + source: string | undefined; } /** * Completion entry details request; value of command field is @@ -6380,7 +6386,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. @@ -6437,11 +6443,11 @@ declare namespace ts.server.protocol { /** * Documentation strings for the symbol. */ - documentation: SymbolDisplayPart[]; + documentation: SymbolDisplayPart[] | undefined; /** * JSDoc tags for the symbol. */ - tags: JSDocTagInfo[]; + tags: JSDocTagInfo[] | undefined; /** * The associated code actions for this entry */ @@ -7389,7 +7395,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; @@ -7401,7 +7407,7 @@ declare namespace ts.server { constructor(installer: ITypingsInstaller); isKnownTypesPackageName(name: string): boolean; installPackage(options: InstallPackageOptionsWithProject): Promise; - getTypingsForProject(project: Project, unresolvedImports: SortedReadonlyArray, forceRefresh: boolean): SortedReadonlyArray; + getTypingsForProject(project: Project, unresolvedImports: SortedReadonlyArray | undefined, forceRefresh: boolean): SortedReadonlyArray; updateTypingsForProject(projectName: string, compilerOptions: CompilerOptions, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray, newTypings: string[]): void; deleteTypingsForProject(projectName: string): void; onProjectClosed(project: Project): void; @@ -7504,7 +7510,7 @@ declare namespace ts.server { isNonTsProject(): boolean; isJsOnlyProject(): boolean; getCachedUnresolvedImportsPerFile_TestOnly(): UnresolvedImportsMap; - static resolveModule(moduleName: string, initialDir: string, host: ServerHost, log: (message: string) => void): {}; + static resolveModule(moduleName: string, initialDir: string, host: ServerHost, log: (message: string) => void): {} | undefined; isKnownTypesPackageName(name: string): boolean; installPackage(options: InstallPackageOptions): Promise; private readonly typingsCache; @@ -7516,7 +7522,7 @@ declare namespace ts.server { private getOrCreateScriptInfoAndAttachToProject(fileName); getScriptKind(fileName: string): ScriptKind; getScriptVersion(filename: string): string; - getScriptSnapshot(filename: string): IScriptSnapshot; + getScriptSnapshot(filename: string): IScriptSnapshot | undefined; getCancellationToken(): HostCancellationToken; getCurrentDirectory(): string; getDefaultLibFileName(): string; @@ -7707,7 +7713,7 @@ declare namespace ts.server { readonly version: string; } interface ProjectInfoTypeAcquisitionData { - readonly enable: boolean; + readonly enable: boolean | undefined; readonly include: boolean; readonly exclude: boolean; } @@ -7837,7 +7843,7 @@ declare namespace ts.server { private delayUpdateProjectGraphs(projects); setCompilerOptionsForInferredProjects(projectCompilerOptions: protocol.ExternalProjectCompilerOptions, projectRootPath?: string): void; findProject(projectName: string): Project | undefined; - getDefaultProjectForFile(fileName: NormalizedPath, ensureProject: boolean): Project; + getDefaultProjectForFile(fileName: NormalizedPath, ensureProject: boolean): Project | undefined; getScriptInfoEnsuringProjectsUptoDate(uncheckedFileName: string): ScriptInfo; /** * Ensures the project structures are upto date diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 21ea143e8c57f..b1b2189754c36 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -452,7 +452,7 @@ declare namespace ts { flags: NodeFlags; decorators?: NodeArray; modifiers?: ModifiersArray; - parent?: Node; + parent: Node; } interface JSDocContainer { } @@ -517,12 +517,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; @@ -545,7 +545,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; @@ -553,12 +553,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; @@ -567,7 +567,7 @@ declare namespace ts { } interface BindingElement extends NamedDeclaration { kind: SyntaxKind.BindingElement; - parent?: BindingPattern; + parent: BindingPattern; propertyName?: PropertyName; dotDotDotToken?: DotDotDotToken; name: BindingName; @@ -598,7 +598,7 @@ declare namespace ts { kind: SyntaxKind.PropertyAssignment; name: PropertyName; questionToken?: QuestionToken; - initializer: Expression; + initializer: Expression | undefined; } interface ShorthandPropertyAssignment extends ObjectLiteralElement, JSDocContainer { parent: ObjectLiteralExpression; @@ -619,12 +619,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; @@ -652,41 +652,41 @@ declare namespace ts { } interface MethodSignature extends SignatureDeclarationBase, TypeElement { kind: SyntaxKind.MethodSignature; - parent?: ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode; + parent: ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode; 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?: ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode; + parent: ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode; } interface TypeNode extends Node { _typeNodeBrand: any; @@ -712,7 +712,7 @@ declare namespace ts { } interface TypePredicateNode extends TypeNode { kind: SyntaxKind.TypePredicate; - parent?: SignatureDeclaration; + parent: SignatureDeclaration; parameterName: Identifier | ThisTypeNode; type: TypeNode; } @@ -941,15 +941,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 { @@ -959,7 +959,7 @@ declare namespace ts { } interface TemplateSpan extends Node { kind: SyntaxKind.TemplateSpan; - parent?: TemplateExpression; + parent: TemplateExpression; expression: Expression; literal: TemplateMiddle | TemplateTail; } @@ -973,7 +973,7 @@ declare namespace ts { } interface SpreadElement extends Expression { kind: SyntaxKind.SpreadElement; - parent?: ArrayLiteralExpression | CallExpression | NewExpression; + parent: ArrayLiteralExpression | CallExpression | NewExpression; expression: Expression; } /** @@ -1026,7 +1026,7 @@ declare namespace ts { } interface ExpressionWithTypeArguments extends TypeNode { kind: SyntaxKind.ExpressionWithTypeArguments; - parent?: HeritageClause; + parent: HeritageClause; expression: LeftHandSideExpression; typeArguments?: NodeArray; } @@ -1072,11 +1072,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; attributes: JsxAttributes; } @@ -1093,38 +1093,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 { @@ -1225,18 +1225,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; @@ -1247,7 +1247,7 @@ declare namespace ts { } interface ThrowStatement extends Statement { kind: SyntaxKind.ThrowStatement; - expression: Expression; + expression: Expression | undefined; } interface TryStatement extends Statement { kind: SyntaxKind.TryStatement; @@ -1257,7 +1257,7 @@ declare namespace ts { } interface CatchClause extends Node { kind: SyntaxKind.CatchClause; - parent?: TryStatement; + parent: TryStatement; variableDeclaration?: VariableDeclaration; block: Block; } @@ -1296,7 +1296,7 @@ declare namespace ts { } interface HeritageClause extends Node { kind: SyntaxKind.HeritageClause; - parent?: InterfaceDeclaration | ClassLikeDeclaration; + parent: InterfaceDeclaration | ClassLikeDeclaration; token: SyntaxKind.ExtendsKeyword | SyntaxKind.ImplementsKeyword; types: NodeArray; } @@ -1308,7 +1308,7 @@ declare namespace ts { } interface EnumMember extends NamedDeclaration, JSDocContainer { kind: SyntaxKind.EnumMember; - parent?: EnumDeclaration; + parent: EnumDeclaration; name: PropertyName; initializer?: Expression; } @@ -1321,7 +1321,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; } @@ -1333,11 +1333,11 @@ declare namespace ts { type JSDocNamespaceBody = Identifier | JSDocNamespaceDeclaration; interface JSDocNamespaceDeclaration extends ModuleDeclaration { name: Identifier; - body: JSDocNamespaceBody; + body: JSDocNamespaceBody | undefined; } interface ModuleBlock extends Node, Statement { kind: SyntaxKind.ModuleBlock; - parent?: ModuleDeclaration; + parent: ModuleDeclaration; statements: NodeArray; } type ModuleReference = EntityName | ExternalModuleReference; @@ -1348,18 +1348,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; + 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; @@ -1367,13 +1367,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 { @@ -1382,7 +1382,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. */ @@ -1390,24 +1390,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; } @@ -1418,7 +1418,7 @@ declare namespace ts { */ interface ExportAssignment extends DeclarationStatement { kind: SyntaxKind.ExportAssignment; - parent?: SourceFile; + parent: SourceFile; isExportEquals?: boolean; expression: Expression; } @@ -1473,7 +1473,7 @@ declare namespace ts { type JSDocTypeReferencingNode = JSDocVariadicType | JSDocOptionalType | JSDocNullableType | JSDocNonNullableType; interface JSDoc extends Node { kind: SyntaxKind.JSDocComment; - parent?: HasJSDoc; + parent: HasJSDoc; tags: NodeArray | undefined; comment: string | undefined; } @@ -1505,11 +1505,11 @@ declare namespace ts { } interface JSDocReturnTag extends JSDocTag { kind: SyntaxKind.JSDocReturnTag; - typeExpression: JSDocTypeExpression; + typeExpression: JSDocTypeExpression | undefined; } interface JSDocTypeTag extends JSDocTag { kind: SyntaxKind.JSDocTypeTag; - typeExpression: JSDocTypeExpression; + typeExpression: JSDocTypeExpression | undefined; } interface JSDocTypedefTag extends JSDocTag, NamedDeclaration { parent: JSDoc; @@ -1574,7 +1574,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; @@ -1601,7 +1601,7 @@ declare namespace ts { } interface AmdDependency { path: string; - name: string; + name: string | undefined; } interface SourceFile extends Declaration { kind: SyntaxKind.SourceFile; @@ -1610,7 +1610,7 @@ declare namespace ts { fileName: string; text: string; amdDependencies: ReadonlyArray; - moduleName: string; + moduleName: string | undefined; referencedFiles: ReadonlyArray; typeReferenceDirectives: ReadonlyArray; languageVariant: LanguageVariant; @@ -1748,7 +1748,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; @@ -1780,7 +1780,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; @@ -1797,9 +1797,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: FunctionLike): boolean | undefined; isUndefinedSymbol(symbol: Symbol): boolean; @@ -2139,18 +2140,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 | undefined; + declaredNumberIndexInfo: IndexInfo | undefined; } /** * Type references (ObjectFlags.Reference). When a class or interface has type parameters or @@ -2229,10 +2230,10 @@ declare namespace ts { } interface InferenceInfo { typeParameter: TypeParameter; - candidates: Type[]; - contraCandidates: Type[]; - inferredType: Type; - priority: InferencePriority; + candidates: Type[] | undefined; + contraCandidates: Type[] | undefined; + inferredType: Type | undefined; + priority: InferencePriority | undefined; topLevel: boolean; isFixed: boolean; } @@ -2523,7 +2524,7 @@ declare namespace ts { packageId?: PackageId; } interface ResolvedTypeReferenceDirectiveWithFailedLookupLocations { - readonly resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective; + readonly resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective | undefined; readonly failedLookupLocations: ReadonlyArray; } interface CompilerHost extends ModuleResolutionHost { @@ -2542,7 +2543,7 @@ 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)[]; + resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[]; getEnvironmentVariable?(name: string): string; createHash?(data: string): string; } @@ -2607,7 +2608,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. */ @@ -2738,7 +2739,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, @@ -2910,7 +2911,7 @@ declare namespace ts { interface FileWatcher { close(): void; } - function getNodeMajorVersion(): number; + function getNodeMajorVersion(): number | undefined; let sys: System; } declare namespace ts { @@ -2937,8 +2938,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; @@ -2958,15 +2959,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; @@ -2975,12 +2976,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; @@ -2996,7 +2997,7 @@ declare namespace ts { * Vn. */ function collapseTextChangeRangesAcrossMultipleVersions(changes: ReadonlyArray): TextChangeRange; - function getTypeParameterOwner(d: Declaration): Declaration; + function getTypeParameterOwner(d: Declaration): Declaration | undefined; function isParameterPropertyDeclaration(node: Node): boolean; function isEmptyBindingPattern(node: BindingName): node is BindingPattern; function isEmptyBindingElement(node: BindingElement): boolean; @@ -3014,6 +3015,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. * @@ -3034,7 +3037,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. * @@ -3052,6 +3055,9 @@ declare namespace ts { */ function unescapeIdentifier(id: string): string; function getNameOfJSDocTypedef(declaration: JSDocTypedefTag): Identifier | undefined; + function isNamedDeclaration(node: Node): node is NamedDeclaration & { + name: DeclarationName; + }; function getNameOfDeclaration(declaration: Declaration | Expression): DeclarationName | undefined; /** * Gets the JSDoc parameter tags for the node if present. @@ -3104,7 +3110,7 @@ declare namespace ts { */ function getJSDocReturnType(node: Node): TypeNode | undefined; /** Get all JSDoc tags related to a node, including those on parent nodes. */ - function getJSDocTags(node: Node): ReadonlyArray | undefined; + function getJSDocTags(node: Node): ReadonlyArray; /** Gets all JSDoc tags of a specified kind, or undefined if not present. */ function getAllJSDocTagsOfKind(node: Node, kind: SyntaxKind): ReadonlyArray | undefined; } @@ -3328,7 +3334,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 @@ -3374,7 +3380,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; @@ -3447,7 +3453,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; @@ -3484,11 +3490,11 @@ 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 createElementAccess(expression: Expression, index: number | Expression | undefined): 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; @@ -3498,7 +3504,7 @@ declare namespace ts { 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; @@ -3528,15 +3534,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; @@ -3563,8 +3569,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; @@ -3588,8 +3594,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; @@ -3607,7 +3613,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; @@ -3616,7 +3622,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; @@ -3744,15 +3750,15 @@ 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; /** * 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. */ @@ -3788,7 +3794,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. * @@ -3797,7 +3803,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. * @@ -3807,7 +3813,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. * @@ -3827,7 +3833,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. @@ -3876,7 +3882,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; /** * Create a new 'Program' instance. A Program is an immutable collection of 'SourceFile's and a 'CompilerOptions' * that represent a compilation unit. @@ -4068,7 +4074,7 @@ declare namespace ts { /** 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 */ @@ -4211,8 +4217,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 { @@ -4291,7 +4297,7 @@ declare namespace ts { referencedFiles: FileReference[]; typeReferenceDirectives: FileReference[]; importedFiles: FileReference[]; - ambientExternalModules: string[]; + ambientExternalModules: string[] | undefined; isLibFile: boolean; } interface HostCancellationToken { @@ -4347,24 +4353,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, options: FormatCodeOptions | FormatCodeSettings | undefined, source: string | 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, options: FormatCodeOptions | FormatCodeSettings | undefined, source: string | 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; @@ -4375,9 +4381,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; getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: ReadonlyArray, formatOptions: FormatCodeSettings): ReadonlyArray; getCombinedCodeFix(scope: CombinedCodeFixScope, fixId: {}, formatOptions: FormatCodeSettings): CombinedCodeActions; applyCodeActionCommand(action: CodeActionCommand): Promise; @@ -4700,13 +4706,13 @@ declare namespace ts { kind: ScriptElementKind; kindModifiers: string; textSpan: TextSpan; - displayParts: SymbolDisplayPart[]; - documentation: SymbolDisplayPart[]; - tags: JSDocTagInfo[]; + displayParts: SymbolDisplayPart[] | undefined; + documentation: SymbolDisplayPart[] | undefined; + tags: JSDocTagInfo[] | undefined; } interface RenameInfo { canRename: boolean; - localizedErrorMessage: string; + localizedErrorMessage: string | undefined; displayName: string; fullDisplayName: string; kind: ScriptElementKind; @@ -4758,7 +4764,7 @@ declare namespace ts { interface CompletionEntry { name: string; kind: ScriptElementKind; - kindModifiers: string; + kindModifiers: string | undefined; sortText: string; insertText?: string; /** @@ -4776,8 +4782,8 @@ declare namespace ts { kind: ScriptElementKind; kindModifiers: string; displayParts: SymbolDisplayPart[]; - documentation: SymbolDisplayPart[]; - tags: JSDocTagInfo[]; + documentation: SymbolDisplayPart[] | undefined; + tags: JSDocTagInfo[] | undefined; codeActions?: CodeAction[]; source?: SymbolDisplayPart[]; } @@ -5074,12 +5080,12 @@ declare namespace ts { /** The version of the language service API */ const servicesVersion = "0.7"; 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): 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 bd06724edb8fc..25858083725e3 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": { From 28991e18c9533490f2e9d0e82bd4d78af5c254c7 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Thu, 1 Mar 2018 14:40:59 -0800 Subject: [PATCH 02/42] Fix API baselines --- Jakefile.js | 2 +- scripts/buildProtocol.ts | 10 +++---- scripts/processDiagnosticMessages.ts | 2 +- scripts/tslint/rules/noInOperatorRule.ts | 2 +- src/compiler/factory.ts | 2 +- src/compiler/sys.ts | 2 +- src/compiler/tsc.ts | 14 ++++----- src/compiler/utilities.ts | 4 +-- src/server/server.ts | 10 +++---- .../reference/api/tsserverlibrary.d.ts | 30 +++++++++---------- 10 files changed, 39 insertions(+), 39 deletions(-) diff --git a/Jakefile.js b/Jakefile.js index e10517de00c44..9bdf59b82f424 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -386,7 +386,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 899ab700bf372..f439a769341ca 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; @@ -178,7 +178,7 @@ function writeProtocolFile(outputFile: string, protocolTs: string, typeScriptSer ts.sys.writeFile(outputFile, protocolDts); if (diagnostics.length) { - const flattenedDiagnostics = diagnostics.map(d => `${ts.flattenDiagnosticMessageText(d.messageText, "\n")} at ${d.file.fileName} line ${d.start}`).join("\n"); + const flattenedDiagnostics = diagnostics.map(d => `${ts.flattenDiagnosticMessageText(d.messageText, "\n")} at ${d.file!.fileName} line ${d.start!}`).join("\n"); throw new Error(`Unexpected errors during sanity check: ${flattenedDiagnostics}`); } } diff --git a/scripts/processDiagnosticMessages.ts b/scripts/processDiagnosticMessages.ts index dd66564b13458..634e1ecd5ef42 100644 --- a/scripts/processDiagnosticMessages.ts +++ b/scripts/processDiagnosticMessages.ts @@ -24,7 +24,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/src/compiler/factory.ts b/src/compiler/factory.ts index 5e0eeddc974e2..b3a86409e0f8f 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -2792,7 +2792,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; } diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index a3331c726934f..0a9badac148f1 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -82,7 +82,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; } diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 15e4867d7f7a1..4770bb9ea6eb6 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -47,7 +47,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); } @@ -71,7 +71,7 @@ namespace ts { if (commandLine.options.help || commandLine.options.all) { printVersion(); - printHelp(commandLine.options.all); + printHelp(!!commandLine.options.all); return sys.exit(ExitStatus.Success); } @@ -104,13 +104,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 udpateReportDiagnostic(configParseResult.options); if (isWatchSet(configParseResult.options)) { reportWatchModeWithoutSysSupport(); @@ -155,7 +155,7 @@ namespace ts { enableStatistics(options); return compileUsingBuilder(rootNames, options, host, oldProgram); }; - const emitFilesUsingBuilder = watchCompilerHost.afterProgramCreate; + const emitFilesUsingBuilder = watchCompilerHost.afterProgramCreate!; // TODO: GH#18217 watchCompilerHost.afterProgramCreate = builderProgram => { emitFilesUsingBuilder(builderProgram); reportStatistics(builderProgram.getProgram()); @@ -167,7 +167,7 @@ namespace ts { } function createWatchOfConfigFile(configParseResult: ParsedCommandLine, optionsToExtend: CompilerOptions) { - const watchCompilerHost = ts.createWatchCompilerHostOfConfigFile(configParseResult.options.configFilePath, optionsToExtend, sys, /*createProgram*/ undefined, reportDiagnostic, createWatchStatusReporter(configParseResult.options)); + const watchCompilerHost = ts.createWatchCompilerHostOfConfigFile(configParseResult.options.configFilePath!, optionsToExtend, sys, /*createProgram*/ undefined, reportDiagnostic, createWatchStatusReporter(configParseResult.options)); // TODO: GH#18217 updateWatchCompilationHost(watchCompilerHost); watchCompilerHost.rootFiles = configParseResult.fileNames; watchCompilerHost.options = configParseResult.options; @@ -292,7 +292,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/utilities.ts b/src/compiler/utilities.ts index 66a6813d3b634..1f7e04e3df7bf 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -3777,7 +3777,7 @@ namespace ts { return overlapStart < overlapEnd; } - export function textSpanOverlap(span1: TextSpan, span2: TextSpan) { + export function textSpanOverlap(span1: TextSpan, span2: TextSpan): TextSpan | undefined { const overlapStart = Math.max(span1.start, span2.start); const overlapEnd = Math.min(textSpanEnd(span1), textSpanEnd(span2)); if (overlapStart < overlapEnd) { @@ -3805,7 +3805,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 intersectStart = Math.max(span1.start, span2.start); const intersectEnd = Math.min(textSpanEnd(span1), textSpanEnd(span2)); if (intersectStart <= intersectEnd) { diff --git a/src/server/server.ts b/src/server/server.ts index 70bd85a1d3db5..1ca6c67d6909d 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -310,7 +310,7 @@ namespace ts.server { args.push(Arguments.EnableTelemetry); } if (this.logger.loggingEnabled() && this.logger.getLogFileName()) { - args.push(Arguments.LogFile, combinePaths(getDirectoryPath(normalizeSlashes(this.logger.getLogFileName())), `ti-${process.pid}.log`)); + args.push(Arguments.LogFile, combinePaths(getDirectoryPath(normalizeSlashes(this.logger.getLogFileName()!)), `ti-${process.pid}.log`)); } if (this.typingSafeListLocation) { args.push(Arguments.TypingSafeListLocation, this.typingSafeListLocation); @@ -466,7 +466,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); @@ -499,7 +499,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; @@ -557,7 +557,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) { @@ -578,7 +578,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() { diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index c2730f1648d47..c83f784684f05 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -2896,7 +2896,7 @@ declare namespace ts { interface FileWatcher { close(): void; } - function getNodeMajorVersion(): number; + function getNodeMajorVersion(): number | undefined; let sys: System; } declare namespace ts { @@ -2906,12 +2906,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; @@ -3293,8 +3293,8 @@ 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 */ @@ -3797,7 +3797,7 @@ declare namespace ts { /** * 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. */ @@ -7440,7 +7440,7 @@ declare namespace ts.server { clear(): void; getVersion(): number; remove(path: Path): void; - get(path: Path): ReadonlyArray; + get(path: Path): ReadonlyArray | undefined; set(path: Path, value: ReadonlyArray): void; } interface PluginCreateInfo { @@ -7557,7 +7557,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(uncheckedFilename); isClosed(): boolean; @@ -7586,8 +7586,8 @@ declare namespace ts.server { private detachScriptInfoFromProject(uncheckedFileName); private addMissingFileWatcher(missingFilePath); private isWatchedMissingFile(path); - getScriptInfoForNormalizedPath(fileName: NormalizedPath): ScriptInfo; - getScriptInfo(uncheckedFileName: string): ScriptInfo; + getScriptInfoForNormalizedPath(fileName: NormalizedPath): ScriptInfo | undefined; + getScriptInfo(uncheckedFileName: string): ScriptInfo | undefined; filesToString(writeProjectFileNames: boolean): string; setCompilerOptions(compilerOptions: CompilerOptions): void; protected removeRoot(info: ScriptInfo): void; @@ -7846,7 +7846,7 @@ declare namespace ts.server { setCompilerOptionsForInferredProjects(projectCompilerOptions: protocol.ExternalProjectCompilerOptions, projectRootPath?: string): void; findProject(projectName: string): Project | undefined; getDefaultProjectForFile(fileName: NormalizedPath, ensureProject: boolean): Project | undefined; - getScriptInfoEnsuringProjectsUptoDate(uncheckedFileName: string): ScriptInfo; + getScriptInfoEnsuringProjectsUptoDate(uncheckedFileName: string): ScriptInfo | undefined; /** * Ensures the project structures are upto date * This means, @@ -7930,18 +7930,18 @@ declare namespace ts.server { private getOrCreateInferredProjectForProjectRootPathIfEnabled(info, projectRootPath); private getOrCreateSingleInferredProjectIfEnabled(); private createInferredProject(currentDirectory, isSingleInferredProject?, projectRootPath?); - getScriptInfo(uncheckedFileName: string): ScriptInfo; + getScriptInfo(uncheckedFileName: string): ScriptInfo | undefined; private watchClosedScriptInfo(info); private stopWatchingScriptInfo(info); getOrCreateScriptInfoForNormalizedPath(fileName: NormalizedPath, openedByClient: boolean, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, hostToQueryFileExistsOn?: { fileExists(path: string): boolean; - }): ScriptInfo; + }): ScriptInfo | undefined; private getOrCreateScriptInfoWorker(fileName, currentDirectory, openedByClient, fileContent?, scriptKind?, hasMixedContent?, hostToQueryFileExistsOn?); /** * 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; /** From 6f77c3476d016a9cb9794cf6a4de968ecb94009b Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 24 Apr 2018 10:56:19 -0700 Subject: [PATCH 03/42] Make sys.getEnvironmentVariable non-nullable --- src/compiler/sys.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index a65d497f38f66..63d7aa21d76df 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -456,7 +456,7 @@ namespace ts { getMemoryUsage?(): number; exit(exitCode?: number): void; realpath?(path: string): string; - /*@internal*/ getEnvironmentVariable(name: string): string | undefined; + /*@internal*/ getEnvironmentVariable(name: string): string; /*@internal*/ tryEnableSourceMapsForHost?(): void; /*@internal*/ debugMode?: boolean; setTimeout?(callback: (...args: any[]) => void, ms: number, ...args: any[]): any; @@ -1155,7 +1155,7 @@ namespace ts { if (sys && sys.getEnvironmentVariable) { setCustomPollingValues(sys); - Debug.currentAssertionLevel = /^development$/i.test(sys.getEnvironmentVariable("NODE_ENV")!) + Debug.currentAssertionLevel = /^development$/i.test(sys.getEnvironmentVariable("NODE_ENV")) ? AssertionLevel.Normal : AssertionLevel.None; } From 6152c9b54104cb8b3d3122eb1fabd4dc22173f15 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 24 Apr 2018 11:02:03 -0700 Subject: [PATCH 04/42] make properties optional instead of using `| undefined` in thier type --- src/compiler/types.ts | 64 +++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 4c68610eaefd2..9953d202081ec 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -803,7 +803,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 } @@ -905,7 +905,7 @@ namespace ts { kind: SyntaxKind.PropertyAssignment; name: PropertyName; questionToken?: QuestionToken; - initializer: Expression | undefined; + initializer?: Expression; } export interface ShorthandPropertyAssignment extends ObjectLiteralElement, JSDocContainer { @@ -2025,7 +2025,7 @@ namespace ts { export interface ThrowStatement extends Statement { kind: SyntaxKind.ThrowStatement; - expression: Expression | undefined; + expression?: Expression; } export interface TryStatement extends Statement { @@ -2139,7 +2139,7 @@ namespace ts { export interface JSDocNamespaceDeclaration extends ModuleDeclaration { name: Identifier; - body: JSDocNamespaceBody | undefined; + body?: JSDocNamespaceBody; } export interface ModuleBlock extends Node, Statement { @@ -2327,15 +2327,15 @@ namespace ts { export interface JSDoc extends Node { kind: SyntaxKind.JSDocComment; parent: HasJSDoc; - tags: NodeArray | undefined; - comment: string | undefined; + 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 { @@ -2362,12 +2362,12 @@ namespace ts { export interface JSDocReturnTag extends JSDocTag { kind: SyntaxKind.JSDocReturnTag; - typeExpression: JSDocTypeExpression | undefined; + typeExpression?: JSDocTypeExpression; } export interface JSDocTypeTag extends JSDocTag { kind: SyntaxKind.JSDocTypeTag; - typeExpression: JSDocTypeExpression | undefined; + typeExpression?: JSDocTypeExpression; } export interface JSDocTypedefTag extends JSDocTag, NamedDeclaration { @@ -2492,7 +2492,7 @@ namespace ts { export interface AmdDependency { path: string; - name: string | undefined; + name?: string; } /* @internal */ @@ -2531,10 +2531,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 | undefined; + moduleName?: string; referencedFiles: ReadonlyArray; typeReferenceDirectives: ReadonlyArray; languageVariant: LanguageVariant; @@ -2558,9 +2558,9 @@ namespace ts { /* @internal */ scriptKind: ScriptKind; // The first node that causes this file to be an external module - /* @internal */ externalModuleIndicator: Node | undefined; + /* @internal */ externalModuleIndicator?: Node; // The first node that causes this file to be a CommonJS module - /* @internal */ commonJsModuleIndicator: Node | undefined; + /* @internal */ commonJsModuleIndicator?: Node; /* @internal */ identifiers: Map; // Map from a string to an interned string /* @internal */ nodeCount: number; @@ -2587,14 +2587,14 @@ 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 | undefined; + /* @internal */ resolvedModules?: Map; /* @internal */ resolvedTypeReferenceDirectiveNames: Map; /* @internal */ imports: ReadonlyArray; // Identifier only if `declare global` /* @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; @@ -3709,7 +3709,7 @@ namespace ts { 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) + thisType: TypeParameter | undefined; // The "this" type (undefined if none) /* @internal */ resolvedBaseConstructorType?: Type; // Resolved base constructor type of class /* @internal */ @@ -3723,8 +3723,8 @@ namespace ts { declaredProperties: Symbol[]; // Declared members declaredCallSignatures: Signature[]; // Declared call signatures declaredConstructSignatures: Signature[]; // Declared construct signatures - declaredStringIndexInfo: IndexInfo | undefined; // Declared string indexing info - declaredNumberIndexInfo: IndexInfo | undefined; // Declared numeric indexing info + declaredStringIndexInfo?: IndexInfo; // Declared string indexing info + declaredNumberIndexInfo?: IndexInfo; // Declared numeric indexing info } /** @@ -3901,11 +3901,11 @@ namespace ts { trueType: Type; falseType: Type; isDistributive: boolean; - inferTypeParameters: TypeParameter[] | undefined; + inferTypeParameters?: TypeParameter[]; outerTypeParameters?: TypeParameter[]; instantiations?: Map; - aliasSymbol: Symbol | undefined; - aliasTypeArguments: Type[] | undefined; + aliasSymbol?: Symbol; + aliasTypeArguments?: Type[]; } // T extends U ? X : Y (TypeFlags.Conditional) @@ -3947,12 +3947,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 */ @@ -4006,8 +4006,8 @@ namespace ts { 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 | undefined; // Cache for resolved inferred type - priority: InferencePriority | undefined; // Priority of current inference set + 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 } @@ -4042,7 +4042,7 @@ namespace ts { /* @internal */ export interface InferenceContext extends TypeMapper { typeParameters: TypeParameter[]; // Type parameters for which inferences are made - signature: Signature | undefined; // 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 @@ -4319,17 +4319,17 @@ namespace ts { /* @internal */ export interface ConfigFileSpecs { - filesSpecs: ReadonlyArray | undefined; + filesSpecs?: ReadonlyArray; /** * Present to report errors (user specified specs), validatedIncludeSpecs are used for file name matching */ - includeSpecs: ReadonlyArray | undefined; + includeSpecs?: ReadonlyArray; /** * Present to report errors (user specified specs), validatedExcludeSpecs are used for file name matching */ - excludeSpecs: ReadonlyArray | undefined; - validatedIncludeSpecs: ReadonlyArray | undefined; - validatedExcludeSpecs: ReadonlyArray | undefined; + excludeSpecs?: ReadonlyArray; + validatedIncludeSpecs?: ReadonlyArray; + validatedExcludeSpecs?: ReadonlyArray; wildcardDirectories: MapLike; } From 8cda69c64b533ef83f6ff492665c274fa8c2a48e Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 24 Apr 2018 11:20:34 -0700 Subject: [PATCH 05/42] reportDiagnostics should be required --- src/compiler/watch.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/compiler/watch.ts b/src/compiler/watch.ts index 411b07c5dcb11..2d3fff6a6cc50 100644 --- a/src/compiler/watch.ts +++ b/src/compiler/watch.ts @@ -208,7 +208,7 @@ 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 as CreateProgram; } @@ -261,7 +261,7 @@ namespace ts { } }; - emitFilesAndReportErrors(builderProgram, reportDiagnostic!, writeFileName, reportSummary); // TODO: GH#18217 + emitFilesAndReportErrors(builderProgram, reportDiagnostic, writeFileName, reportSummary); } } @@ -277,9 +277,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; @@ -487,7 +487,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[] | 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 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 From b0bcef5369a15d527e1f2087ce61cd1e07391c91 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 24 Apr 2018 12:09:24 -0700 Subject: [PATCH 06/42] Declare firstAccessor as non-nullable --- src/compiler/checker.ts | 2 +- src/compiler/transformers/declarations.ts | 2 +- src/compiler/transformers/es2015.ts | 8 ++++---- src/compiler/transformers/ts.ts | 2 +- src/compiler/utilities.ts | 5 ++--- 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a145fed87d381..7f03fdcb73e80 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -26627,7 +26627,7 @@ namespace ts { } else if (node.kind === SyntaxKind.GetAccessor || node.kind === SyntaxKind.SetAccessor) { const accessors = getAllAccessorDeclarations((node.parent).members, node); - if (accessors.firstAccessor!.decorators && node === accessors.secondAccessor) { + if (accessors.firstAccessor.decorators && node === accessors.secondAccessor) { return grammarErrorOnFirstToken(node, Diagnostics.Decorators_cannot_be_applied_to_multiple_get_Slashset_accessors_of_the_same_name); } } diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 5d4e2c405cfac..826ac7be46d44 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -1173,7 +1173,7 @@ namespace ts { function ensureAccessor(node: AccessorDeclaration): PropertyDeclaration | undefined { const accessors = getAllAccessorDeclarations((node.parent as ClassDeclaration).members, node); - if (node.kind !== accessors.firstAccessor!.kind) { + if (node.kind !== accessors.firstAccessor.kind) { return; } let accessorType = getTypeAnnotationFromAccessor(node); diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index 8d766b3118c09..a783f2eaf8c62 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -1624,7 +1624,7 @@ namespace ts { // No comments should be emitted for this statement to align with the // old emitter. setEmitFlags(statement, EmitFlags.NoComments); - setSourceMapRange(statement, getSourceMapRange(accessors.firstAccessor!)); // TODO: GH#18217 + setSourceMapRange(statement, getSourceMapRange(accessors.firstAccessor)); return statement; } @@ -1641,11 +1641,11 @@ 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); // TODO: GH#18217 + setSourceMapRange(target, firstAccessor.name); // TODO: GH#18217 - const propertyName = createExpressionForPropertyName(visitNode(firstAccessor!.name, visitor, isPropertyName)); + const propertyName = createExpressionForPropertyName(visitNode(firstAccessor.name, visitor, isPropertyName)); setEmitFlags(propertyName, EmitFlags.NoComments | EmitFlags.NoLeadingSourceMap); - setSourceMapRange(propertyName, firstAccessor!.name); + setSourceMapRange(propertyName, firstAccessor.name); const properties: ObjectLiteralElementLike[] = []; if (getAccessor) { diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 1e1d795507b2a..bbb95b29b2b8f 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -1386,7 +1386,7 @@ namespace ts { } const { firstAccessor, secondAccessor, setAccessor } = getAllAccessorDeclarations(node.members, accessor); - const firstAccessorWithDecorators = firstAccessor!.decorators ? firstAccessor : secondAccessor && secondAccessor.decorators ? secondAccessor : undefined; + const firstAccessorWithDecorators = firstAccessor.decorators ? firstAccessor : secondAccessor && secondAccessor.decorators ? secondAccessor : undefined; if (!firstAccessorWithDecorators || accessor !== firstAccessorWithDecorators) { return undefined; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 4c9980155440b..71b0585170619 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2986,16 +2986,15 @@ namespace ts { return id.originalKeywordKind === SyntaxKind.ThisKeyword; } - // TODO: GH#18217 These are frequently asserted to be defined export interface AllAccessorDeclarations { - firstAccessor: AccessorDeclaration | undefined; + firstAccessor: AccessorDeclaration; secondAccessor: AccessorDeclaration | undefined; getAccessor: AccessorDeclaration | undefined; setAccessor: AccessorDeclaration | undefined; } export function getAllAccessorDeclarations(declarations: NodeArray, accessor: AccessorDeclaration): AllAccessorDeclarations { - let firstAccessor: AccessorDeclaration | undefined; + let firstAccessor!: AccessorDeclaration; let secondAccessor: AccessorDeclaration | undefined; let getAccessor: AccessorDeclaration | undefined; let setAccessor: AccessorDeclaration | undefined; From 4d63f375baeb6f1895f8d341f393b429c513d21e Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 24 Apr 2018 12:45:48 -0700 Subject: [PATCH 07/42] Make `some` a type guard --- src/compiler/checker.ts | 2 +- src/compiler/core.ts | 3 ++- src/compiler/factory.ts | 12 ++++++------ src/compiler/transformers/destructuring.ts | 4 ++-- src/compiler/transformers/ts.ts | 4 ++-- src/compiler/visitor.ts | 2 +- 6 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7f03fdcb73e80..57a143caa1aa0 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3439,7 +3439,7 @@ namespace ts { function mapToTypeNodes(types: Type[] | undefined, context: NodeBuilderContext): TypeNode[] | undefined { if (some(types)) { const result = []; - for (const type of types!) { + for (const type of types) { const typeNode = typeToTypeNodeHelper(type, context); if (typeNode) { result.push(typeNode); diff --git a/src/compiler/core.ts b/src/compiler/core.ts index bc3180a80a628..c729eb3114bda 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -695,7 +695,8 @@ namespace ts { }); return result; } - + 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) { diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index fc333fd633d5f..842735f912397 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -2909,7 +2909,7 @@ namespace ts { export function addEmitHelpers(node: T, helpers: EmitHelper[] | undefined): T { if (some(helpers)) { const emitNode = getOrCreateEmitNode(node); - for (const helper of helpers!) { + for (const helper of helpers) { emitNode.helpers = appendIfUnique(emitNode.helpers, helper); } } @@ -2948,14 +2948,14 @@ namespace ts { const targetEmitNode = getOrCreateEmitNode(target); let helpersRemoved = 0; - for (let i = 0; i < sourceEmitHelpers!.length; i++) { - const helper = sourceEmitHelpers![i]; + for (let i = 0; i < sourceEmitHelpers.length; i++) { + const helper = sourceEmitHelpers[i]; if (predicate(helper)) { helpersRemoved++; targetEmitNode.helpers = appendIfUnique(targetEmitNode.helpers, helper); } else if (helpersRemoved > 0) { - sourceEmitHelpers![i - helpersRemoved] = helper; + sourceEmitHelpers[i - helpersRemoved] = helper; } } @@ -4244,8 +4244,8 @@ namespace ts { export function parenthesizeTypeParameters(typeParameters: ReadonlyArray | undefined) { if (some(typeParameters)) { const params: TypeNode[] = []; - for (let i = 0; i < typeParameters!.length; ++i) { - const entry = typeParameters![i]; + for (let i = 0; i < typeParameters.length; ++i) { + const entry = typeParameters[i]; params.push(i === 0 && isFunctionOrConstructorTypeNode(entry) && entry.typeParameters ? createParenthesizedType(entry) : entry); diff --git a/src/compiler/transformers/destructuring.ts b/src/compiler/transformers/destructuring.ts index d8e174a8b1a4a..e85a6a4912aa3 100644 --- a/src/compiler/transformers/destructuring.ts +++ b/src/compiler/transformers/destructuring.ts @@ -100,10 +100,10 @@ namespace ts { return value; } - expressions!.push(value); + expressions.push(value); } - return aggregateTransformFlags(inlineExpressions(expressions!)) || createOmittedExpression(); // TODO: GH#18217 + return aggregateTransformFlags(inlineExpressions(expressions!)) || createOmittedExpression(); function emitExpression(expression: Expression) { // NOTE: this completely disables source maps, but aligns with the behavior of diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index bbb95b29b2b8f..c4c468e463842 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -2133,8 +2133,8 @@ namespace ts { 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 if (some(pendingExpressions)) { - expr = inlineExpressions([...pendingExpressions!, expr]); - pendingExpressions!.length = 0; + expr = inlineExpressions([...pendingExpressions, expr]); + pendingExpressions.length = 0; } return updateComputedPropertyName(name as ComputedPropertyName, expr); } diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index 4526f8a98db2d..7d7cb7e3748ef 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -180,7 +180,7 @@ namespace ts { const declarations = context.endLexicalEnvironment(); if (some(declarations)) { const block = convertToFunctionBody(updated); - const statements = mergeLexicalEnvironment(block.statements, declarations!); + const statements = mergeLexicalEnvironment(block.statements, declarations); return updateBlock(block, statements); } return updated; From e4d8b76e293b581e9c9c4366cd2b550dd9ea39c7 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 24 Apr 2018 12:46:10 -0700 Subject: [PATCH 08/42] Fix `getEnvironmentVariable` definition in tests --- src/harness/harnessLanguageService.ts | 2 +- src/harness/virtualFileSystemWithWatch.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index f6d7fa2ddd7b6..58bba103915b8 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -684,7 +684,7 @@ namespace Harness.LanguageService { return []; } - getEnvironmentVariable(name: string): string | undefined { + getEnvironmentVariable(name: string): string { return ts.sys.getEnvironmentVariable(name); } diff --git a/src/harness/virtualFileSystemWithWatch.ts b/src/harness/virtualFileSystemWithWatch.ts index 5d4df4a499c08..928cb945d7402 100644 --- a/src/harness/virtualFileSystemWithWatch.ts +++ b/src/harness/virtualFileSystemWithWatch.ts @@ -892,7 +892,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) || ""; } } } From 34a06119701aeb430874f39d4c84922f2d78b9db Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 24 Apr 2018 13:06:44 -0700 Subject: [PATCH 09/42] Pretend transformFlags are always defined --- src/compiler/binder.ts | 14 ++++----- src/compiler/transformers/destructuring.ts | 6 ++-- src/compiler/transformers/es2015.ts | 34 +++++++++++----------- src/compiler/transformers/es2016.ts | 2 +- src/compiler/transformers/es2017.ts | 2 +- src/compiler/transformers/esnext.ts | 14 ++++----- src/compiler/transformers/generators.ts | 10 +++---- src/compiler/transformers/jsx.ts | 4 +-- src/compiler/transformers/module/module.ts | 6 ++-- src/compiler/transformers/module/system.ts | 6 ++-- src/compiler/transformers/ts.ts | 12 ++++---- src/compiler/types.ts | 6 ++-- src/compiler/visitor.ts | 6 ++-- src/services/services.ts | 1 + 14 files changed, 62 insertions(+), 61 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 8bfa8ba9b5b04..1851a2c76f38d 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -578,11 +578,11 @@ namespace ts { if (skipTransformFlagAggregation) { bindChildrenWorker(node); } - else if (node.transformFlags! & TransformFlags.HasComputedFlags) { + else if (node.transformFlags & TransformFlags.HasComputedFlags) { skipTransformFlagAggregation = true; bindChildrenWorker(node); skipTransformFlagAggregation = false; - subtreeTransformFlags |= node.transformFlags! & ~getTransformFlagsSubtreeExclusions(node.kind); + subtreeTransformFlags |= node.transformFlags & ~getTransformFlagsSubtreeExclusions(node.kind); } else { const savedSubtreeTransformFlags = subtreeTransformFlags; @@ -611,7 +611,7 @@ namespace ts { let nodeArrayFlags = TransformFlags.None; for (const node of nodes) { bindFunction(node); - nodeArrayFlags |= node.transformFlags! & ~TransformFlags.HasComputedFlags; + nodeArrayFlags |= node.transformFlags & ~TransformFlags.HasComputedFlags; } nodes.transformFlags = nodeArrayFlags | TransformFlags.HasComputedFlags; subtreeTransformFlags |= savedSubtreeTransformFlags; @@ -1954,7 +1954,7 @@ namespace ts { } parent = saveParent; } - else if (!skipTransformFlagAggregation && (node.transformFlags! & TransformFlags.HasComputedFlags) === 0) { + else if (!skipTransformFlagAggregation && (node.transformFlags & TransformFlags.HasComputedFlags) === 0) { subtreeTransformFlags |= computeTransformFlagsForNode(node, 0); } inStrictMode = saveInStrictMode; @@ -2864,13 +2864,13 @@ namespace ts { } if (subtreeFlags & TransformFlags.ContainsSpread - || (expression.transformFlags! & (TransformFlags.Super | TransformFlags.ContainsSuper))) { + || (expression.transformFlags & (TransformFlags.Super | TransformFlags.ContainsSuper))) { // If the this node contains a SpreadExpression, or is a super call, then it is an ES6 // node. transformFlags |= TransformFlags.AssertES2015; // super property or element accesses could be inside lambdas, etc, and need a captured `this`, // while super keyword for super calls (indicated by TransformFlags.Super) does not (since it can only be top-level in a constructor) - if (expression.transformFlags! & TransformFlags.ContainsSuper) { + if (expression.transformFlags & TransformFlags.ContainsSuper) { transformFlags |= TransformFlags.ContainsLexicalThis; } } @@ -3399,7 +3399,7 @@ namespace ts { // If the expression of an expression statement is a destructuring assignment, // then we treat the statement as ES6 so that we can indicate that we do not // need to hold on to the right-hand side. - if (node.expression.transformFlags! & TransformFlags.DestructuringAssignment) { + if (node.expression.transformFlags & TransformFlags.DestructuringAssignment) { transformFlags |= TransformFlags.AssertES2015; } diff --git a/src/compiler/transformers/destructuring.ts b/src/compiler/transformers/destructuring.ts index e85a6a4912aa3..8b072db88bcf5 100644 --- a/src/compiler/transformers/destructuring.ts +++ b/src/compiler/transformers/destructuring.ts @@ -307,8 +307,8 @@ namespace ts { if (!getRestIndicatorOfBindingOrAssignmentElement(element)) { const propertyName = getPropertyNameOfBindingOrAssignmentElement(element)!; if (flattenContext.level >= FlattenLevel.ObjectRest - && !(element.transformFlags! & (TransformFlags.ContainsRest | TransformFlags.ContainsObjectRest)) - && !(getTargetOfBindingOrAssignmentElement(element)!.transformFlags! & (TransformFlags.ContainsRest | TransformFlags.ContainsObjectRest)) + && !(element.transformFlags & (TransformFlags.ContainsRest | TransformFlags.ContainsObjectRest)) + && !(getTargetOfBindingOrAssignmentElement(element)!.transformFlags & (TransformFlags.ContainsRest | TransformFlags.ContainsObjectRest)) && !isComputedPropertyName(propertyName)) { bindingElements = append(bindingElements, element); } @@ -384,7 +384,7 @@ namespace ts { if (flattenContext.level >= FlattenLevel.ObjectRest) { // If an array pattern contains an ObjectRest, we must cache the result so that we // can perform the ObjectRest destructuring in a different declaration - if (element.transformFlags! & TransformFlags.ContainsObjectRest) { + if (element.transformFlags & TransformFlags.ContainsObjectRest) { const temp = createTempVariable(/*recordTempVariable*/ undefined); if (flattenContext.hoistTempVariables) { flattenContext.context.hoistVariableDeclaration(temp); diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index a783f2eaf8c62..fbad8a7e7883b 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -344,7 +344,7 @@ namespace ts { } function shouldVisitNode(node: Node): boolean { - return (node.transformFlags! & TransformFlags.ContainsES2015) !== 0 + return (node.transformFlags & TransformFlags.ContainsES2015) !== 0 || convertedLoopState !== undefined || (hierarchyFacts & HierarchyFacts.ConstructorWithCapturedSuper && (isStatement(node) || (node.kind === SyntaxKind.Block))) || (isIterationStatement(node, /*lookInLabeledStatements*/ false) && shouldConvertIterationStatementBody(node)) @@ -1102,7 +1102,7 @@ namespace ts { // but only if the constructor itself doesn't use 'this' elsewhere. if (superCallExpression && statementOffset === ctorStatements.length - 1 - && !(ctor.transformFlags! & (TransformFlags.ContainsLexicalThis | TransformFlags.ContainsCapturedLexicalThis))) { + && !(ctor.transformFlags & (TransformFlags.ContainsLexicalThis | TransformFlags.ContainsCapturedLexicalThis))) { const returnStatement = createReturn(superCallExpression); if (superCallExpression.kind !== SyntaxKind.BinaryExpression @@ -1211,7 +1211,7 @@ namespace ts { * @param node A function-like node. */ function shouldAddDefaultValueAssignments(node: FunctionLikeDeclaration): boolean { - return (node.transformFlags! & TransformFlags.ContainsDefaultValueAssignments) !== 0; + return (node.transformFlags & TransformFlags.ContainsDefaultValueAssignments) !== 0; } /** @@ -1438,7 +1438,7 @@ namespace ts { * @param node A node. */ function addCaptureThisForNodeIfNeeded(statements: Statement[], node: Node): void { - if (node.transformFlags! & TransformFlags.ContainsCapturedLexicalThis && node.kind !== SyntaxKind.ArrowFunction) { + if (node.transformFlags & TransformFlags.ContainsCapturedLexicalThis && node.kind !== SyntaxKind.ArrowFunction) { captureThisForNode(statements, node, createThis()); } } @@ -1694,7 +1694,7 @@ namespace ts { * @param node An ArrowFunction node. */ function visitArrowFunction(node: ArrowFunction) { - if (node.transformFlags! & TransformFlags.ContainsLexicalThis) { + if (node.transformFlags & TransformFlags.ContainsLexicalThis) { enableSubstitutionsForCapturedThis(); } const savedConvertedLoopState = convertedLoopState; @@ -1730,7 +1730,7 @@ namespace ts { convertedLoopState = undefined; const parameters = visitParameterList(node.parameters, visitor, context); - const body = node.transformFlags! & TransformFlags.ES2015 + const body = node.transformFlags & TransformFlags.ES2015 ? transformFunctionBody(node) : visitFunctionBodyDownLevel(node); const name = hierarchyFacts & HierarchyFacts.NewTarget @@ -1761,7 +1761,7 @@ namespace ts { convertedLoopState = undefined; const ancestorFacts = enterSubtree(HierarchyFacts.FunctionExcludes, HierarchyFacts.FunctionIncludes); const parameters = visitParameterList(node.parameters, visitor, context); - const body = node.transformFlags! & TransformFlags.ES2015 + const body = node.transformFlags & TransformFlags.ES2015 ? transformFunctionBody(node) : visitFunctionBodyDownLevel(node); const name = hierarchyFacts & HierarchyFacts.NewTarget @@ -2051,7 +2051,7 @@ namespace ts { * @param node A VariableDeclarationList node. */ function visitVariableDeclarationList(node: VariableDeclarationList): VariableDeclarationList { - if (node.transformFlags! & TransformFlags.ES2015) { + if (node.transformFlags & TransformFlags.ES2015) { if (node.flags & NodeFlags.BlockScoped) { enableSubstitutionsForBlockScopedBindings(); } @@ -2065,7 +2065,7 @@ namespace ts { setTextRange(declarationList, node); setCommentRange(declarationList, node); - if (node.transformFlags! & TransformFlags.ContainsBindingPattern + if (node.transformFlags & TransformFlags.ContainsBindingPattern && (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. @@ -2559,7 +2559,7 @@ namespace ts { let numInitialPropertiesWithoutYield = numProperties; for (let i = 0; i < numProperties; i++) { const property = properties[i]; - if ((property.transformFlags! & TransformFlags.ContainsYield && hierarchyFacts & HierarchyFacts.AsyncFunctionBody) + if ((property.transformFlags & TransformFlags.ContainsYield && hierarchyFacts & HierarchyFacts.AsyncFunctionBody) && i < numInitialPropertiesWithoutYield) { numInitialPropertiesWithoutYield = i; } @@ -2722,7 +2722,7 @@ namespace ts { loopBody = createBlock([loopBody], /*multiline*/ true); } - const containsYield = (node.statement.transformFlags! & TransformFlags.ContainsYield) !== 0; + const containsYield = (node.statement.transformFlags & TransformFlags.ContainsYield) !== 0; const isAsyncBlockContainingAwait = containsYield && (hierarchyFacts & HierarchyFacts.AsyncFunctionBody) !== 0; let loopBodyFlags: EmitFlags = 0; @@ -3191,7 +3191,7 @@ namespace ts { const ancestorFacts = enterSubtree(HierarchyFacts.FunctionExcludes, HierarchyFacts.FunctionIncludes); let updated: AccessorDeclaration; const parameters = visitParameterList(node.parameters, visitor, context); - const body = node.transformFlags! & (TransformFlags.ContainsCapturedLexicalThis | TransformFlags.ContainsES2015) + const body = node.transformFlags & (TransformFlags.ContainsCapturedLexicalThis | TransformFlags.ContainsES2015) ? transformFunctionBody(node) : visitFunctionBodyDownLevel(node); if (node.kind === SyntaxKind.GetAccessor) { @@ -3243,7 +3243,7 @@ namespace ts { * @param node An ArrayLiteralExpression node. */ function visitArrayLiteralExpression(node: ArrayLiteralExpression): Expression { - if (node.transformFlags! & TransformFlags.ES2015) { + 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); } @@ -3260,7 +3260,7 @@ namespace ts { return visitTypeScriptClassWrapper(node); } - if (node.transformFlags! & TransformFlags.ES2015) { + if (node.transformFlags & TransformFlags.ES2015) { return visitCallExpressionWithPotentialCapturedThisAssignment(node, /*assignToCapturedThis*/ true); } @@ -3427,7 +3427,7 @@ namespace ts { function visitCallExpressionWithPotentialCapturedThisAssignment(node: CallExpression, assignToCapturedThis: boolean): CallExpression | BinaryExpression { // We are here either because SuperKeyword was used somewhere in the expression, or // because we contain a SpreadElementExpression. - if (node.transformFlags! & TransformFlags.ContainsSpread || + if (node.transformFlags & TransformFlags.ContainsSpread || node.expression.kind === SyntaxKind.SuperKeyword || isSuperProperty(skipOuterExpressions(node.expression))) { @@ -3437,7 +3437,7 @@ namespace ts { } let resultingCall: CallExpression | BinaryExpression; - if (node.transformFlags! & TransformFlags.ContainsSpread) { + if (node.transformFlags & TransformFlags.ContainsSpread) { // [source] // f(...a, b) // x.m(...a, b) @@ -3500,7 +3500,7 @@ namespace ts { * @param node A NewExpression node. */ function visitNewExpression(node: NewExpression): LeftHandSideExpression { - if (node.transformFlags! & TransformFlags.ContainsSpread) { + if (node.transformFlags & TransformFlags.ContainsSpread) { // We are here because we contain a SpreadElementExpression. // [source] // new C(...a) diff --git a/src/compiler/transformers/es2016.ts b/src/compiler/transformers/es2016.ts index 2e14605043121..e4c56f98fa700 100644 --- a/src/compiler/transformers/es2016.ts +++ b/src/compiler/transformers/es2016.ts @@ -14,7 +14,7 @@ namespace ts { } function visitor(node: Node): VisitResult { - if ((node.transformFlags! & TransformFlags.ContainsES2016) === 0) { + if ((node.transformFlags & TransformFlags.ContainsES2016) === 0) { return node; } switch (node.kind) { diff --git a/src/compiler/transformers/es2017.ts b/src/compiler/transformers/es2017.ts index 16b897ee17208..f611dc4a33f26 100644 --- a/src/compiler/transformers/es2017.ts +++ b/src/compiler/transformers/es2017.ts @@ -53,7 +53,7 @@ namespace ts { } function visitor(node: Node): VisitResult { - if ((node.transformFlags! & TransformFlags.ContainsES2017) === 0) { + if ((node.transformFlags & TransformFlags.ContainsES2017) === 0) { return node; } diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index f8572f36aa5d0..542274b9407bc 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -54,7 +54,7 @@ namespace ts { } function visitorWorker(node: Node, noDestructuringValue: boolean): VisitResult { - if ((node.transformFlags! & TransformFlags.ContainsESNext) === 0) { + if ((node.transformFlags & TransformFlags.ContainsESNext) === 0) { return node; } @@ -180,7 +180,7 @@ namespace ts { } function visitObjectLiteralExpression(node: ObjectLiteralExpression): Expression { - if (node.transformFlags! & TransformFlags.ContainsObjectSpread) { + if (node.transformFlags & TransformFlags.ContainsObjectSpread) { // spread elements emit like so: // non-spread elements are chunked together into object literals, and then all are passed to __assign: // { a, ...o, b } => __assign({a}, o, {b}); @@ -220,7 +220,7 @@ namespace ts { * @param node A BinaryExpression node. */ function visitBinaryExpression(node: BinaryExpression, noDestructuringValue: boolean): Expression { - if (isDestructuringAssignment(node) && node.left.transformFlags! & TransformFlags.ContainsObjectRest) { + if (isDestructuringAssignment(node) && node.left.transformFlags & TransformFlags.ContainsObjectRest) { return flattenDestructuringAssignment( node, visitor, @@ -246,7 +246,7 @@ namespace ts { */ function visitVariableDeclaration(node: VariableDeclaration): VisitResult { // If we are here it is because the name contains a binding pattern with a rest somewhere in it. - if (isBindingPattern(node.name) && node.name.transformFlags! & TransformFlags.ContainsObjectRest) { + if (isBindingPattern(node.name) && node.name.transformFlags & TransformFlags.ContainsObjectRest) { return flattenDestructuringBinding( node, visitor, @@ -277,7 +277,7 @@ namespace ts { * @param node A ForOfStatement. */ function visitForOfStatement(node: ForOfStatement, outermostLabeledStatement: LabeledStatement | undefined): VisitResult { - if (node.initializer.transformFlags! & TransformFlags.ContainsObjectRest) { + if (node.initializer.transformFlags & TransformFlags.ContainsObjectRest) { node = transformForOfStatementWithObjectRest(node); } if (node.awaitModifier) { @@ -469,7 +469,7 @@ namespace ts { } function visitParameter(node: ParameterDeclaration): ParameterDeclaration { - if (node.transformFlags! & TransformFlags.ContainsObjectRest) { + if (node.transformFlags & TransformFlags.ContainsObjectRest) { // Binding patterns are converted into a generated name and are // evaluated inside the function body. return updateParameter( @@ -686,7 +686,7 @@ namespace ts { function appendObjectRestAssignmentsIfNeeded(statements: Statement[] | undefined, node: FunctionLikeDeclaration): Statement[] | undefined { for (const parameter of node.parameters) { - if (parameter.transformFlags! & TransformFlags.ContainsObjectRest) { + if (parameter.transformFlags & TransformFlags.ContainsObjectRest) { const temp = getGeneratedNameForNode(parameter); const declarations = flattenDestructuringBinding( parameter, diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts index fd53beae1b7ec..ee5564c1ca6d6 100644 --- a/src/compiler/transformers/generators.ts +++ b/src/compiler/transformers/generators.ts @@ -293,7 +293,7 @@ namespace ts { return transformSourceFile; function transformSourceFile(node: SourceFile) { - if (node.isDeclarationFile || (node.transformFlags! & TransformFlags.ContainsGenerator) === 0) { + if (node.isDeclarationFile || (node.transformFlags & TransformFlags.ContainsGenerator) === 0) { return node; } @@ -374,10 +374,10 @@ namespace ts { case SyntaxKind.ReturnStatement: return visitReturnStatement(node); default: - if (node.transformFlags! & TransformFlags.ContainsYield) { + if (node.transformFlags & TransformFlags.ContainsYield) { return visitJavaScriptContainingYield(node); } - else if (node.transformFlags! & (TransformFlags.ContainsGenerator | TransformFlags.ContainsHoistedDeclarationOrCompletion)) { + else if (node.transformFlags & (TransformFlags.ContainsGenerator | TransformFlags.ContainsHoistedDeclarationOrCompletion)) { return visitEachChild(node, visitor, context); } else { @@ -617,7 +617,7 @@ namespace ts { * @param node The node to visit. */ function visitVariableStatement(node: VariableStatement): Statement | undefined { - if (node.transformFlags! & TransformFlags.ContainsYield) { + if (node.transformFlags & TransformFlags.ContainsYield) { transformAndEmitVariableDeclarationList(node.declarationList); return undefined; } @@ -1925,7 +1925,7 @@ namespace ts { } function containsYield(node: Node | undefined): boolean { - return !!node && (node.transformFlags! & TransformFlags.ContainsYield) !== 0; + return !!node && (node.transformFlags & TransformFlags.ContainsYield) !== 0; } function countInitialNodesWithoutYield(nodes: NodeArray) { diff --git a/src/compiler/transformers/jsx.ts b/src/compiler/transformers/jsx.ts index 0715029be22d0..ed2da56034d92 100644 --- a/src/compiler/transformers/jsx.ts +++ b/src/compiler/transformers/jsx.ts @@ -23,7 +23,7 @@ namespace ts { } function visitor(node: Node): VisitResult { - if (node.transformFlags! & TransformFlags.ContainsJsx) { + if (node.transformFlags & TransformFlags.ContainsJsx) { return visitorWorker(node); } else { @@ -563,4 +563,4 @@ namespace ts { hearts: 0x2665, diams: 0x2666 }); -} \ No newline at end of file +} diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts index 512740d5ec244..1cf8bea6c7809 100644 --- a/src/compiler/transformers/module/module.ts +++ b/src/compiler/transformers/module/module.ts @@ -53,7 +53,7 @@ namespace ts { * @param node The SourceFile node. */ function transformSourceFile(node: SourceFile) { - if (node.isDeclarationFile || !(isEffectiveExternalModule(node, compilerOptions) || node.transformFlags! & TransformFlags.ContainsDynamicImport)) { + if (node.isDeclarationFile || !(isEffectiveExternalModule(node, compilerOptions) || node.transformFlags & TransformFlags.ContainsDynamicImport)) { return node; } @@ -524,7 +524,7 @@ namespace ts { function importCallExpressionVisitor(node: Expression): VisitResult { // This visitor does not need to descend into the tree if there is no dynamic import, // as export/import statements are only transformed at the top level of a file. - if (!(node.transformFlags! & TransformFlags.ContainsDynamicImport)) { + if (!(node.transformFlags & TransformFlags.ContainsDynamicImport)) { return node; } @@ -538,7 +538,7 @@ namespace ts { function visitImportCallExpression(node: ImportCall): Expression { const argument = visitNode(firstOrUndefined(node.arguments), importCallExpressionVisitor); - const containsLexicalThis = !!(node.transformFlags! & TransformFlags.ContainsLexicalThis); + const containsLexicalThis = !!(node.transformFlags & TransformFlags.ContainsLexicalThis); switch (compilerOptions.module) { case ModuleKind.AMD: return createImportCallExpressionAMD(argument, containsLexicalThis); diff --git a/src/compiler/transformers/module/system.ts b/src/compiler/transformers/module/system.ts index 0b3da0476943c..e88e028049eab 100644 --- a/src/compiler/transformers/module/system.ts +++ b/src/compiler/transformers/module/system.ts @@ -47,7 +47,7 @@ namespace ts { * @param node The SourceFile node. */ function transformSourceFile(node: SourceFile) { - if (node.isDeclarationFile || !(isEffectiveExternalModule(node, compilerOptions) || node.transformFlags! & TransformFlags.ContainsDynamicImport)) { + if (node.isDeclarationFile || !(isEffectiveExternalModule(node, compilerOptions) || node.transformFlags & TransformFlags.ContainsDynamicImport)) { return node; } @@ -1463,14 +1463,14 @@ namespace ts { * @param node The node to visit. */ function destructuringAndImportCallVisitor(node: Node): VisitResult { - if (node.transformFlags! & TransformFlags.DestructuringAssignment + if (node.transformFlags & TransformFlags.DestructuringAssignment && node.kind === SyntaxKind.BinaryExpression) { return visitDestructuringAssignment(node); } else if (isImportCall(node)) { return visitImportCallExpression(node); } - else if ((node.transformFlags! & TransformFlags.ContainsDestructuringAssignment) || (node.transformFlags! & TransformFlags.ContainsDynamicImport)) { + else if ((node.transformFlags & TransformFlags.ContainsDestructuringAssignment) || (node.transformFlags & TransformFlags.ContainsDynamicImport)) { return visitEachChild(node, destructuringAndImportCallVisitor, context); } else { diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index c4c468e463842..6c52b1096fa2c 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -184,11 +184,11 @@ namespace ts { * @param node The node to visit. */ function visitorWorker(node: Node): VisitResult { - if (node.transformFlags! & TransformFlags.TypeScript) { + if (node.transformFlags & TransformFlags.TypeScript) { // This node is explicitly marked as TypeScript, so we should transform the node. return visitTypeScript(node); } - else if (node.transformFlags! & TransformFlags.ContainsTypeScript) { + else if (node.transformFlags & TransformFlags.ContainsTypeScript) { // This node contains TypeScript, so we should visit its children. return visitEachChild(node, visitor, context); } @@ -229,7 +229,7 @@ namespace ts { // As the type information we would attempt to lookup to perform ellision is potentially unavailable for the synthesized nodes // We do not reuse `visitorWorker`, as the ellidable statement syntax kinds are technically unrecognized by the switch-case in `visitTypeScript`, // and will trigger debug failures when debug verbosity is turned up - if (node.transformFlags! & TransformFlags.ContainsTypeScript) { + if (node.transformFlags & TransformFlags.ContainsTypeScript) { // This node contains TypeScript, so we should visit its children. return visitEachChild(node, visitor, context); } @@ -273,12 +273,12 @@ namespace ts { // do not emit ES6 imports and exports since they are illegal inside a namespace return undefined; } - else if (node.transformFlags! & TransformFlags.TypeScript || hasModifier(node, ModifierFlags.Export)) { + else if (node.transformFlags & TransformFlags.TypeScript || hasModifier(node, ModifierFlags.Export)) { // This node is explicitly marked as TypeScript, or is exported at the namespace // level, so we should transform the node. return visitTypeScript(node); } - else if (node.transformFlags! & TransformFlags.ContainsTypeScript) { + else if (node.transformFlags & TransformFlags.ContainsTypeScript) { // This node contains TypeScript, so we should visit its children. return visitEachChild(node, visitor, context); } @@ -945,7 +945,7 @@ namespace ts { // If there is a property assignment, we need to emit constructor whether users define it or not // If there is no property assignment, we can omit constructor if users do not define it const hasInstancePropertyWithInitializer = forEach(node.members, isInstanceInitializedProperty); - const hasParameterPropertyAssignments = node.transformFlags! & TransformFlags.ContainsParameterPropertyAssignments; + const hasParameterPropertyAssignments = node.transformFlags & TransformFlags.ContainsParameterPropertyAssignments; const constructor = getFirstConstructorWithBody(node); // If the class does not contain nodes that require a synthesized constructor, diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 9953d202081ec..bfbe38c6eb0a7 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -562,11 +562,11 @@ 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 */ locals?: SymbolTable; // Locals associated with node (initialized by binding) @@ -655,7 +655,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 { diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index 7d7cb7e3748ef..56c477e299375 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -1501,8 +1501,8 @@ namespace ts { if (node === undefined) { return TransformFlags.None; } - if (node.transformFlags! & TransformFlags.HasComputedFlags) { - return node.transformFlags! & ~getTransformFlagsSubtreeExclusions(node.kind); + if (node.transformFlags & TransformFlags.HasComputedFlags) { + return node.transformFlags & ~getTransformFlagsSubtreeExclusions(node.kind); } const subtreeFlags = aggregateTransformFlagsForSubtree(node); return computeTransformFlagsForNode(node, subtreeFlags); @@ -1516,7 +1516,7 @@ namespace ts { let nodeArrayFlags = TransformFlags.None; for (const node of nodes) { subtreeFlags |= aggregateTransformFlagsForNode(node); - nodeArrayFlags |= node.transformFlags! & ~TransformFlags.HasComputedFlags; + nodeArrayFlags |= node.transformFlags & ~TransformFlags.HasComputedFlags; } nodes.transformFlags = nodeArrayFlags | TransformFlags.HasComputedFlags; return subtreeFlags; diff --git a/src/services/services.ts b/src/services/services.ts index d4ab17e0b6ffc..95393c17a2d5b 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -201,6 +201,7 @@ namespace ts { public flags: NodeFlags; public parent: Node; public jsDocComments: JSDoc[]; + public transformFlags: TransformFlags; constructor(pos: number, end: number) { // Set properties in same order as NodeObject From 0900823aed40cf01a9517e1ba2d54ac83a75d39d Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 24 Apr 2018 13:59:09 -0700 Subject: [PATCH 10/42] Fix one more use of sys.getEnvironmentVariable --- src/compiler/tsc.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 5cba045288b21..fdab39c9c8197 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -396,7 +396,7 @@ if (ts.Debug.isDebugging) { ts.Debug.enableDebugInfo(); } -if (ts.sys.tryEnableSourceMapsForHost && /^development$/i.test(ts.sys.getEnvironmentVariable("NODE_ENV")!)) { +if (ts.sys.tryEnableSourceMapsForHost && /^development$/i.test(ts.sys.getEnvironmentVariable("NODE_ENV"))) { ts.sys.tryEnableSourceMapsForHost(); } From c10ace5f626eb6da4d43c85d2110235c7b0f9f3d Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 24 Apr 2018 13:59:30 -0700 Subject: [PATCH 11/42] `requiredResponse` accepts undefined, remove assertions --- src/server/session.ts | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/server/session.ts b/src/server/session.ts index 6ea8a5929db46..c4f41afd53284 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -1904,16 +1904,16 @@ namespace ts.server { return this.requiredResponse(this.getImplementation(request.arguments, /*simplifiedResult*/ false)); }, [CommandNames.References]: (request: protocol.FileLocationRequest) => { - return this.requiredResponse(this.getReferences(request.arguments, /*simplifiedResult*/ true)!); // TODO: GH#18217 + return this.requiredResponse(this.getReferences(request.arguments, /*simplifiedResult*/ true)); }, [CommandNames.ReferencesFull]: (request: protocol.FileLocationRequest) => { - return this.requiredResponse(this.getReferences(request.arguments, /*simplifiedResult*/ false)!); // TODO: GH#18217 + return this.requiredResponse(this.getReferences(request.arguments, /*simplifiedResult*/ false)); }, [CommandNames.Rename]: (request: protocol.Request) => { - return this.requiredResponse(this.getRenameLocations(request.arguments, /*simplifiedResult*/ true)!); // TODO: GH#18217 + return this.requiredResponse(this.getRenameLocations(request.arguments, /*simplifiedResult*/ true)); }, [CommandNames.RenameLocationsFull]: (request: protocol.RenameRequest) => { - return this.requiredResponse(this.getRenameLocations(request.arguments, /*simplifiedResult*/ false)!); // TODO: GH#18217 + return this.requiredResponse(this.getRenameLocations(request.arguments, /*simplifiedResult*/ false)); }, [CommandNames.RenameInfoFull]: (request: protocol.FileLocationRequest) => { return this.requiredResponse(this.getRenameInfo(request.arguments)); @@ -1927,10 +1927,10 @@ namespace ts.server { return this.notRequired(); }, [CommandNames.Quickinfo]: (request: protocol.QuickInfoRequest) => { - return this.requiredResponse(this.getQuickInfoWorker(request.arguments, /*simplifiedResult*/ true)!); // TODO: GH#18217 + return this.requiredResponse(this.getQuickInfoWorker(request.arguments, /*simplifiedResult*/ true)); }, [CommandNames.QuickinfoFull]: (request: protocol.QuickInfoRequest) => { - return this.requiredResponse(this.getQuickInfoWorker(request.arguments, /*simplifiedResult*/ false)!); // TODO: GH#18217 + return this.requiredResponse(this.getQuickInfoWorker(request.arguments, /*simplifiedResult*/ false)); }, [CommandNames.GetOutliningSpans]: (request: protocol.FileRequest) => { return this.requiredResponse(this.getOutliningSpans(request.arguments, /*simplifiedResult*/ true)); @@ -1960,10 +1960,10 @@ namespace ts.server { return this.requiredResponse(this.getSpanOfEnclosingComment(request.arguments)); }, [CommandNames.Format]: (request: protocol.FormatRequest) => { - return this.requiredResponse(this.getFormattingEditsForRange(request.arguments)!); // TODO: GH#18217 + return this.requiredResponse(this.getFormattingEditsForRange(request.arguments)); }, [CommandNames.Formatonkey]: (request: protocol.FormatOnKeyRequest) => { - return this.requiredResponse(this.getFormattingEditsAfterKeystroke(request.arguments)!); // TODO: GH#18217 + return this.requiredResponse(this.getFormattingEditsAfterKeystroke(request.arguments)); }, [CommandNames.FormatFull]: (request: protocol.FormatRequest) => { return this.requiredResponse(this.getFormattingEditsForDocumentFull(request.arguments)); @@ -1975,10 +1975,10 @@ namespace ts.server { return this.requiredResponse(this.getFormattingEditsForRangeFull(request.arguments)); }, [CommandNames.Completions]: (request: protocol.CompletionsRequest) => { - return this.requiredResponse(this.getCompletions(request.arguments, /*simplifiedResult*/ true)!); // TODO: GH#18217 + return this.requiredResponse(this.getCompletions(request.arguments, /*simplifiedResult*/ true)); }, [CommandNames.CompletionsFull]: (request: protocol.CompletionsRequest) => { - return this.requiredResponse(this.getCompletions(request.arguments, /*simplifiedResult*/ false)!); // TODO: GH#18217 + return this.requiredResponse(this.getCompletions(request.arguments, /*simplifiedResult*/ false)); }, [CommandNames.CompletionDetails]: (request: protocol.CompletionDetailsRequest) => { return this.requiredResponse(this.getCompletionEntryDetails(request.arguments, /*simplifiedResult*/ true)); @@ -1993,10 +1993,10 @@ namespace ts.server { return this.requiredResponse(this.emitFile(request.arguments)); }, [CommandNames.SignatureHelp]: (request: protocol.SignatureHelpRequest) => { - return this.requiredResponse(this.getSignatureHelpItems(request.arguments, /*simplifiedResult*/ true)!); // TODO: GH#18217 + return this.requiredResponse(this.getSignatureHelpItems(request.arguments, /*simplifiedResult*/ true)); }, [CommandNames.SignatureHelpFull]: (request: protocol.SignatureHelpRequest) => { - return this.requiredResponse(this.getSignatureHelpItems(request.arguments, /*simplifiedResult*/ false)!); // TODO: GH#18217 + return this.requiredResponse(this.getSignatureHelpItems(request.arguments, /*simplifiedResult*/ false)); }, [CommandNames.CompilerOptionsDiagnosticsFull]: (request: protocol.CompilerOptionsDiagnosticsRequest) => { return this.requiredResponse(this.getCompilerOptionsDiagnostics(request.arguments)); @@ -2055,22 +2055,22 @@ namespace ts.server { return this.requiredResponse(this.getNavigateToItems(request.arguments, /*simplifiedResult*/ false)); }, [CommandNames.Brace]: (request: protocol.FileLocationRequest) => { - return this.requiredResponse(this.getBraceMatching(request.arguments, /*simplifiedResult*/ true)!); // TODO: GH#18217 + return this.requiredResponse(this.getBraceMatching(request.arguments, /*simplifiedResult*/ true)); }, [CommandNames.BraceFull]: (request: protocol.FileLocationRequest) => { - return this.requiredResponse(this.getBraceMatching(request.arguments, /*simplifiedResult*/ false)!); // TODO: GH#18217 + return this.requiredResponse(this.getBraceMatching(request.arguments, /*simplifiedResult*/ false)); }, [CommandNames.NavBar]: (request: protocol.FileRequest) => { - return this.requiredResponse(this.getNavigationBarItems(request.arguments, /*simplifiedResult*/ true)!); // TODO: GH#18217 + return this.requiredResponse(this.getNavigationBarItems(request.arguments, /*simplifiedResult*/ true)); }, [CommandNames.NavBarFull]: (request: protocol.FileRequest) => { - return this.requiredResponse(this.getNavigationBarItems(request.arguments, /*simplifiedResult*/ false)!); // TODO: GH#18217 + return this.requiredResponse(this.getNavigationBarItems(request.arguments, /*simplifiedResult*/ false)); }, [CommandNames.NavTree]: (request: protocol.FileRequest) => { - return this.requiredResponse(this.getNavigationTree(request.arguments, /*simplifiedResult*/ true)!); // TODO: GH#18217 + return this.requiredResponse(this.getNavigationTree(request.arguments, /*simplifiedResult*/ true)); }, [CommandNames.NavTreeFull]: (request: protocol.FileRequest) => { - return this.requiredResponse(this.getNavigationTree(request.arguments, /*simplifiedResult*/ false)!); // TODO: GH#18217 + return this.requiredResponse(this.getNavigationTree(request.arguments, /*simplifiedResult*/ false)); }, [CommandNames.Occurrences]: (request: protocol.FileLocationRequest) => { return this.requiredResponse(this.getOccurrences(request.arguments)); @@ -2093,10 +2093,10 @@ namespace ts.server { return this.notRequired(); }, [CommandNames.GetCodeFixes]: (request: protocol.CodeFixRequest) => { - return this.requiredResponse(this.getCodeFixes(request.arguments, /*simplifiedResult*/ true)!); // TODO: GH#18217 + return this.requiredResponse(this.getCodeFixes(request.arguments, /*simplifiedResult*/ true)); }, [CommandNames.GetCodeFixesFull]: (request: protocol.CodeFixRequest) => { - return this.requiredResponse(this.getCodeFixes(request.arguments, /*simplifiedResult*/ false)!); // TODO: GH#18217 + return this.requiredResponse(this.getCodeFixes(request.arguments, /*simplifiedResult*/ false)); }, [CommandNames.GetCombinedCodeFix]: (request: protocol.GetCombinedCodeFixRequest) => { return this.requiredResponse(this.getCombinedCodeFix(request.arguments, /*simplifiedResult*/ true)); From b98cbbb648bd96cc85dc6ae696424779ee3312a3 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 24 Apr 2018 13:59:49 -0700 Subject: [PATCH 12/42] Mark optional properties as optional instead of using `| undefined` --- src/server/protocol.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/server/protocol.ts b/src/server/protocol.ts index 761b611896ef0..3492da29aad14 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -1196,7 +1196,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; } /** @@ -1802,7 +1802,7 @@ namespace ts.server.protocol { export interface CompletionEntryIdentifier { name: string; - source: string | undefined; + source?: string; } /** @@ -1905,12 +1905,12 @@ namespace ts.server.protocol { /** * Documentation strings for the symbol. */ - documentation: SymbolDisplayPart[] | undefined; + documentation?: SymbolDisplayPart[]; /** * JSDoc tags for the symbol. */ - tags: JSDocTagInfo[] | undefined; + tags?: JSDocTagInfo[]; /** * The associated code actions for this entry From ddffe1ff06126d541990512adc7977b765436fb3 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 24 Apr 2018 14:07:27 -0700 Subject: [PATCH 13/42] Mark optional properties as optional instead of using ` | undefined` --- src/services/types.ts | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/services/types.ts b/src/services/types.ts index 5ab7fa31f2b69..89760a64f9917 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -155,7 +155,7 @@ namespace ts { referencedFiles: FileReference[]; typeReferenceDirectives: FileReference[]; importedFiles: FileReference[]; - ambientExternalModules: string[] | undefined; + ambientExternalModules?: string[]; isLibFile: boolean; } @@ -460,7 +460,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. @@ -522,8 +522,8 @@ namespace ts { */ export interface RefactorEditInfo { edits: FileTextChanges[]; - renameFilename: string | undefined; - renameLocation: number | undefined; + renameFilename?: string ; + renameLocation?: number; commands?: CodeActionCommand[]; } @@ -659,7 +659,7 @@ namespace ts { } export interface DefinitionInfoAndBoundSpan { - definitions: ReadonlyArray | undefined; + definitions?: ReadonlyArray; textSpan: TextSpan; } @@ -711,14 +711,14 @@ namespace ts { kind: ScriptElementKind; kindModifiers: string; textSpan: TextSpan; - displayParts: SymbolDisplayPart[] | undefined; - documentation: SymbolDisplayPart[] | undefined; - tags: JSDocTagInfo[] | undefined; + displayParts?: SymbolDisplayPart[]; + documentation?: SymbolDisplayPart[]; + tags?: JSDocTagInfo[]; } export interface RenameInfo { canRename: boolean; - localizedErrorMessage: string | undefined; + localizedErrorMessage?: string; displayName: string; fullDisplayName: string; kind: ScriptElementKind; @@ -777,7 +777,7 @@ namespace ts { export interface CompletionEntry { name: string; kind: ScriptElementKind; - kindModifiers: string | undefined; // see ScriptElementKindModifier, comma separated + kindModifiers?: string; // see ScriptElementKindModifier, comma separated sortText: string; insertText?: string; /** @@ -796,8 +796,8 @@ namespace ts { kind: ScriptElementKind; kindModifiers: string; // see ScriptElementKindModifier, comma separated displayParts: SymbolDisplayPart[]; - documentation: SymbolDisplayPart[] | undefined; - tags: JSDocTagInfo[] | undefined; + documentation?: SymbolDisplayPart[]; + tags?: JSDocTagInfo[]; codeActions?: CodeAction[]; source?: SymbolDisplayPart[]; } From ced45f44b54e4597d2389d5cd3e098c7680fe260 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 24 Apr 2018 14:10:11 -0700 Subject: [PATCH 14/42] Remove unnecessary null assertions --- src/compiler/binder.ts | 6 +++--- src/compiler/checker.ts | 2 +- src/compiler/factory.ts | 2 +- src/compiler/transformers/generators.ts | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index f7494869f730c..a6b1db06b5ff5 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -2981,7 +2981,7 @@ namespace ts { // If the expression of a ParenthesizedExpression is a destructuring assignment, // then the ParenthesizedExpression is a destructuring assignment. - if (expressionTransformFlags! & TransformFlags.DestructuringAssignment) { + if (expressionTransformFlags & TransformFlags.DestructuringAssignment) { transformFlags |= TransformFlags.DestructuringAssignment; } @@ -3324,7 +3324,7 @@ namespace ts { // If an ElementAccessExpression starts with a super keyword, then it is // ES6 syntax, and requires a lexical `this` binding. - if (expressionFlags! & TransformFlags.Super) { + if (expressionFlags & TransformFlags.Super) { transformFlags &= ~TransformFlags.Super; transformFlags |= TransformFlags.ContainsSuper; } @@ -3362,7 +3362,7 @@ namespace ts { else { transformFlags = subtreeFlags; - if (declarationListTransformFlags! & TransformFlags.ContainsBindingPattern) { + if (declarationListTransformFlags & TransformFlags.ContainsBindingPattern) { transformFlags |= TransformFlags.AssertES2015; } } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6b479ceae82c1..58134be4e0037 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -23176,7 +23176,7 @@ namespace ts { return undefined; } - const returnType = getUnionType(map(signatures!, getReturnTypeOfSignature), UnionReduction.Subtype); + const returnType = getUnionType(map(signatures, getReturnTypeOfSignature), UnionReduction.Subtype); const iteratedType = getIteratedTypeOfIterator(returnType, errorNode, /*isAsyncIterator*/ !!asyncMethodType); if (checkAssignability && errorNode && iteratedType) { // If `checkAssignability` was specified, we were called from diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 842735f912397..5e4239a328610 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -2960,7 +2960,7 @@ namespace ts { } if (helpersRemoved > 0) { - sourceEmitHelpers!.length -= helpersRemoved; + sourceEmitHelpers.length -= helpersRemoved; } } diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts index ee5564c1ca6d6..35af6a32bcb83 100644 --- a/src/compiler/transformers/generators.ts +++ b/src/compiler/transformers/generators.ts @@ -316,10 +316,10 @@ namespace ts { else if (inGeneratorFunctionBody) { return visitJavaScriptInGeneratorFunctionBody(node); } - else if (transformFlags! & TransformFlags.Generator) { + else if (transformFlags & TransformFlags.Generator) { return visitGenerator(node); } - else if (transformFlags! & TransformFlags.ContainsGenerator) { + else if (transformFlags & TransformFlags.ContainsGenerator) { return visitEachChild(node, visitor, context); } else { From 95fdfaf57cabec5bcb33a6ac17bb9422b77c2a49 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 24 Apr 2018 15:10:02 -0700 Subject: [PATCH 15/42] Put the bang on the declaration instead of every use --- src/compiler/scanner.ts | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 0968cf2ca40f7..dee23a3279104 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -627,10 +627,10 @@ namespace ts { * 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 | undefined) => U, state: T, initial?: U): U | undefined { - let pendingPos: number | undefined; - let pendingEnd: number | undefined; - let pendingKind: CommentKind | undefined; - let pendingHasTrailingNewLine: boolean | undefined; + let pendingPos!: number; + let pendingEnd!: number; + let pendingKind!: CommentKind; + let pendingHasTrailingNewLine!: boolean; let hasPendingCommentRange = false; let collecting = trailing || pos === 0; let accumulator = initial; @@ -688,7 +688,7 @@ namespace ts { if (collecting) { if (hasPendingCommentRange) { - accumulator = cb(pendingPos!, pendingEnd!, pendingKind!, pendingHasTrailingNewLine!, state, accumulator); + accumulator = cb(pendingPos, pendingEnd, pendingKind, pendingHasTrailingNewLine, state, accumulator); if (!reduce && accumulator) { // If we are not reducing and we have a truthy result, return it. return accumulator; @@ -718,7 +718,7 @@ namespace ts { } if (hasPendingCommentRange) { - accumulator = cb(pendingPos!, pendingEnd!, pendingKind!, pendingHasTrailingNewLine!, state, accumulator); + accumulator = cb(pendingPos, pendingEnd, pendingKind, pendingHasTrailingNewLine, state, accumulator); } return accumulator; @@ -820,7 +820,7 @@ namespace ts { let tokenPos: number; let token: SyntaxKind; - let tokenValue: string | undefined; + let tokenValue!: string; let tokenFlags: TokenFlags; setText(text, start, length); @@ -831,7 +831,7 @@ namespace ts { getToken: () => token, getTokenPos: () => tokenPos, getTokenText: () => text.substring(tokenPos, pos), - getTokenValue: () => tokenValue!, + getTokenValue: () => tokenValue, hasExtendedUnicodeEscape: () => (tokenFlags & TokenFlags.ExtendedUnicodeEscape) !== 0, hasPrecedingLineBreak: () => (tokenFlags & TokenFlags.PrecedingLineBreak) !== 0, isIdentifier: () => token === SyntaxKind.Identifier || token > SyntaxKind.LastReservedWord, @@ -1284,11 +1284,11 @@ namespace ts { function getIdentifierToken(): SyntaxKind { // Reserved words are between 2 and 11 characters long and start with a lowercase letter - const len = tokenValue!.length; + const len = tokenValue.length; if (len >= 2 && len <= 11) { - const ch = tokenValue!.charCodeAt(0); + 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; } @@ -2074,7 +2074,7 @@ namespace ts { startPos = textPos; tokenPos = textPos; token = SyntaxKind.Unknown; - tokenValue = undefined; + tokenValue = undefined!; tokenFlags = 0; } } From 0b53a42243821a33a24601490b211fe1b245b54a Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 24 Apr 2018 15:25:33 -0700 Subject: [PATCH 16/42] Make `createMapFromTemplate` require a parameter --- src/compiler/core.ts | 6 +++--- src/server/editorServices.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index c729eb3114bda..2f6dba6084575 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -59,14 +59,14 @@ 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 // template is undefined, and instead will just exit the loop. - for (const key in template!) { + for (const key in template) { if (hasOwnProperty.call(template, key)) { - map.set(key, template![key]); + map.set(key, template[key]); } } diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 8647cd21c2da4..d07cfe6d2f64d 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1333,7 +1333,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 }; From bd0b455cf91209ca4c4fee2cc34cf5674c8cc8d3 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 24 Apr 2018 15:32:42 -0700 Subject: [PATCH 17/42] Mark `EmitResult.emittedFiles` and `EmitResult.sourceMaps` as optional --- src/compiler/emitter.ts | 4 ++-- src/compiler/program.ts | 6 +++--- src/compiler/types.ts | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index d7e2dc8bff54c..fd093d3cfadab 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -109,8 +109,8 @@ namespace ts { return { emitSkipped, diagnostics: emitterDiagnostics.getDiagnostics(), - emittedFiles: emittedFilesList!, // TODO: GH#18217 - sourceMaps: sourceMapDataList!, // TODO: GH#18217 + emittedFiles: emittedFilesList, + sourceMaps: sourceMapDataList, }; function emitSourceFileOrBundle({ jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath }: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle) { diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 782daccdd77c5..7692dc5b292c9 100755 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1148,7 +1148,7 @@ namespace ts { if (!emitOnlyDtsFiles) { if (options.noEmit) { - return { diagnostics: declarationDiagnostics, sourceMaps: undefined!, emittedFiles: undefined!, emitSkipped: true }; // TODO: GH#18217 + return { diagnostics: declarationDiagnostics, sourceMaps: undefined, emittedFiles: undefined, emitSkipped: true }; } // If the noEmitOnError flag is set, then check if we have any errors so far. If so, @@ -1169,8 +1169,8 @@ namespace ts { if (diagnostics.length > 0 || declarationDiagnostics.length > 0) { return { diagnostics: concatenate(diagnostics, declarationDiagnostics), - sourceMaps: undefined!, - emittedFiles: undefined!, + sourceMaps: undefined, + emittedFiles: undefined, emitSkipped: true }; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index bfbe38c6eb0a7..70f3d9c0b7de6 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2790,8 +2790,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 */ From 971fa9ab7b71eb99d40231b7f4898a2638e0de42 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 24 Apr 2018 15:44:56 -0700 Subject: [PATCH 18/42] Plumb through undefined in emitLsit and EmitExpressionList --- src/compiler/emitter.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index fd093d3cfadab..b546f6b0808e5 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -975,7 +975,7 @@ namespace ts { function emitIdentifier(node: Identifier) { const writeText = node.symbol ? writeSymbol : write; writeText(getTextOfNode(node, /*includeTrivia*/ false), node.symbol!); - emitList(node, node.typeArguments!, ListFormat.TypeParameters); // Call emitList directly since it could be an array of TypeParameterDeclarations _or_ type arguments + emitList(node, node.typeArguments, ListFormat.TypeParameters); // Call emitList directly since it could be an array of TypeParameterDeclarations _or_ type arguments } // @@ -1457,7 +1457,7 @@ namespace ts { writeSpace(); emitExpression(node.expression); emitTypeArguments(node, node.typeArguments); - emitExpressionList(node, node.arguments!, ListFormat.NewExpressionArguments); + emitExpressionList(node, node.arguments, ListFormat.NewExpressionArguments); } function emitTaggedTemplateExpression(node: TaggedTemplateExpression) { @@ -2723,7 +2723,7 @@ namespace ts { emitNodeList(emit, parentNode, children, format, start, count); } - function emitExpressionList(parentNode: TextRange, children: NodeArray, format: ListFormat, start?: number, count?: number) { + function emitExpressionList(parentNode: TextRange, children: NodeArray | undefined, format: ListFormat, start?: number, count?: number) { emitNodeList(emitExpression, parentNode, children, format, start, count); } From 94c416d6af5ced20020e2c27e7155196f1fbaffa Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 24 Apr 2018 15:53:08 -0700 Subject: [PATCH 19/42] `ElementAccessExpression.argumentExpression` can not be `undefined` --- src/compiler/checker.ts | 10 +++++----- src/compiler/emitter.ts | 2 +- src/compiler/factory.ts | 4 ++-- src/compiler/transformers/es2016.ts | 2 +- src/compiler/transformers/es2017.ts | 2 +- src/compiler/transformers/esnext.ts | 2 +- src/compiler/transformers/generators.ts | 4 ++-- src/compiler/transformers/ts.ts | 2 +- src/compiler/types.ts | 2 +- src/compiler/utilities.ts | 2 +- src/compiler/visitor.ts | 2 +- 11 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 58134be4e0037..9af871d5858e9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8341,7 +8341,7 @@ namespace ts { 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) ? + accessExpression && checkThatExpressionIsProperSymbolReference(accessExpression.argumentExpression, indexType, /*reportError*/ false) ? getPropertyNameForKnownSymbolName(idText((accessExpression.argumentExpression).name)) : undefined; if (propName !== undefined) { @@ -13136,7 +13136,7 @@ namespace ts { (parent.parent).operatorToken.kind === SyntaxKind.EqualsToken && (parent.parent).left === parent && !isAssignmentTarget(parent.parent) && - isTypeAssignableToKind(getTypeOfExpression((parent).argumentExpression!), TypeFlags.NumberLike); + isTypeAssignableToKind(getTypeOfExpression((parent).argumentExpression), TypeFlags.NumberLike); return isLengthPushOrUnshift || isElementAssignment; } @@ -13327,7 +13327,7 @@ namespace ts { } } else { - const indexType = getTypeOfExpression((node.left).argumentExpression!); + const indexType = getTypeOfExpression((node.left).argumentExpression); if (isTypeAssignableToKind(indexType, TypeFlags.NumberLike)) { evolvedType = addEvolvingArrayElementType(evolvedType, node.right); } @@ -24231,7 +24231,7 @@ namespace ts { name = ex.name.escapedText; } else { - const argument = ex.argumentExpression!; + const argument = ex.argumentExpression; Debug.assert(isLiteralExpression(argument)); name = escapeLeadingUnderscores((argument as LiteralExpression).text); } @@ -24263,7 +24263,7 @@ namespace ts { return node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.PropertyAccessExpression && isConstantMemberAccess((node).expression) || node.kind === SyntaxKind.ElementAccessExpression && isConstantMemberAccess((node).expression) && - (node).argumentExpression!.kind === SyntaxKind.StringLiteral; + (node).argumentExpression.kind === SyntaxKind.StringLiteral; } function checkEnumDeclaration(node: EnumDeclaration) { diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index b546f6b0808e5..1bf81fcf8a415 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1442,7 +1442,7 @@ namespace ts { function emitElementAccessExpression(node: ElementAccessExpression) { emitExpression(node.expression); const openPos = emitTokenWithComment(SyntaxKind.OpenBracketToken, node.expression.end, writePunctuation, node); - emitExpression(node.argumentExpression!); // TODO: GH#18217 + emitExpression(node.argumentExpression); emitTokenWithComment(SyntaxKind.CloseBracketToken, node.argumentExpression ? node.argumentExpression.end : openPos, writePunctuation, node); } diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 5e4239a328610..b5ab74bff192e 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -986,7 +986,7 @@ namespace ts { : node; } - export function createElementAccess(expression: Expression, index: number | Expression | undefined) { + export function createElementAccess(expression: Expression, index: number | Expression) { const node = createSynthesizedNode(SyntaxKind.ElementAccessExpression); node.expression = parenthesizeForAccess(expression); node.argumentExpression = asExpression(index); @@ -2684,7 +2684,7 @@ namespace ts { return isString(name) ? createIdentifier(name) : name; } - function asExpression(value: string | number | Expression | undefined) { + function asExpression(value: string | number | Expression) { return isString(value) || typeof value === "number" ? createLiteral(value) : value; } diff --git a/src/compiler/transformers/es2016.ts b/src/compiler/transformers/es2016.ts index e4c56f98fa700..22b2f11b6122e 100644 --- a/src/compiler/transformers/es2016.ts +++ b/src/compiler/transformers/es2016.ts @@ -48,7 +48,7 @@ namespace ts { target = setTextRange( createElementAccess( setTextRange(createAssignment(expressionTemp, left.expression), left.expression), - setTextRange(createAssignment(argumentExpressionTemp, left.argumentExpression!), left.argumentExpression) + setTextRange(createAssignment(argumentExpressionTemp, left.argumentExpression), left.argumentExpression) ), left ); diff --git a/src/compiler/transformers/es2017.ts b/src/compiler/transformers/es2017.ts index f611dc4a33f26..2e8224df0a064 100644 --- a/src/compiler/transformers/es2017.ts +++ b/src/compiler/transformers/es2017.ts @@ -559,7 +559,7 @@ namespace ts { function substituteElementAccessExpression(node: ElementAccessExpression) { if (node.expression.kind === SyntaxKind.SuperKeyword) { return createSuperAccessInAsyncMethod( - node.argumentExpression!, + node.argumentExpression, node ); } diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index 542274b9407bc..ffb0938295bce 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -794,7 +794,7 @@ namespace ts { function substituteElementAccessExpression(node: ElementAccessExpression) { if (node.expression.kind === SyntaxKind.SuperKeyword) { return createSuperAccessInAsyncMethod( - node.argumentExpression!, + node.argumentExpression, node ); } diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts index 35af6a32bcb83..caf4063c792e0 100644 --- a/src/compiler/transformers/generators.ts +++ b/src/compiler/transformers/generators.ts @@ -731,7 +731,7 @@ namespace ts { target = updateElementAccess(left, cacheExpression(visitNode((left).expression, visitor, isLeftHandSideExpression)), - cacheExpression(visitNode((left).argumentExpression!, visitor, isExpression)) + cacheExpression(visitNode((left).argumentExpression, visitor, isExpression)) ); break; @@ -1089,7 +1089,7 @@ namespace ts { * @param node The node to visit. */ function visitElementAccessExpression(node: ElementAccessExpression) { - if (containsYield(node.argumentExpression!)) { + if (containsYield(node.argumentExpression)) { // [source] // a = x[yield]; // diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 6c52b1096fa2c..0448923591b19 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -3536,7 +3536,7 @@ namespace ts { if (!compilerOptions.removeComments) { const propertyName = isPropertyAccessExpression(node) ? declarationNameToString(node.name) - : getTextOfNode(node.argumentExpression!); + : getTextOfNode(node.argumentExpression); addSyntheticTrailingComment(substitute, SyntaxKind.MultiLineCommentTrivia, ` ${propertyName} `); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 70f3d9c0b7de6..a80343c25310c 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1685,7 +1685,7 @@ namespace ts { export interface ElementAccessExpression extends MemberExpression { kind: SyntaxKind.ElementAccessExpression; expression: LeftHandSideExpression; - argumentExpression?: Expression; + argumentExpression: Expression; } export interface SuperElementAccessExpression extends ElementAccessExpression { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 71d190cfa8147..89d53474eeb85 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -4543,7 +4543,7 @@ namespace ts { case SyntaxKind.PropertyAccessExpression: return (expr as PropertyAccessExpression).name; case SyntaxKind.ElementAccessExpression: - const arg = (expr as ElementAccessExpression).argumentExpression!; + const arg = (expr as ElementAccessExpression).argumentExpression; if (isIdentifier(arg)) { return arg; } diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index 56c477e299375..ab54fba232ad7 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -461,7 +461,7 @@ namespace ts { case SyntaxKind.ElementAccessExpression: return updateElementAccess(node, visitNode((node).expression, visitor, isExpression), - visitNode((node).argumentExpression!, visitor, isExpression)); + visitNode((node).argumentExpression, visitor, isExpression)); case SyntaxKind.CallExpression: return updateCall(node, From 54a37db6534742eccaefbb4931b69aa615b8f155 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 24 Apr 2018 17:25:13 -0700 Subject: [PATCH 20/42] Add overloads for `writeTokenText` --- src/compiler/emitter.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 1bf81fcf8a415..95b920f16a2ca 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2997,6 +2997,8 @@ namespace ts { } } + 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); From 4c8ec965f1f5d5193e00c13dd47ee21c6d59063a Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 24 Apr 2018 17:27:35 -0700 Subject: [PATCH 21/42] Make `shouldWriteSeparatingLineTerminator` argument non-nullable --- src/compiler/emitter.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 95b920f16a2ca..87a69883215e7 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -3076,7 +3076,7 @@ namespace ts { } } - function shouldWriteSeparatingLineTerminator(previousNode: Node | undefined, nextNode: Node | undefined, format: ListFormat) { + function shouldWriteSeparatingLineTerminator(previousNode: Node | undefined, nextNode: Node, format: ListFormat) { if (format & ListFormat.MultiLine) { return true; } @@ -3092,7 +3092,7 @@ namespace ts { } } else { - return getStartsOnNewLine(nextNode!); // TODO: GH#18217 + return getStartsOnNewLine(nextNode); } } From 3f066aa7d2d892aaa84b66f19560f8176a6c1908 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 24 Apr 2018 17:29:37 -0700 Subject: [PATCH 22/42] Make `synthesizedNodeStartsOnNewLine` argument required --- src/compiler/emitter.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 87a69883215e7..6a8cf60d41aa5 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -3121,17 +3121,17 @@ namespace ts { } } - function synthesizedNodeStartsOnNewLine(node: Node, format?: ListFormat) { + function synthesizedNodeStartsOnNewLine(node: Node, format: ListFormat) { if (nodeIsSynthesized(node)) { const startsOnNewLine = getStartsOnNewLine(node); if (startsOnNewLine === undefined) { - return (format! & ListFormat.PreferNewLine) !== 0; + return (format & ListFormat.PreferNewLine) !== 0; } return startsOnNewLine; } - return (format! & ListFormat.PreferNewLine) !== 0; + return (format & ListFormat.PreferNewLine) !== 0; } function needsIndentation(parent: Node, node1: Node, node2: Node): boolean { From 9867f7dd844c8a7e02889e1444578dd45a26dda8 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 24 Apr 2018 17:48:39 -0700 Subject: [PATCH 23/42] `PropertyAssignment.initializer` cannot be undefined --- src/compiler/binder.ts | 2 +- src/compiler/checker.ts | 10 +++++----- src/compiler/commandLineParser.ts | 8 ++++---- src/compiler/emitter.ts | 2 +- src/compiler/factory.ts | 4 ++-- src/compiler/program.ts | 8 ++++---- src/compiler/transformers/es2015.ts | 2 +- src/compiler/transformers/es5.ts | 2 +- src/compiler/transformers/module/system.ts | 2 +- src/compiler/types.ts | 2 +- src/compiler/visitor.ts | 2 +- 11 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index a6b1db06b5ff5..5d2f79807d9fb 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1258,7 +1258,7 @@ namespace ts { else if (node.kind === SyntaxKind.ObjectLiteralExpression) { for (const p of (node).properties) { if (p.kind === SyntaxKind.PropertyAssignment) { - bindDestructuringTargetFlow(p.initializer!); + bindDestructuringTargetFlow(p.initializer); } else if (p.kind === SyntaxKind.ShorthandPropertyAssignment) { bindAssignmentTargetFlow(p.name); diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9af871d5858e9..e8b18e51b8c15 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -9479,7 +9479,7 @@ namespace ts { return (node).operatorToken.kind === SyntaxKind.BarBarToken && (isContextSensitive((node).left) || isContextSensitive((node).right)); case SyntaxKind.PropertyAssignment: - return isContextSensitive((node).initializer!); + return isContextSensitive((node).initializer); case SyntaxKind.ParenthesizedExpression: return isContextSensitive((node).expression); case SyntaxKind.JsxAttributes: @@ -14957,7 +14957,7 @@ namespace ts { if (!prop.symbol) continue; if (prop.kind !== SyntaxKind.PropertyAssignment) continue; if (isDiscriminantProperty(contextualType, prop.symbol!.escapedName)) { - const discriminatingType = getTypeOfNode(prop.initializer!)!; // TODO: GH#18217 + const discriminatingType = getTypeOfNode(prop.initializer)!; // TODO: GH#18217 for (const type of (contextualType as UnionType).types) { const targetType = getTypeOfPropertyOfType(type, prop.symbol!.escapedName); if (targetType && checkTypeAssignableTo(discriminatingType, targetType, /*errorNode*/ undefined)) { @@ -15502,7 +15502,7 @@ namespace ts { // If object literal is an assignment pattern and if the assignment pattern specifies a default value // for the property, make the property optional. const isOptional = - (memberDecl.kind === SyntaxKind.PropertyAssignment && hasDefaultValue(memberDecl.initializer!)) || + (memberDecl.kind === SyntaxKind.PropertyAssignment && hasDefaultValue(memberDecl.initializer)) || (memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment && memberDecl.objectAssignmentInitializer); if (isOptional) { prop.flags |= SymbolFlags.Optional; @@ -19576,7 +19576,7 @@ namespace ts { } else { // non-shorthand property assignments should always have initializers - return checkDestructuringAssignment(property.initializer!, type); + return checkDestructuringAssignment(property.initializer, type); } } else { @@ -20197,7 +20197,7 @@ namespace ts { checkComputedPropertyName(node.name); } - return checkExpressionForMutableLocation(node.initializer!, checkMode); + return checkExpressionForMutableLocation(node.initializer, checkMode); } function checkObjectLiteralMethod(node: MethodDeclaration, checkMode?: CheckMode): Type { diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 973adc8c670cb..1c7ceac69f3d7 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -1103,7 +1103,7 @@ namespace ts { if (extraKeyDiagnosticMessage && !option) { errors.push(createDiagnosticForNodeInSourceFile(sourceFile, element.name, extraKeyDiagnosticMessage, keyText)); } - const value = convertPropertyValueToJson(element.initializer!, option); // TODO: GH#18217 + const value = convertPropertyValueToJson(element.initializer, option); if (typeof keyText !== "undefined") { result[keyText] = value; // Notify key value set, if user asked for it @@ -1120,11 +1120,11 @@ namespace ts { else if (knownOptions === knownRootOptions) { if (isValidOptionValue) { // Notify about the valid root key value being set - jsonConversionNotifier.onSetValidOptionKeyValueInRoot(keyText, element.name, value, element.initializer!); + jsonConversionNotifier.onSetValidOptionKeyValueInRoot(keyText, element.name, value, element.initializer); } else if (!option) { // Notify about the unknown root key value being set - jsonConversionNotifier.onSetUnknownOptionKeyValueInRoot(keyText, element.name, value, element.initializer!); + jsonConversionNotifier.onSetUnknownOptionKeyValueInRoot(keyText, element.name, value, element.initializer); } } } @@ -2116,7 +2116,7 @@ namespace ts { function createDiagnostic(message: DiagnosticMessage, spec: string): Diagnostic { if (jsonSourceFile && jsonSourceFile.jsonObject) { for (const property of getPropertyAssignment(jsonSourceFile.jsonObject, specKey)) { - const initializer = property.initializer!; + const initializer = property.initializer; if (isArrayLiteralExpression(initializer)) { for (const element of initializer.elements) { if (isStringLiteral(element) && element.text === spec) { diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 6a8cf60d41aa5..4047442c485b4 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2420,7 +2420,7 @@ namespace ts { // } // "comment1" is not considered to be leading comment for node.initializer // but rather a trailing comment on the previous node. - const initializer = node.initializer!; + const initializer = node.initializer; if (emitTrailingCommentsOfPosition && (getEmitFlags(initializer) & EmitFlags.NoLeadingComments) === 0) { const commentRange = getCommentRange(initializer); emitTrailingCommentsOfPosition(commentRange.pos); diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index b5ab74bff192e..10b03edca9975 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -3576,7 +3576,7 @@ namespace ts { setTextRange( createAssignment( createMemberAccessForPropertyName(receiver, property.name, /*location*/ property.name), - property.initializer! // TODO: GH#18217 + property.initializer ), property ), @@ -4529,7 +4529,7 @@ namespace ts { // `1` in `({ a: b = 1 } = ...)` // `1` in `({ a: {b} = 1 } = ...)` // `1` in `({ a: [b] = 1 } = ...)` - const initializer = bindingElement.initializer!; // TODO: GH#18217 + const initializer = bindingElement.initializer; return isAssignmentExpression(initializer, /*excludeCompoundAssignment*/ true) ? initializer.right : undefined; diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 7692dc5b292c9..94dcd441fe99a 100755 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -2291,7 +2291,7 @@ namespace ts { let needCompilerDiagnostic = true; const pathsSyntax = getOptionPathsSyntax(); for (const pathProp of pathsSyntax) { - if (isObjectLiteralExpression(pathProp.initializer!)) { // TODO: GH#18217 + if (isObjectLiteralExpression(pathProp.initializer)) { for (const keyProps of getPropertyAssignment(pathProp.initializer as ObjectLiteralExpression, key)) { const initializer = keyProps.initializer!; if (isArrayLiteralExpression(initializer) && initializer.elements.length > valueIndex) { @@ -2311,7 +2311,7 @@ namespace ts { let needCompilerDiagnostic = true; const pathsSyntax = getOptionPathsSyntax(); for (const pathProp of pathsSyntax) { - if (isObjectLiteralExpression(pathProp.initializer!) && // TODO: GH#18217 + if (isObjectLiteralExpression(pathProp.initializer) && createOptionDiagnosticInObjectLiteralSyntax( pathProp.initializer as ObjectLiteralExpression, onKey, key, /*key2*/ undefined, message, arg0)) { @@ -2354,7 +2354,7 @@ namespace ts { _compilerOptionsObjectLiteralSyntax = null; // tslint:disable-line:no-null-keyword if (options.configFile && options.configFile.jsonObject) { for (const prop of getPropertyAssignment(options.configFile.jsonObject, "compilerOptions")) { - if (isObjectLiteralExpression(prop.initializer!)) { // TODO: GH#18217 + if (isObjectLiteralExpression(prop.initializer)) { _compilerOptionsObjectLiteralSyntax = prop.initializer as ObjectLiteralExpression; break; } @@ -2367,7 +2367,7 @@ namespace ts { 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; } diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index fbad8a7e7883b..5ecf85639d6eb 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -3069,7 +3069,7 @@ namespace ts { receiver, visitNode(property.name, visitor, isPropertyName) ), - visitNode(property.initializer!, visitor, isExpression) + visitNode(property.initializer, visitor, isExpression) ); setTextRange(expression, property); if (startsOnNewLine) { diff --git a/src/compiler/transformers/es5.ts b/src/compiler/transformers/es5.ts index 7dbcececd6c0b..7f81bf9ed279b 100644 --- a/src/compiler/transformers/es5.ts +++ b/src/compiler/transformers/es5.ts @@ -97,7 +97,7 @@ namespace ts { function substitutePropertyAssignment(node: PropertyAssignment): PropertyAssignment { const literalName = isIdentifier(node.name) && trySubstituteReservedName(node.name); if (literalName) { - return updatePropertyAssignment(node, literalName, node.initializer!); + return updatePropertyAssignment(node, literalName, node.initializer); } return node; } diff --git a/src/compiler/transformers/module/system.ts b/src/compiler/transformers/module/system.ts index e88e028049eab..5a7f4a71910e5 100644 --- a/src/compiler/transformers/module/system.ts +++ b/src/compiler/transformers/module/system.ts @@ -1540,7 +1540,7 @@ namespace ts { return hasExportedReferenceInDestructuringTarget(node.name); } else if (isPropertyAssignment(node)) { - return hasExportedReferenceInDestructuringTarget(node.initializer!); + return hasExportedReferenceInDestructuringTarget(node.initializer); } else if (isIdentifier(node)) { const container = resolver.getReferencedExportContainer(node); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index a80343c25310c..5687eb21d131b 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -905,7 +905,7 @@ namespace ts { kind: SyntaxKind.PropertyAssignment; name: PropertyName; questionToken?: QuestionToken; - initializer?: Expression; + initializer: Expression; } export interface ShorthandPropertyAssignment extends ObjectLiteralElement, JSDocContainer { diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index ab54fba232ad7..29989dc20a479 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -887,7 +887,7 @@ namespace ts { case SyntaxKind.PropertyAssignment: return updatePropertyAssignment(node, visitNode((node).name, visitor, isPropertyName), - visitNode((node).initializer!, visitor, isExpression)); + visitNode((node).initializer, visitor, isExpression)); case SyntaxKind.ShorthandPropertyAssignment: return updateShorthandPropertyAssignment(node, From 4dc981ff290d116298522bf6d7507e2f6b9fcddd Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 24 Apr 2018 22:52:42 -0700 Subject: [PATCH 24/42] Use one `!` at declaration site instead of on every use site --- src/compiler/parser.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index bb7dc9839db89..2e170d87b40ce 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -2720,7 +2720,7 @@ namespace ts { function parseLiteralTypeNode(negative?: boolean): LiteralTypeNode { const node = createNode(SyntaxKind.LiteralType) as LiteralTypeNode; - let unaryMinusExpression: PrefixUnaryExpression | undefined; + let unaryMinusExpression!: PrefixUnaryExpression; if (negative) { unaryMinusExpression = createNode(SyntaxKind.PrefixUnaryExpression) as PrefixUnaryExpression; unaryMinusExpression.operator = SyntaxKind.MinusToken; @@ -2730,9 +2730,9 @@ namespace ts { ? parseTokenNode() : parseLiteralLikeNode(token()) as LiteralExpression; if (negative) { - unaryMinusExpression!.operand = expression; - finishNode(unaryMinusExpression!); - expression = unaryMinusExpression!; + unaryMinusExpression.operand = expression; + finishNode(unaryMinusExpression); + expression = unaryMinusExpression; } node.literal = expression; return finishNode(node); @@ -4802,7 +4802,7 @@ namespace ts { const awaitToken = parseOptionalToken(SyntaxKind.AwaitKeyword); parseExpected(SyntaxKind.OpenParenToken); - let initializer: VariableDeclarationList | Expression | undefined; + let initializer!: VariableDeclarationList | Expression; if (token() !== SyntaxKind.SemicolonToken) { if (token() === SyntaxKind.VarKeyword || token() === SyntaxKind.LetKeyword || token() === SyntaxKind.ConstKeyword) { initializer = parseVariableDeclarationList(/*inForStatementInitializer*/ true); @@ -4815,14 +4815,14 @@ namespace ts { if (awaitToken ? parseExpected(SyntaxKind.OfKeyword) : parseOptional(SyntaxKind.OfKeyword)) { const forOfStatement = createNode(SyntaxKind.ForOfStatement, pos); forOfStatement.awaitModifier = awaitToken; - forOfStatement.initializer = initializer!; + forOfStatement.initializer = initializer; forOfStatement.expression = allowInAnd(parseAssignmentExpressionOrHigher); parseExpected(SyntaxKind.CloseParenToken); forOrForInOrForOfStatement = forOfStatement; } else if (parseOptional(SyntaxKind.InKeyword)) { const forInStatement = createNode(SyntaxKind.ForInStatement, pos); - forInStatement.initializer = initializer!; + forInStatement.initializer = initializer; forInStatement.expression = allowInAnd(parseExpression); parseExpected(SyntaxKind.CloseParenToken); forOrForInOrForOfStatement = forInStatement; From faf868fdd94c7699ce77090893759869a0c1ca99 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 24 Apr 2018 23:16:16 -0700 Subject: [PATCH 25/42] Capture host in a constant and avoid null assertions --- src/compiler/program.ts | 75 ++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 38 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 94dcd441fe99a..7368327de3600 100755 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -491,8 +491,7 @@ namespace ts { * @param configFileParsingDiagnostics - error during config file parsing * @returns A 'Program' object. */ - // TODO: GH#18217 Have to write `host!` a lot - export function createProgram(rootNames: ReadonlyArray, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray): Program { + export function createProgram(rootNames: ReadonlyArray, options: CompilerOptions, compilerHost?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray): Program { let program: Program; let files: SourceFile[] = []; let commonSourceDirectory: string; @@ -526,10 +525,10 @@ namespace ts { performance.mark("beforeProgram"); - host = host || createCompilerHost(options); + const host = compilerHost || createCompilerHost(options); let skipDefaultLib = options.noLib; - const getDefaultLibraryFileName = memoize(() => host!.getDefaultLibFileName(options)); + const getDefaultLibraryFileName = memoize(() => host.getDefaultLibFileName(options)); const defaultLibraryPath = host.getDefaultLibLocation ? host.getDefaultLibLocation() : getDirectoryPath(getDefaultLibraryFileName()); const programDiagnostics = createDiagnosticCollection(); const currentDirectory = host.getCurrentDirectory(); @@ -543,7 +542,7 @@ namespace ts { 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; @@ -554,17 +553,17 @@ namespace ts { }); } else { - moduleResolutionCache = createModuleResolutionCache(currentDirectory, x => host!.getCanonicalFileName(x)); - const loader = (moduleName: string, containingFile: string) => resolveModuleName(moduleName, containingFile, options, host!, moduleResolutionCache).resolvedModule!; // TODO: GH#18217 + moduleResolutionCache = createModuleResolutionCache(currentDirectory, x => host.getCanonicalFileName(x)); + 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!; // TODO: GH#18217 + const loader = (typesRef: string, containingFile: string) => resolveTypeReferenceDirective(typesRef, containingFile, options, host).resolvedTypeReferenceDirective!; // TODO: GH#18217 resolveTypeReferenceDirectiveNamesWorker = (typeReferenceDirectiveNames, containingFile) => loadWithLocalCache(Debug.assertEachDefined(typeReferenceDirectiveNames), containingFile, loader); } @@ -778,8 +777,8 @@ namespace ts { if (file === oldSourceFile && !hasInvalidatedResolution(oldSourceFile.path)) { 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); + if (isTraceEnabled(options, host)) { + trace(host, Diagnostics.Reusing_resolution_of_module_0_to_file_1_from_old_program, moduleName, containingFile); } (result || (result = new Array(moduleNames.length)))[i] = oldResolvedModule; (reusedNames || (reusedNames = [])).push(moduleName); @@ -793,8 +792,8 @@ namespace ts { let resolvesToAmbientModuleInNonModifiedFile = false; if (contains(file.ambientModuleNames, moduleName)) { resolvesToAmbientModuleInNonModifiedFile = true; - if (isTraceEnabled(options, host!)) { - trace(host!, Diagnostics.Module_0_was_resolved_as_locally_declared_ambient_module_in_file_1, moduleName, containingFile); + if (isTraceEnabled(options, host)) { + trace(host, Diagnostics.Module_0_was_resolved_as_locally_declared_ambient_module_in_file_1, moduleName, containingFile); } } else { @@ -866,8 +865,8 @@ namespace ts { return false; } - if (isTraceEnabled(options, host!)) { - trace(host!, Diagnostics.Module_0_was_resolved_as_ambient_module_declared_in_1_since_this_file_was_not_modified, moduleName, firstUnmodifiedFile.fileName); + if (isTraceEnabled(options, host)) { + trace(host, Diagnostics.Module_0_was_resolved_as_ambient_module_declared_in_1_since_this_file_was_not_modified, moduleName, firstUnmodifiedFile.fileName); } return true; } @@ -906,7 +905,7 @@ namespace ts { // If the missing file paths are now present, it can change the progam structure, // and hence cant reuse the structure. // This is same as how we dont reuse the structure if one of the file from old program is now missing - if (oldProgram.getMissingFilePaths().some(missingFilePath => host!.fileExists(missingFilePath))) { + if (oldProgram.getMissingFilePaths().some(missingFilePath => host.fileExists(missingFilePath))) { return oldProgram.structureIsReused = StructureIsReused.Not; } @@ -915,9 +914,9 @@ namespace ts { const seenPackageNames = createMap(); 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); // TODO: GH#18217 + let newSourceFile = host.getSourceFileByPath + ? 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; @@ -1053,7 +1052,7 @@ namespace ts { return oldProgram.structureIsReused; } - if (host!.hasChangedAutomaticTypeDirectiveNames) { + if (host.hasChangedAutomaticTypeDirectiveNames) { return oldProgram.structureIsReused = StructureIsReused.SafeModules; } @@ -1088,13 +1087,13 @@ namespace ts { getCommonSourceDirectory: program.getCommonSourceDirectory, getCompilerOptions: program.getCompilerOptions, getCurrentDirectory: () => currentDirectory, - getNewLine: () => host!.getNewLine(), + getNewLine: () => host.getNewLine(), getSourceFile: program.getSourceFile, getSourceFileByPath: program.getSourceFileByPath, getSourceFiles: program.getSourceFiles, isSourceFileFromExternalLibrary, writeFile: writeFileCallback || ( - (fileName, data, writeByteOrderMark, onError, sourceFiles) => host!.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles)), + (fileName, data, writeByteOrderMark, onError, sourceFiles) => host.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles)), isEmitBlocked, }; } @@ -1114,7 +1113,7 @@ namespace ts { // If '--lib' is not specified, include default library file according to '--target' // otherwise, using options specified in '--lib' instead of '--target' default library file - const equalityComparer = host!.useCaseSensitiveFileNames() ? equateStringsCaseSensitive : equateStringsCaseInsensitive; + const equalityComparer = host.useCaseSensitiveFileNames() ? equateStringsCaseSensitive : equateStringsCaseInsensitive; if (!options.lib) { return equalityComparer(file.fileName, getDefaultLibraryFileName()); } @@ -1716,7 +1715,7 @@ namespace ts { refFile?: SourceFile): SourceFile | undefined { if (hasExtension(fileName)) { - if (!options.allowNonTsExtensions && !forEach(supportedExtensions, extension => fileExtensionIs(host!.getCanonicalFileName(fileName), extension))) { + if (!options.allowNonTsExtensions && !forEach(supportedExtensions, extension => fileExtensionIs(host.getCanonicalFileName(fileName), extension))) { if (fail) fail(Diagnostics.File_0_has_unsupported_extension_The_only_supported_extensions_are_1, fileName, "'" + supportedExtensions.join("', '") + "'"); return undefined; } @@ -1726,7 +1725,7 @@ namespace ts { if (!sourceFile) { fail(Diagnostics.File_0_not_found, fileName); } - else if (refFile && host!.getCanonicalFileName(fileName) === host!.getCanonicalFileName(refFile.fileName)) { + else if (refFile && host.getCanonicalFileName(fileName) === host.getCanonicalFileName(refFile.fileName)) { fail(Diagnostics.A_file_cannot_have_a_reference_to_itself); } } @@ -1821,7 +1820,7 @@ namespace ts { } // We haven't looked for this file, do so now and cache result - const file = host!.getSourceFile(fileName, options.target!, hostErrorMessage => { // TODO: GH#18217 + 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)); @@ -1856,7 +1855,7 @@ namespace ts { sourceFilesFoundSearchingNodeModules.set(path, currentNodeModulesDepth > 0); file.path = path; - if (host!.useCaseSensitiveFileNames()) { + 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); @@ -1931,7 +1930,7 @@ 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!); + 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, @@ -1969,7 +1968,7 @@ namespace ts { } function getCanonicalFileName(fileName: string): string { - return host!.getCanonicalFileName(fileName); + return host.getCanonicalFileName(fileName); } function processImportedModules(file: SourceFile) { @@ -2046,11 +2045,11 @@ namespace ts { function checkSourceFilesBelongToPath(sourceFiles: SourceFile[], rootDirectory: string): boolean { let allFilesBelongToPath = true; if (sourceFiles) { - const absoluteRootDirectoryPath = host!.getCanonicalFileName(getNormalizedAbsolutePath(rootDirectory, currentDirectory)); + const absoluteRootDirectoryPath = host.getCanonicalFileName(getNormalizedAbsolutePath(rootDirectory, currentDirectory)); for (const sourceFile of sourceFiles) { if (!sourceFile.isDeclarationFile) { - const absoluteSourceFilePath = host!.getCanonicalFileName(getNormalizedAbsolutePath(sourceFile.fileName, currentDirectory)); + const absoluteSourceFilePath = host.getCanonicalFileName(getNormalizedAbsolutePath(sourceFile.fileName, currentDirectory)); if (absoluteSourceFilePath.indexOf(absoluteRootDirectoryPath) !== 0) { programDiagnostics.add(createCompilerDiagnostic(Diagnostics.File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files, sourceFile.fileName, options.rootDir)); allFilesBelongToPath = false; @@ -2274,7 +2273,7 @@ namespace ts { blockEmittingOfFile(emitFileName, createCompilerDiagnosticFromMessageChain(chain)); } - const emitFileKey = !host!.useCaseSensitiveFileNames() ? emitFilePath.toLocaleLowerCase() : emitFilePath; + const emitFileKey = !host.useCaseSensitiveFileNames() ? emitFilePath.toLocaleLowerCase() : emitFilePath; // Report error if multiple files write into same file if (emitFilesSeen.has(emitFileKey)) { // Already seen the same emit file - report error @@ -2292,8 +2291,8 @@ namespace ts { const pathsSyntax = getOptionPathsSyntax(); for (const pathProp of pathsSyntax) { if (isObjectLiteralExpression(pathProp.initializer)) { - for (const keyProps of getPropertyAssignment(pathProp.initializer as ObjectLiteralExpression, key)) { - const initializer = keyProps.initializer!; + for (const keyProps of getPropertyAssignment(pathProp.initializer, key)) { + 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; @@ -2313,7 +2312,7 @@ namespace ts { for (const pathProp of pathsSyntax) { if (isObjectLiteralExpression(pathProp.initializer) && createOptionDiagnosticInObjectLiteralSyntax( - pathProp.initializer as ObjectLiteralExpression, onKey, key, /*key2*/ undefined, + pathProp.initializer, onKey, key, /*key2*/ undefined, message, arg0)) { needCompilerDiagnostic = false; } @@ -2355,7 +2354,7 @@ namespace ts { if (options.configFile && options.configFile.jsonObject) { for (const prop of getPropertyAssignment(options.configFile.jsonObject, "compilerOptions")) { if (isObjectLiteralExpression(prop.initializer)) { - _compilerOptionsObjectLiteralSyntax = prop.initializer as ObjectLiteralExpression; + _compilerOptionsObjectLiteralSyntax = prop.initializer; break; } } @@ -2396,7 +2395,7 @@ namespace ts { // If --outDir, check if file is in that directory if (options.outDir) { - return containsPath(options.outDir, filePath, currentDirectory, !host!.useCaseSensitiveFileNames()); + return containsPath(options.outDir, filePath, currentDirectory, !host.useCaseSensitiveFileNames()); } if (fileExtensionIsOneOf(filePath, supportedJavascriptExtensions) || fileExtensionIs(filePath, Extension.Dts)) { @@ -2409,7 +2408,7 @@ namespace ts { } function isSameFile(file1: string, file2: string) { - return comparePaths(file1, file2, currentDirectory, !host!.useCaseSensitiveFileNames()) === Comparison.EqualTo; + return comparePaths(file1, file2, currentDirectory, !host.useCaseSensitiveFileNames()) === Comparison.EqualTo; } } From 3c0dc90f23f0d55b775b4b317d4cc198ad81f0eb Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 24 Apr 2018 23:18:45 -0700 Subject: [PATCH 26/42] Remove few more unused assertions --- src/services/codefixes/convertToEs6Module.ts | 2 +- src/services/refactors/generateGetAccessorAndSetAccessor.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/codefixes/convertToEs6Module.ts b/src/services/codefixes/convertToEs6Module.ts index 45f56e23284b5..32aacb30a602a 100644 --- a/src/services/codefixes/convertToEs6Module.ts +++ b/src/services/codefixes/convertToEs6Module.ts @@ -222,7 +222,7 @@ namespace ts.codefix { case SyntaxKind.SpreadAssignment: return undefined; case SyntaxKind.PropertyAssignment: - return !isIdentifier(prop.name) ? undefined : convertExportsDotXEquals_replaceNode(prop.name.text, prop.initializer!); // TODO: GH#18217 + return !isIdentifier(prop.name) ? undefined : convertExportsDotXEquals_replaceNode(prop.name.text, prop.initializer); case SyntaxKind.MethodDeclaration: return !isIdentifier(prop.name) ? undefined : functionExpressionToDeclaration(prop.name.text, [createToken(SyntaxKind.ExportKeyword)], prop); default: diff --git a/src/services/refactors/generateGetAccessorAndSetAccessor.ts b/src/services/refactors/generateGetAccessorAndSetAccessor.ts index a7873157cb09b..47378721fd0ab 100644 --- a/src/services/refactors/generateGetAccessorAndSetAccessor.ts +++ b/src/services/refactors/generateGetAccessorAndSetAccessor.ts @@ -178,7 +178,7 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor { } function updatePropertyAssignmentDeclaration (changeTracker: textChanges.ChangeTracker, file: SourceFile, declaration: PropertyAssignment, fieldName: AcceptedNameType) { - const assignment = updatePropertyAssignment(declaration, fieldName, declaration.initializer!); // TODO: GH#18217 + const assignment = updatePropertyAssignment(declaration, fieldName, declaration.initializer); changeTracker.replacePropertyAssignment(file, declaration, assignment); } From 334b6d8d0d752cc8dace46b2b253ac8a3e4c89ed Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 25 Apr 2018 08:46:06 -0700 Subject: [PATCH 27/42] Update baselines --- .../reference/api/tsserverlibrary.d.ts | 70 +++++++++---------- tests/baselines/reference/api/typescript.d.ts | 64 ++++++++--------- 2 files changed, 67 insertions(+), 67 deletions(-) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index add6fcc6ea61e..c1aea56e6d1ce 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -536,7 +536,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 { @@ -602,7 +602,7 @@ declare namespace ts { kind: SyntaxKind.PropertyAssignment; name: PropertyName; questionToken?: QuestionToken; - initializer: Expression | undefined; + initializer: Expression; } interface ShorthandPropertyAssignment extends ObjectLiteralElement, JSDocContainer { parent: ObjectLiteralExpression; @@ -1019,7 +1019,7 @@ declare namespace ts { interface ElementAccessExpression extends MemberExpression { kind: SyntaxKind.ElementAccessExpression; expression: LeftHandSideExpression; - argumentExpression?: Expression; + argumentExpression: Expression; } interface SuperElementAccessExpression extends ElementAccessExpression { expression: SuperExpression; @@ -1262,7 +1262,7 @@ declare namespace ts { } interface ThrowStatement extends Statement { kind: SyntaxKind.ThrowStatement; - expression: Expression | undefined; + expression?: Expression; } interface TryStatement extends Statement { kind: SyntaxKind.TryStatement; @@ -1349,7 +1349,7 @@ declare namespace ts { type JSDocNamespaceBody = Identifier | JSDocNamespaceDeclaration; interface JSDocNamespaceDeclaration extends ModuleDeclaration { name: Identifier; - body: JSDocNamespaceBody | undefined; + body?: JSDocNamespaceBody; } interface ModuleBlock extends Node, Statement { kind: SyntaxKind.ModuleBlock; @@ -1490,14 +1490,14 @@ declare namespace ts { interface JSDoc extends Node { kind: SyntaxKind.JSDocComment; parent: HasJSDoc; - tags: NodeArray | undefined; - comment: string | undefined; + 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; @@ -1521,11 +1521,11 @@ declare namespace ts { } interface JSDocReturnTag extends JSDocTag { kind: SyntaxKind.JSDocReturnTag; - typeExpression: JSDocTypeExpression | undefined; + typeExpression?: JSDocTypeExpression; } interface JSDocTypeTag extends JSDocTag { kind: SyntaxKind.JSDocTypeTag; - typeExpression: JSDocTypeExpression | undefined; + typeExpression?: JSDocTypeExpression; } interface JSDocTypedefTag extends JSDocTag, NamedDeclaration { parent: JSDoc; @@ -1617,7 +1617,7 @@ declare namespace ts { } interface AmdDependency { path: string; - name: string | undefined; + name?: string; } interface SourceFile extends Declaration { kind: SyntaxKind.SourceFile; @@ -1626,7 +1626,7 @@ declare namespace ts { fileName: string; text: string; amdDependencies: ReadonlyArray; - moduleName: string | undefined; + moduleName?: string; referencedFiles: ReadonlyArray; typeReferenceDirectives: ReadonlyArray; languageVariant: LanguageVariant; @@ -1748,7 +1748,7 @@ declare namespace ts { emitSkipped: boolean; /** Contains declaration emit diagnostics */ diagnostics: ReadonlyArray; - emittedFiles: string[]; + emittedFiles?: string[]; } interface TypeChecker { getTypeOfSymbolAtLocation(symbol: Symbol, node: Node): Type; @@ -2172,8 +2172,8 @@ declare namespace ts { declaredProperties: Symbol[]; declaredCallSignatures: Signature[]; declaredConstructSignatures: Signature[]; - declaredStringIndexInfo: IndexInfo | undefined; - declaredNumberIndexInfo: IndexInfo | undefined; + declaredStringIndexInfo?: IndexInfo; + declaredNumberIndexInfo?: IndexInfo; } /** * Type references (ObjectFlags.Reference). When a class or interface has type parameters or @@ -2223,11 +2223,11 @@ declare namespace ts { trueType: Type; falseType: Type; isDistributive: boolean; - inferTypeParameters: TypeParameter[] | undefined; + inferTypeParameters?: TypeParameter[]; outerTypeParameters?: TypeParameter[]; instantiations?: Map; - aliasSymbol: Symbol | undefined; - aliasTypeArguments: Type[] | undefined; + aliasSymbol?: Symbol; + aliasTypeArguments?: Type[]; } interface ConditionalType extends InstantiableType { root: ConditionalRoot; @@ -3523,7 +3523,7 @@ declare namespace ts { function updateObjectLiteral(node: ObjectLiteralExpression, properties: ReadonlyArray): ObjectLiteralExpression; 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 | undefined): ElementAccessExpression; + 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 | undefined): CallExpression; function updateCall(node: CallExpression, expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray): CallExpression; @@ -3931,7 +3931,7 @@ declare namespace ts { * @param configFileParsingDiagnostics - error during config file parsing * @returns A 'Program' object. */ - function createProgram(rootNames: ReadonlyArray, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray): Program; + function createProgram(rootNames: ReadonlyArray, options: CompilerOptions, compilerHost?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray): Program; } declare namespace ts { interface EmitOutput { @@ -4342,7 +4342,7 @@ declare namespace ts { referencedFiles: FileReference[]; typeReferenceDirectives: FileReference[]; importedFiles: FileReference[]; - ambientExternalModules: string[] | undefined; + ambientExternalModules?: string[]; isLibFile: boolean; } interface HostCancellationToken { @@ -4554,7 +4554,7 @@ declare namespace ts { } interface CombinedCodeActions { changes: ReadonlyArray; - commands: ReadonlyArray | undefined; + commands?: ReadonlyArray; } type CodeActionCommand = InstallPackageAction; interface InstallPackageAction { @@ -4604,8 +4604,8 @@ declare namespace ts { */ interface RefactorEditInfo { edits: FileTextChanges[]; - renameFilename: string | undefined; - renameLocation: number | undefined; + renameFilename?: string; + renameLocation?: number; commands?: CodeActionCommand[]; } interface TextInsertion { @@ -4722,7 +4722,7 @@ declare namespace ts { containerName: string; } interface DefinitionInfoAndBoundSpan { - definitions: ReadonlyArray | undefined; + definitions?: ReadonlyArray; textSpan: TextSpan; } interface ReferencedSymbolDefinitionInfo extends DefinitionInfo { @@ -4768,13 +4768,13 @@ declare namespace ts { kind: ScriptElementKind; kindModifiers: string; textSpan: TextSpan; - displayParts: SymbolDisplayPart[] | undefined; - documentation: SymbolDisplayPart[] | undefined; - tags: JSDocTagInfo[] | undefined; + displayParts?: SymbolDisplayPart[]; + documentation?: SymbolDisplayPart[]; + tags?: JSDocTagInfo[]; } interface RenameInfo { canRename: boolean; - localizedErrorMessage: string | undefined; + localizedErrorMessage?: string; displayName: string; fullDisplayName: string; kind: ScriptElementKind; @@ -4826,7 +4826,7 @@ declare namespace ts { interface CompletionEntry { name: string; kind: ScriptElementKind; - kindModifiers: string | undefined; + kindModifiers?: string; sortText: string; insertText?: string; /** @@ -4844,8 +4844,8 @@ declare namespace ts { kind: ScriptElementKind; kindModifiers: string; displayParts: SymbolDisplayPart[]; - documentation: SymbolDisplayPart[] | undefined; - tags: JSDocTagInfo[] | undefined; + documentation?: SymbolDisplayPart[]; + tags?: JSDocTagInfo[]; codeActions?: CodeAction[]; source?: SymbolDisplayPart[]; } @@ -6717,7 +6717,7 @@ declare namespace ts.server.protocol { } interface CompletionEntryIdentifier { name: string; - source: string | undefined; + source?: string; } /** * Completion entry details request; value of command field is @@ -6814,11 +6814,11 @@ declare namespace ts.server.protocol { /** * Documentation strings for the symbol. */ - documentation: SymbolDisplayPart[] | undefined; + documentation?: SymbolDisplayPart[]; /** * JSDoc tags for the symbol. */ - tags: JSDocTagInfo[] | undefined; + tags?: JSDocTagInfo[]; /** * The associated code actions for this entry */ diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 539590b2af272..8a82c585bd9c1 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -536,7 +536,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 { @@ -602,7 +602,7 @@ declare namespace ts { kind: SyntaxKind.PropertyAssignment; name: PropertyName; questionToken?: QuestionToken; - initializer: Expression | undefined; + initializer: Expression; } interface ShorthandPropertyAssignment extends ObjectLiteralElement, JSDocContainer { parent: ObjectLiteralExpression; @@ -1019,7 +1019,7 @@ declare namespace ts { interface ElementAccessExpression extends MemberExpression { kind: SyntaxKind.ElementAccessExpression; expression: LeftHandSideExpression; - argumentExpression?: Expression; + argumentExpression: Expression; } interface SuperElementAccessExpression extends ElementAccessExpression { expression: SuperExpression; @@ -1262,7 +1262,7 @@ declare namespace ts { } interface ThrowStatement extends Statement { kind: SyntaxKind.ThrowStatement; - expression: Expression | undefined; + expression?: Expression; } interface TryStatement extends Statement { kind: SyntaxKind.TryStatement; @@ -1349,7 +1349,7 @@ declare namespace ts { type JSDocNamespaceBody = Identifier | JSDocNamespaceDeclaration; interface JSDocNamespaceDeclaration extends ModuleDeclaration { name: Identifier; - body: JSDocNamespaceBody | undefined; + body?: JSDocNamespaceBody; } interface ModuleBlock extends Node, Statement { kind: SyntaxKind.ModuleBlock; @@ -1490,14 +1490,14 @@ declare namespace ts { interface JSDoc extends Node { kind: SyntaxKind.JSDocComment; parent: HasJSDoc; - tags: NodeArray | undefined; - comment: string | undefined; + 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; @@ -1521,11 +1521,11 @@ declare namespace ts { } interface JSDocReturnTag extends JSDocTag { kind: SyntaxKind.JSDocReturnTag; - typeExpression: JSDocTypeExpression | undefined; + typeExpression?: JSDocTypeExpression; } interface JSDocTypeTag extends JSDocTag { kind: SyntaxKind.JSDocTypeTag; - typeExpression: JSDocTypeExpression | undefined; + typeExpression?: JSDocTypeExpression; } interface JSDocTypedefTag extends JSDocTag, NamedDeclaration { parent: JSDoc; @@ -1617,7 +1617,7 @@ declare namespace ts { } interface AmdDependency { path: string; - name: string | undefined; + name?: string; } interface SourceFile extends Declaration { kind: SyntaxKind.SourceFile; @@ -1626,7 +1626,7 @@ declare namespace ts { fileName: string; text: string; amdDependencies: ReadonlyArray; - moduleName: string | undefined; + moduleName?: string; referencedFiles: ReadonlyArray; typeReferenceDirectives: ReadonlyArray; languageVariant: LanguageVariant; @@ -1748,7 +1748,7 @@ declare namespace ts { emitSkipped: boolean; /** Contains declaration emit diagnostics */ diagnostics: ReadonlyArray; - emittedFiles: string[]; + emittedFiles?: string[]; } interface TypeChecker { getTypeOfSymbolAtLocation(symbol: Symbol, node: Node): Type; @@ -2172,8 +2172,8 @@ declare namespace ts { declaredProperties: Symbol[]; declaredCallSignatures: Signature[]; declaredConstructSignatures: Signature[]; - declaredStringIndexInfo: IndexInfo | undefined; - declaredNumberIndexInfo: IndexInfo | undefined; + declaredStringIndexInfo?: IndexInfo; + declaredNumberIndexInfo?: IndexInfo; } /** * Type references (ObjectFlags.Reference). When a class or interface has type parameters or @@ -2223,11 +2223,11 @@ declare namespace ts { trueType: Type; falseType: Type; isDistributive: boolean; - inferTypeParameters: TypeParameter[] | undefined; + inferTypeParameters?: TypeParameter[]; outerTypeParameters?: TypeParameter[]; instantiations?: Map; - aliasSymbol: Symbol | undefined; - aliasTypeArguments: Type[] | undefined; + aliasSymbol?: Symbol; + aliasTypeArguments?: Type[]; } interface ConditionalType extends InstantiableType { root: ConditionalRoot; @@ -3523,7 +3523,7 @@ declare namespace ts { function updateObjectLiteral(node: ObjectLiteralExpression, properties: ReadonlyArray): ObjectLiteralExpression; 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 | undefined): ElementAccessExpression; + 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 | undefined): CallExpression; function updateCall(node: CallExpression, expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray): CallExpression; @@ -3931,7 +3931,7 @@ declare namespace ts { * @param configFileParsingDiagnostics - error during config file parsing * @returns A 'Program' object. */ - function createProgram(rootNames: ReadonlyArray, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray): Program; + function createProgram(rootNames: ReadonlyArray, options: CompilerOptions, compilerHost?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray): Program; } declare namespace ts { interface EmitOutput { @@ -4342,7 +4342,7 @@ declare namespace ts { referencedFiles: FileReference[]; typeReferenceDirectives: FileReference[]; importedFiles: FileReference[]; - ambientExternalModules: string[] | undefined; + ambientExternalModules?: string[]; isLibFile: boolean; } interface HostCancellationToken { @@ -4554,7 +4554,7 @@ declare namespace ts { } interface CombinedCodeActions { changes: ReadonlyArray; - commands: ReadonlyArray | undefined; + commands?: ReadonlyArray; } type CodeActionCommand = InstallPackageAction; interface InstallPackageAction { @@ -4604,8 +4604,8 @@ declare namespace ts { */ interface RefactorEditInfo { edits: FileTextChanges[]; - renameFilename: string | undefined; - renameLocation: number | undefined; + renameFilename?: string; + renameLocation?: number; commands?: CodeActionCommand[]; } interface TextInsertion { @@ -4722,7 +4722,7 @@ declare namespace ts { containerName: string; } interface DefinitionInfoAndBoundSpan { - definitions: ReadonlyArray | undefined; + definitions?: ReadonlyArray; textSpan: TextSpan; } interface ReferencedSymbolDefinitionInfo extends DefinitionInfo { @@ -4768,13 +4768,13 @@ declare namespace ts { kind: ScriptElementKind; kindModifiers: string; textSpan: TextSpan; - displayParts: SymbolDisplayPart[] | undefined; - documentation: SymbolDisplayPart[] | undefined; - tags: JSDocTagInfo[] | undefined; + displayParts?: SymbolDisplayPart[]; + documentation?: SymbolDisplayPart[]; + tags?: JSDocTagInfo[]; } interface RenameInfo { canRename: boolean; - localizedErrorMessage: string | undefined; + localizedErrorMessage?: string; displayName: string; fullDisplayName: string; kind: ScriptElementKind; @@ -4826,7 +4826,7 @@ declare namespace ts { interface CompletionEntry { name: string; kind: ScriptElementKind; - kindModifiers: string | undefined; + kindModifiers?: string; sortText: string; insertText?: string; /** @@ -4844,8 +4844,8 @@ declare namespace ts { kind: ScriptElementKind; kindModifiers: string; displayParts: SymbolDisplayPart[]; - documentation: SymbolDisplayPart[] | undefined; - tags: JSDocTagInfo[] | undefined; + documentation?: SymbolDisplayPart[]; + tags?: JSDocTagInfo[]; codeActions?: CodeAction[]; source?: SymbolDisplayPart[]; } From 11acd0b5045b0befecdc765e1f0b26c56958e144 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 25 Apr 2018 08:55:40 -0700 Subject: [PATCH 28/42] Use parameter defaults --- src/compiler/program.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 7368327de3600..95f57c5fda201 100755 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -491,7 +491,7 @@ namespace ts { * @param configFileParsingDiagnostics - error during config file parsing * @returns A 'Program' object. */ - export function createProgram(rootNames: ReadonlyArray, options: CompilerOptions, compilerHost?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray): Program { + export function createProgram(rootNames: ReadonlyArray, options: CompilerOptions, host = createCompilerHost(options), oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray): Program { let program: Program; let files: SourceFile[] = []; let commonSourceDirectory: string; @@ -525,8 +525,6 @@ namespace ts { performance.mark("beforeProgram"); - const host = compilerHost || createCompilerHost(options); - let skipDefaultLib = options.noLib; const getDefaultLibraryFileName = memoize(() => host.getDefaultLibFileName(options)); const defaultLibraryPath = host.getDefaultLibLocation ? host.getDefaultLibLocation() : getDirectoryPath(getDefaultLibraryFileName()); From 1f63084fe2a192634ca3ef9a0d6e78e5b7992b1f Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 25 Apr 2018 09:13:20 -0700 Subject: [PATCH 29/42] Update baselines --- tests/baselines/reference/api/tsserverlibrary.d.ts | 2 +- tests/baselines/reference/api/typescript.d.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index c1aea56e6d1ce..94dde50bf7f20 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -3931,7 +3931,7 @@ declare namespace ts { * @param configFileParsingDiagnostics - error during config file parsing * @returns A 'Program' object. */ - function createProgram(rootNames: ReadonlyArray, options: CompilerOptions, compilerHost?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray): Program; + function createProgram(rootNames: ReadonlyArray, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray): Program; } declare namespace ts { interface EmitOutput { diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 8a82c585bd9c1..49f5bff1da72d 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -3931,7 +3931,7 @@ declare namespace ts { * @param configFileParsingDiagnostics - error during config file parsing * @returns A 'Program' object. */ - function createProgram(rootNames: ReadonlyArray, options: CompilerOptions, compilerHost?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray): Program; + function createProgram(rootNames: ReadonlyArray, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray): Program; } declare namespace ts { interface EmitOutput { From 8d562daf706096321a7a7e6c7abd926764de74c1 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Wed, 25 Apr 2018 10:18:42 -0700 Subject: [PATCH 30/42] Fix lint --- src/services/codefixes/importFixes.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index 21a6c5d3dd550..f7b0ff952f4fa 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -145,7 +145,7 @@ namespace ts.codefix { if (namespace) { 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 as Identifier)); + useExisting.push(getCodeActionForUseExistingNamespaceImport(namespace.text, context, context.symbolToken)); } } } From e958ece66e6fe5f764afe421513a4158e53d547e Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Wed, 25 Apr 2018 10:34:18 -0700 Subject: [PATCH 31/42] Make Symbol#valueDeclaration and Symbol#declarations non-optional to reduce assertions --- src/compiler/binder.ts | 4 +- src/compiler/checker.ts | 177 +++++++++--------- src/compiler/core.ts | 4 +- src/compiler/types.ts | 4 +- src/compiler/utilities.ts | 8 +- src/harness/fourslash.ts | 2 +- .../codefixes/convertFunctionToEs6Class.ts | 2 +- .../fixClassIncorrectlyImplementsInterface.ts | 2 +- src/services/codefixes/importFixes.ts | 4 +- src/services/completions.ts | 6 +- src/services/findAllReferences.ts | 18 +- src/services/goToDefinition.ts | 8 +- src/services/importTracker.ts | 8 +- src/services/services.ts | 3 +- src/services/symbolDisplay.ts | 12 +- .../reference/api/tsserverlibrary.d.ts | 4 +- tests/baselines/reference/api/typescript.d.ts | 4 +- 17 files changed, 135 insertions(+), 135 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 5d2f79807d9fb..ffbc952e9e7b3 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -231,7 +231,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 @@ -2551,7 +2551,7 @@ namespace ts { if (node.name) { node.name.parent = node; } - file.bindDiagnostics.push(createDiagnosticForNode(symbolExport.declarations![0], Diagnostics.Duplicate_identifier_0, symbolName(prototypeSymbol))); + file.bindDiagnostics.push(createDiagnosticForNode(symbolExport.declarations[0], Diagnostics.Duplicate_identifier_0, symbolName(prototypeSymbol))); } symbol.exports!.set(prototypeSymbol.escapedName, prototypeSymbol); prototypeSymbol.parent = symbol; diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index aed8cd545121f..62f1319197a9c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -926,7 +926,7 @@ namespace ts { recordMergedSymbol(target, source); } else if (target.flags & SymbolFlags.NamespaceModule) { - error(getNameOfDeclaration(source.declarations![0]), Diagnostics.Cannot_augment_module_0_with_value_exports_because_it_resolves_to_a_non_module_entity, symbolToString(target)); + error(getNameOfDeclaration(source.declarations[0]), Diagnostics.Cannot_augment_module_0_with_value_exports_because_it_resolves_to_a_non_module_entity, symbolToString(target)); } else { const message = target.flags & SymbolFlags.Enum || source.flags & SymbolFlags.Enum @@ -972,11 +972,11 @@ namespace ts { function mergeModuleAugmentation(moduleName: StringLiteral | Identifier): void { const moduleAugmentation = moduleName.parent; - if (moduleAugmentation.symbol!.declarations![0] !== moduleAugmentation) { + if (moduleAugmentation.symbol!.declarations[0] !== moduleAugmentation) { // this is a combined symbol for multiple augmentations within the same file. // its symbol already has accumulated information for all declarations // so we need to add it just once - do the work only for first declaration - Debug.assert(moduleAugmentation.symbol!.declarations!.length > 1); + Debug.assert(moduleAugmentation.symbol!.declarations.length > 1); return; } @@ -1559,7 +1559,7 @@ namespace ts { } function isTypeParameterSymbolDeclaredInContainer(symbol: Symbol, container: Node) { - for (const decl of symbol.declarations!) { + for (const decl of symbol.declarations) { const parent = isJSDocTemplateTag(decl.parent) ? getJSDocHost(decl.parent) : decl.parent; if (decl.kind === SyntaxKind.TypeParameter && parent === container) { return true; @@ -1739,7 +1739,7 @@ namespace ts { } function getDeclarationOfAliasSymbol(symbol: Symbol): Declaration | undefined { - return find(symbol.declarations!, isAliasSymbolDeclaration); + return find(symbol.declarations, isAliasSymbolDeclaration); } function getTargetOfImportEqualsDeclaration(node: ImportEqualsDeclaration, dontResolveAlias: boolean): Symbol | undefined { @@ -1803,7 +1803,7 @@ namespace ts { exportDefaultSymbol = resolveExportByName(moduleSymbol, InternalSymbolName.Default, dontResolveAlias); } - const file = find(moduleSymbol.declarations!, isSourceFile); + const file = find(moduleSymbol.declarations, isSourceFile); const hasSyntheticDefault = canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias); if (!exportDefaultSymbol && !hasSyntheticDefault) { error(node.name, Diagnostics.Module_0_has_no_default_export, symbolToString(moduleSymbol)); @@ -2093,7 +2093,7 @@ namespace ts { return namespace; } if (isInJavaScriptFile(name)) { - const initializer = getDeclaredJavascriptInitializer(namespace.valueDeclaration!) || getAssignedJavascriptInitializer(namespace.valueDeclaration!); + const initializer = getDeclaredJavascriptInitializer(namespace.valueDeclaration) || getAssignedJavascriptInitializer(namespace.valueDeclaration); if (initializer) { namespace = getSymbolOfNode(initializer)!; } @@ -2418,7 +2418,7 @@ namespace ts { if (exportStars) { const nestedSymbols = createSymbolTable(); const lookupTable = createMap() as ExportCollisionTrackerTable; - for (const node of exportStars.declarations!) { + for (const node of exportStars.declarations) { const resolvedModule = resolveExternalModuleName(node, (node as ExportDeclaration).moduleSpecifier!); const exportedSymbols = visit(resolvedModule); extendExportSymbols( @@ -3163,7 +3163,7 @@ namespace ts { return symbolToTypeNode(symbol, context, isInstanceType); } // Always use 'typeof T' for type of class, enum, and module objects - else if (symbol.flags & SymbolFlags.Class && !getBaseTypeVariableOfClass(symbol) && !(symbol.valueDeclaration!.kind === SyntaxKind.ClassExpression && context.flags! & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral) || + else if (symbol.flags & SymbolFlags.Class && !getBaseTypeVariableOfClass(symbol) && !(symbol.valueDeclaration.kind === SyntaxKind.ClassExpression && context.flags! & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral) || symbol.flags & (SymbolFlags.Enum | SymbolFlags.ValueModule) || shouldWriteTypeOfFunctionSymbol()) { return symbolToTypeNode(symbol, context, SymbolFlags.Value); @@ -3284,7 +3284,7 @@ namespace ts { } else if (context.flags! & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral && type.symbol!.valueDeclaration && - isClassLike(type.symbol!.valueDeclaration!) && + isClassLike(type.symbol!.valueDeclaration) && !isValueSymbolAccessible(type.symbol!, context.enclosingDeclaration!) ) { return createAnonymousTypeNode(type); @@ -3403,7 +3403,7 @@ namespace ts { const saveEnclosingDeclaration = context.enclosingDeclaration; context.enclosingDeclaration = undefined; if (getCheckFlags(propertySymbol) & CheckFlags.Late) { - const decl = first(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); @@ -3824,7 +3824,7 @@ namespace ts { 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); } @@ -4008,7 +4008,7 @@ namespace ts { } let result: Node[] | undefined; if (exportSymbol) { - buildVisibleNodeList(exportSymbol.declarations!); + buildVisibleNodeList(exportSymbol.declarations); } return result; @@ -4030,7 +4030,7 @@ namespace ts { const importSymbol = resolveName(declaration, firstIdentifier.escapedText, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace, undefined, undefined, /*isUse*/ false); if (importSymbol) { - buildVisibleNodeList(importSymbol.declarations!); + buildVisibleNodeList(importSymbol.declarations); } } }); @@ -4400,7 +4400,7 @@ namespace ts { function getWidenedTypeFromJSSpecialPropertyDeclarations(symbol: Symbol) { // function/class/{} assignments are fresh declarations, not property assignments, so only add prototype assignments - const specialDeclaration = getAssignedJavascriptInitializer(symbol.valueDeclaration!); + const specialDeclaration = getAssignedJavascriptInitializer(symbol.valueDeclaration); if (specialDeclaration) { return getWidenedLiteralType(checkExpressionCached(specialDeclaration)); } @@ -4409,7 +4409,7 @@ namespace ts { let definedInConstructor = false; let definedInMethod = false; let jsDocType: Type | undefined; - for (const declaration of symbol.declarations!) { + for (const declaration of symbol.declarations) { let declarationInConstructor = false; const expression = declaration.kind === SyntaxKind.BinaryExpression ? declaration : declaration.kind === SyntaxKind.PropertyAccessExpression ? cast(declaration.parent, isBinaryExpression) : @@ -4499,7 +4499,7 @@ namespace ts { const widened = getWidenedType(addOptionality(type, definedInMethod && !definedInConstructor)); if (filterType(widened, t => !!(t.flags & ~TypeFlags.Nullable)) === neverType) { if (noImplicitAny) { - reportImplicitAnyError(symbol.valueDeclaration!, anyType); + reportImplicitAnyError(symbol.valueDeclaration, anyType); } return anyType; } @@ -4643,7 +4643,7 @@ namespace ts { return links.type = getTypeOfPrototypeProperty(symbol); } // Handle catch clause variables - const declaration = symbol.valueDeclaration!; + const declaration = symbol.valueDeclaration; if (isCatchClauseVariableDeclarationOrBindingElement(declaration)) { return links.type = anyType; } @@ -4808,8 +4808,8 @@ namespace ts { if (symbol.flags & SymbolFlags.Module && isShorthandAmbientModuleSymbol(symbol)) { links.type = anyType; } - else if (symbol.valueDeclaration!.kind === SyntaxKind.BinaryExpression || - symbol.valueDeclaration!.kind === SyntaxKind.PropertyAccessExpression && symbol.valueDeclaration!.parent.kind === SyntaxKind.BinaryExpression) { + else if (symbol.valueDeclaration.kind === SyntaxKind.BinaryExpression || + symbol.valueDeclaration.kind === SyntaxKind.PropertyAccessExpression && symbol.valueDeclaration.parent.kind === SyntaxKind.BinaryExpression) { links.type = getWidenedTypeFromJSSpecialPropertyDeclarations(symbol); } else { @@ -4993,7 +4993,7 @@ namespace ts { // The outer type parameters are those defined by enclosing generic classes, methods, or functions. function getOuterTypeParametersOfClassOrInterface(symbol: Symbol): TypeParameter[] | undefined { - const declaration = symbol.flags & SymbolFlags.Class ? symbol.valueDeclaration! : getDeclarationOfKind(symbol, SyntaxKind.InterfaceDeclaration)!; + const declaration = symbol.flags & SymbolFlags.Class ? symbol.valueDeclaration : getDeclarationOfKind(symbol, SyntaxKind.InterfaceDeclaration)!; return getOuterTypeParameters(declaration); } @@ -5001,7 +5001,7 @@ namespace ts { // interface, or type alias. function getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol: Symbol): TypeParameter[] | undefined { let result: TypeParameter[] | undefined; - for (const node of symbol.declarations!) { + for (const node of symbol.declarations) { if (node.kind === SyntaxKind.InterfaceDeclaration || node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassExpression || node.kind === SyntaxKind.TypeAliasDeclaration) { const declaration = node; @@ -5205,7 +5205,7 @@ namespace ts { function resolveBaseTypesOfInterface(type: InterfaceType): void { type.resolvedBaseTypes = type.resolvedBaseTypes || emptyArray; - for (const declaration of type.symbol!.declarations!) { + for (const declaration of type.symbol!.declarations) { if (declaration.kind === SyntaxKind.InterfaceDeclaration && getInterfaceBaseTypeNodes(declaration)) { for (const node of getInterfaceBaseTypeNodes(declaration)!) { const baseType = getTypeFromTypeNode(node); @@ -5240,7 +5240,7 @@ namespace ts { * and if none of the base interfaces have a "this" type. */ function isThislessInterface(symbol: Symbol): boolean { - for (const declaration of symbol.declarations!) { + for (const declaration of symbol.declarations) { if (declaration.kind === SyntaxKind.InterfaceDeclaration) { if (declaration.flags & NodeFlags.ContainsThis) { return false; @@ -5300,7 +5300,7 @@ namespace ts { return unknownType; } - const declaration = find(symbol.declarations!, d => + const declaration = find(symbol.declarations, d => d.kind === SyntaxKind.JSDocTypedefTag || d.kind === SyntaxKind.TypeAliasDeclaration); const typeNode = declaration.kind === SyntaxKind.JSDocTypedefTag ? declaration.typeExpression : declaration.type; // If typeNode is missing, we will error in checkJSDocTypedefTag. @@ -5362,7 +5362,7 @@ namespace ts { return links.enumKind; } let hasNonLiteralMember = false; - for (const declaration of symbol.declarations!) { + for (const declaration of symbol.declarations) { if (declaration.kind === SyntaxKind.EnumDeclaration) { for (const member of (declaration).members) { if (member.initializer && member.initializer.kind === SyntaxKind.StringLiteral) { @@ -5389,7 +5389,7 @@ namespace ts { if (getEnumKind(symbol) === EnumKind.Literal) { enumCount++; const memberTypeList: Type[] = []; - for (const declaration of symbol.declarations!) { + 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)); // TODO: GH#18217 @@ -5649,8 +5649,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; } } @@ -5742,7 +5741,7 @@ namespace ts { // fill in any as-yet-unresolved late-bound members. const lateSymbols = createSymbolTable(); - for (const decl of symbol.declarations!) { + for (const decl of symbol.declarations) { const members = getMembersOfDeclaration(decl); if (members) { for (const member of members) { @@ -6671,7 +6670,7 @@ namespace ts { } const result = createSymbol(SymbolFlags.Property | commonFlags, name, syntheticFlag | checkFlags); result.containingType = containingType; - result.declarations = declarations; + result.declarations = declarations!; result.nameType = nameType; result.type = isUnion ? getUnionType(propTypes) : getIntersectionType(propTypes); return result; @@ -7077,15 +7076,15 @@ namespace ts { 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]; + for (let i = 0; i < symbol.declarations.length; i++) { + const decl = symbol.declarations[i]; 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 // precedes the implementation node (i.e. has the same parent and ends where the implementation starts). if (i > 0 && (node as FunctionLikeDeclaration).body) { - const previous = symbol.declarations![i - 1]; + const previous = symbol.declarations[i - 1]; if (node.parent === previous.parent && node.kind === previous.kind && node.pos === previous.end) { continue; } @@ -7268,7 +7267,7 @@ namespace ts { const syntaxKind = kind === IndexKind.Number ? SyntaxKind.NumberKeyword : SyntaxKind.StringKeyword; const indexSymbol = getIndexSymbol(symbol); if (indexSymbol) { - for (const decl of indexSymbol.declarations!) { + for (const decl of indexSymbol.declarations) { const node = cast(decl, isIndexSignatureDeclaration); if (node.parameters.length === 1) { const parameter = node.parameters[0]; @@ -7302,7 +7301,7 @@ namespace ts { function getInferredTypeParameterConstraint(typeParameter: TypeParameter) { let inferences: Type[] | undefined; if (typeParameter.symbol) { - for (const declaration of typeParameter.symbol.declarations!) { + for (const declaration of typeParameter.symbol.declarations) { // When an 'infer T' declaration is immediately contained in a type reference node // (such as 'Foo'), T's constraint is inferred from the constraint of the // corresponding type parameter in 'Foo'. When multiple 'infer T' declarations are @@ -7567,7 +7566,7 @@ namespace ts { if (symbol.flags & SymbolFlags.Function && isJSDocTypeReference(node) && - (symbol.members || getJSDocClassTag(symbol.valueDeclaration!))) { + (symbol.members || getJSDocClassTag(symbol.valueDeclaration))) { return getInferredClassType(symbol); } } @@ -7710,7 +7709,7 @@ namespace ts { function getTypeOfGlobalSymbol(symbol: Symbol | undefined, arity: number): ObjectType { function getTypeDeclaration(symbol: Symbol): Declaration | undefined { - const declarations = symbol.declarations!; + const declarations = symbol.declarations; for (const declaration of declarations) { switch (declaration.kind) { case SyntaxKind.ClassDeclaration: @@ -8268,7 +8267,7 @@ namespace ts { if (!(getDeclarationModifierFlagsFromSymbol(prop) & ModifierFlags.NonPublicAccessibilityModifier)) { let type = getLateBoundSymbol(prop).nameType; if (!type && !isKnownSymbol(prop)) { - const name = getNameOfDeclaration(prop.valueDeclaration!); + const name = getNameOfDeclaration(prop.valueDeclaration); type = name && isNumericLiteral(name) ? getLiteralType(+name.text) : name && name.kind === SyntaxKind.ComputedPropertyName && isNumericLiteral(name.expression) ? getLiteralType(+name.expression.text) : getLiteralType(symbolName(prop)); @@ -8904,7 +8903,7 @@ namespace ts { } function isClassMethod(prop: Symbol) { - return prop.flags & SymbolFlags.Method && find(prop.declarations!, decl => isClassLike(decl.parent)); + return prop.flags & SymbolFlags.Method && find(prop.declarations, decl => isClassLike(decl.parent)); } function createLiteralType(flags: TypeFlags, value: string | number, symbol: Symbol | undefined) { @@ -9264,7 +9263,7 @@ namespace ts { // parameters that are in scope (and therefore potentially referenced). For type literals that // aren't the right hand side of a generic type alias declaration we optimize by reducing the // set of type parameters to those that are possibly referenced in the literal. - const declaration = symbol.declarations![0]; + const declaration = symbol.declarations[0]; let outerTypeParameters = getOuterTypeParameters(declaration, /*includeThisTypes*/ true); if (isJavaScriptConstructor(declaration)) { const templateTagParameters = getTypeParametersFromDeclaration(declaration as DeclarationWithTypeParameters); @@ -10244,7 +10243,7 @@ namespace ts { } else { // use the property's value declaration if the property is assigned inside the literal itself - const objectLiteralDeclaration = source.symbol && firstOrUndefined(source.symbol.declarations!); + const objectLiteralDeclaration = source.symbol && firstOrUndefined(source.symbol.declarations); let suggestion; if (prop.valueDeclaration && findAncestor(prop.valueDeclaration, d => d === objectLiteralDeclaration)) { const propDeclaration = prop.valueDeclaration as ObjectLiteralElementLike; @@ -13850,7 +13849,7 @@ namespace ts { // Check if a parameter is assigned anywhere within its declaring function. function isParameterAssigned(symbol: Symbol) { - const func = getRootDeclaration(symbol.valueDeclaration!).parent; + const func = getRootDeclaration(symbol.valueDeclaration).parent; const links = getNodeLinks(func); if (!(links.flags! & NodeCheckFlags.AssignmentsMarked)) { links.flags! |= NodeCheckFlags.AssignmentsMarked; @@ -13958,13 +13957,13 @@ 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 // must instead be rewritten to point to a temporary variable to avoid issues with the double-bind // behavior of class names in ES6. - if (declaration!.kind === SyntaxKind.ClassDeclaration + if (declaration.kind === SyntaxKind.ClassDeclaration && nodeIsDecorated(declaration as ClassDeclaration)) { let container = getContainingClass(node); while (container !== undefined) { @@ -13977,7 +13976,7 @@ namespace ts { container = getContainingClass(container); } } - else if (declaration!.kind === SyntaxKind.ClassExpression) { + else if (declaration.kind === SyntaxKind.ClassExpression) { // When we emit a class expression with static members that contain a reference // to the constructor in the initializer, we will need to substitute that // binding with an alias as the class name is not in scope. @@ -14023,7 +14022,7 @@ namespace ts { } } else if (isAlias) { - declaration = find(symbol.declarations!, isSomeImportDeclaration); + declaration = find(symbol.declarations, isSomeImportDeclaration); } else { return type; @@ -14089,7 +14088,7 @@ namespace ts { function checkNestedBlockScopedBinding(node: Identifier, symbol: Symbol): void { if (languageVersion >= ScriptTarget.ES2015 || (symbol.flags & (SymbolFlags.BlockScopedVariable | SymbolFlags.Class)) === 0 || - symbol.valueDeclaration!.parent.kind === SyntaxKind.CatchClause) { + symbol.valueDeclaration.parent.kind === SyntaxKind.CatchClause) { return; } @@ -14098,7 +14097,7 @@ namespace ts { // 2. walk from the declaration up to the boundary of lexical environment and check // if there is an iteration statement in between declaration and boundary (is binding/class declared inside iteration statement) - const container = getEnclosingBlockScopeContainer(symbol.valueDeclaration!); + const container = getEnclosingBlockScopeContainer(symbol.valueDeclaration); const usedInFunction = isInsideFunction(node.parent, container); let current = container; @@ -14122,15 +14121,15 @@ namespace ts { if (container.kind === SyntaxKind.ForStatement && getAncestor(symbol.valueDeclaration, SyntaxKind.VariableDeclarationList)!.parent === container && isAssignedInBodyOfForStatement(node, container)) { - getNodeLinks(symbol.valueDeclaration!).flags! |= NodeCheckFlags.NeedsLoopOutParameter; + getNodeLinks(symbol.valueDeclaration).flags! |= NodeCheckFlags.NeedsLoopOutParameter; } // set 'declared inside loop' bit on the block-scoped binding - getNodeLinks(symbol.valueDeclaration!).flags! |= NodeCheckFlags.BlockScopedBindingInLoop; + getNodeLinks(symbol.valueDeclaration).flags! |= NodeCheckFlags.BlockScopedBindingInLoop; } if (usedInFunction) { - getNodeLinks(symbol.valueDeclaration!).flags! |= NodeCheckFlags.CapturedBlockScopedBinding; + getNodeLinks(symbol.valueDeclaration).flags! |= NodeCheckFlags.CapturedBlockScopedBinding; } } @@ -15967,7 +15966,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; @@ -16470,7 +16469,7 @@ namespace ts { return true; } if (isInJavaScriptFile(symbol.valueDeclaration)) { - const parent = symbol.valueDeclaration!.parent; + const parent = symbol.valueDeclaration.parent; return parent && isBinaryExpression(parent) && getSpecialPropertyAssignmentKind(parent) === SpecialPropertyAssignmentKind.PrototypeProperty; } @@ -18552,7 +18551,7 @@ namespace ts { } function getJavaScriptClassType(symbol: Symbol): Type | undefined { - const initializer = getDeclaredJavascriptInitializer(symbol.valueDeclaration!); + const initializer = getDeclaredJavascriptInitializer(symbol.valueDeclaration); if (initializer) { symbol = getSymbolOfNode(initializer)!; } @@ -18721,7 +18720,7 @@ namespace ts { if (allowSyntheticDefaultImports && type && type !== unknownType) { const synthType = type as SyntheticDefaultModuleType; if (!synthType.syntheticType) { - const file = find(originalSymbol.declarations!, isSourceFile); + const file = find(originalSymbol.declarations, isSourceFile); const hasSyntheticDefault = canHaveSyntheticDefault(file, originalSymbol, /*dontResolveAlias*/ false); if (hasSyntheticDefault) { const memberTable = createSymbolTable(); @@ -19326,7 +19325,7 @@ namespace ts { // If func.parent is a class and symbol is a (readonly) property of that class, or // if func is a constructor and symbol is a (readonly) parameter property declared in it, // then symbol is writeable here. - return !(func.parent === symbol.valueDeclaration!.parent || func === symbol.valueDeclaration!.parent); + return !(func.parent === symbol.valueDeclaration.parent || func === symbol.valueDeclaration.parent); } return true; } @@ -20775,7 +20774,7 @@ namespace ts { } if (names.get(memberName)) { - error(getNameOfDeclaration(member.symbol!.valueDeclaration!), Diagnostics.Duplicate_identifier_0, memberName); + error(getNameOfDeclaration(member.symbol!.valueDeclaration), Diagnostics.Duplicate_identifier_0, memberName); error(member.name, Diagnostics.Duplicate_identifier_0, memberName); } else { @@ -20790,7 +20789,7 @@ namespace ts { const nodeSymbol = getSymbolOfNode(node)!; // 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) { + if (nodeSymbol.declarations.length > 0 && nodeSymbol.declarations[0] !== node) { return; } } @@ -20802,7 +20801,7 @@ namespace ts { if (indexSymbol) { let seenNumericIndexer = false; let seenStringIndexer = false; - for (const decl of indexSymbol.declarations!) { + for (const decl of indexSymbol.declarations) { const declaration = decl; if (declaration.parameters.length === 1 && declaration.parameters[0].type) { switch (declaration.parameters[0].type!.kind) { @@ -21237,7 +21236,7 @@ namespace ts { let lastSeenNonAmbientDeclaration: FunctionLikeDeclaration | undefined; let previousDeclaration: SignatureDeclaration | undefined; - const declarations = symbol.declarations!; + const declarations = symbol.declarations; const isConstructor = (symbol.flags & SymbolFlags.Constructor) !== 0; function reportImplementationExpectedError(node: SignatureDeclaration): void { @@ -21412,7 +21411,7 @@ namespace ts { let exportedDeclarationSpaces = DeclarationSpaces.None; let nonExportedDeclarationSpaces = DeclarationSpaces.None; let defaultExportedDeclarationSpaces = DeclarationSpaces.None; - for (const d of symbol.declarations!) { + for (const d of symbol.declarations) { const declarationSpaces = getDeclarationSpaces(d); const effectiveDeclarationFlags = getEffectiveDeclarationFlags(d, ModifierFlags.Export | ModifierFlags.Default); @@ -21437,7 +21436,7 @@ namespace ts { if (commonDeclarationSpacesForExportsAndLocals || commonDeclarationSpacesForDefaultAndNonDefault) { // declaration spaces for exported and non-exported declarations intersect - for (const d of symbol.declarations!) { + for (const d of symbol.declarations) { const declarationSpaces = getDeclarationSpaces(d); const name = getNameOfDeclaration(d); @@ -22093,7 +22092,7 @@ namespace ts { // Since the javascript won't do semantic analysis like typescript, // if the javascript file comes before the typescript file and both contain same name functions, // checkFunctionOrConstructorSymbol wouldn't be called if we didnt ignore javascript function. - const firstDeclaration = find(localSymbol.declarations!, + const firstDeclaration = find(localSymbol.declarations, // Get first non javascript function declaration declaration => declaration.kind === node.kind && !(declaration.flags & NodeFlags.JavaScriptFile)); @@ -22295,7 +22294,7 @@ 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) && typeParameters && last(getSymbolOfNode(node)!.declarations!) === node) { + if (!(node.flags & NodeFlags.Ambient) && typeParameters && last(getSymbolOfNode(node)!.declarations) === node) { for (const typeParameter of typeParameters) { 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!))); @@ -22310,7 +22309,7 @@ namespace ts { const unusedImports = createMap<[ImportClause, ImportedDeclaration[]]>(); node.locals!.forEach(local => { if (local.isReferenced || local.exportSymbol) return; - for (const declaration of local.declarations!) { + for (const declaration of local.declarations) { if (isAmbientModule(declaration)) continue; if (isImportedDeclaration(declaration)) { const importClause = importClauseFromImported(declaration); @@ -22736,8 +22735,8 @@ namespace ts { if (node.initializer) { checkTypeAssignableTo(checkExpressionCached(node.initializer), declarationType, node, /*headMessage*/ undefined); } - if (!areDeclarationFlagsIdentical(node, symbol.valueDeclaration!)) { - error(getNameOfDeclaration(symbol.valueDeclaration!), Diagnostics.All_declarations_of_0_must_have_identical_modifiers, declarationNameToString(node.name)); + if (!areDeclarationFlagsIdentical(node, symbol.valueDeclaration)) { + error(getNameOfDeclaration(symbol.valueDeclaration), Diagnostics.All_declarations_of_0_must_have_identical_modifiers, declarationNameToString(node.name)); error(node.name, Diagnostics.All_declarations_of_0_must_have_identical_modifiers, declarationNameToString(node.name)); } } @@ -23496,7 +23495,7 @@ namespace ts { 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); + grammarErrorOnNode(blockLocal.valueDeclaration, Diagnostics.Cannot_redeclare_identifier_0_in_catch_clause, caughtName); } }); } @@ -23525,7 +23524,7 @@ namespace ts { checkIndexConstraintForProperty(prop, propType, type, declaredNumberIndexer, numberIndexType, IndexKind.Number); }); - 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. @@ -23547,7 +23546,7 @@ namespace ts { // condition 'errorNode === undefined' may appear if types does not declare nor string neither number indexer if (!errorNode && (getObjectFlags(type) & ObjectFlags.Interface)) { const someBaseTypeHasBothIndexers = forEach(getBaseTypes(type), base => getIndexTypeOfType(base, IndexKind.String) && getIndexTypeOfType(base, IndexKind.Number)); - errorNode = someBaseTypeHasBothIndexers ? undefined : type.symbol!.declarations![0]; + errorNode = someBaseTypeHasBothIndexers ? undefined : type.symbol!.declarations[0]; } } @@ -23593,7 +23592,7 @@ namespace ts { // check if any base class already has both property and indexer. // check should be performed only if 'type' is the first type that brings property\indexer together const someBaseClassHasBothPropertyAndIndexer = forEach(getBaseTypes(containingType), base => getPropertyOfObjectType(base, prop.escapedName) && getIndexTypeOfType(base, indexKind)); - errorNode = someBaseClassHasBothPropertyAndIndexer ? undefined : containingType.symbol!.declarations![0]; + errorNode = someBaseClassHasBothPropertyAndIndexer ? undefined : containingType.symbol!.declarations[0]; } if (errorNode && !isTypeAssignableTo(propertyType, indexType)) { @@ -23650,7 +23649,7 @@ namespace ts { /** Check that type parameter lists are identical across multiple declarations */ function checkTypeParameterListsIdentical(symbol: Symbol) { - if (symbol.declarations!.length === 1) { + if (symbol.declarations.length === 1) { return; } @@ -23892,7 +23891,7 @@ namespace ts { } function getClassOrInterfaceDeclarationsOfSymbol(symbol: Symbol) { - return filter(symbol.declarations!, (d: Declaration): d is ClassDeclaration | InterfaceDeclaration => + return filter(symbol.declarations, (d: Declaration): d is ClassDeclaration | InterfaceDeclaration => d.kind === SyntaxKind.ClassDeclaration || d.kind === SyntaxKind.InterfaceDeclaration); } @@ -23978,7 +23977,7 @@ namespace ts { errorMessage = Diagnostics.Class_0_defines_instance_member_property_1_but_extended_class_2_defines_it_as_instance_member_function; } - error(getNameOfDeclaration(derived.valueDeclaration!) || derived.valueDeclaration, errorMessage, typeToString(baseType), symbolToString(base), typeToString(type)); + error(getNameOfDeclaration(derived.valueDeclaration) || derived.valueDeclaration, errorMessage, typeToString(baseType), symbolToString(base), typeToString(type)); } } } @@ -24247,7 +24246,7 @@ namespace ts { function evaluateEnumMember(expr: Expression, enumSymbol: Symbol, name: __String) { const memberSymbol = enumSymbol.exports!.get(name); if (memberSymbol) { - const declaration = memberSymbol.valueDeclaration!; + const declaration = memberSymbol.valueDeclaration; if (declaration !== member) { if (isBlockScopedNameDeclaredBeforeUse(declaration, member)) { return getEnumMemberValue(declaration as EnumMember); @@ -24296,7 +24295,7 @@ namespace ts { const enumSymbol = getSymbolOfNode(node)!; const firstDeclaration = getDeclarationOfKind(enumSymbol, node.kind); if (node === firstDeclaration) { - if (enumSymbol.declarations!.length > 1) { + if (enumSymbol.declarations.length > 1) { // check that const is placed\omitted on all enum declarations forEach(enumSymbol.declarations, decl => { if (isConstEnumDeclaration(decl) !== enumIsConst) { @@ -24331,7 +24330,7 @@ namespace ts { } function getFirstNonAmbientClassOrFunctionDeclaration(symbol: Symbol): Declaration | undefined { - const declarations = symbol.declarations!; + const declarations = symbol.declarations; for (const declaration of declarations) { if ((declaration.kind === SyntaxKind.ClassDeclaration || (declaration.kind === SyntaxKind.FunctionDeclaration && nodeIsPresent((declaration).body))) && @@ -24390,7 +24389,7 @@ namespace ts { // The following checks only apply on a non-ambient instantiated module declaration. if (symbol.flags & SymbolFlags.ValueModule - && symbol.declarations!.length > 1 + && symbol.declarations.length > 1 && !inAmbientContext && isInstantiatedModule(node, !!compilerOptions.preserveConstEnums || !!compilerOptions.isolatedModules)) { const firstNonAmbientClassOrFunc = getFirstNonAmbientClassOrFunctionDeclaration(symbol); @@ -24500,7 +24499,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; @@ -24713,7 +24712,7 @@ namespace ts { // find immediate value referenced by exported name (SymbolFlags.Alias is set so we don't chase down aliases) const symbol = resolveName(exportedName, exportedName.escapedText, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true); - if (symbol && (symbol === undefinedSymbol || isGlobalSourceFile(getDeclarationContainer(symbol.declarations![0])))) { + if (symbol && (symbol === undefinedSymbol || isGlobalSourceFile(getDeclarationContainer(symbol.declarations[0])))) { error(exportedName, Diagnostics.Cannot_export_0_Only_local_declarations_can_be_exported_from_a_module, idText(exportedName)); } else { @@ -24782,7 +24781,7 @@ namespace ts { if (!links.exportsChecked) { const exportEqualsSymbol = moduleSymbol.exports!.get("export=" as __String); if (exportEqualsSymbol && hasExportedMembers(moduleSymbol)) { - const declaration = getDeclarationOfAliasSymbol(exportEqualsSymbol) || exportEqualsSymbol.valueDeclaration!; + const declaration = getDeclarationOfAliasSymbol(exportEqualsSymbol) || exportEqualsSymbol.valueDeclaration; if (!isTopLevelInExternalModuleAugmentation(declaration) && !isInJavaScriptFile(declaration)) { error(declaration, Diagnostics.An_export_assignment_cannot_be_used_in_a_module_with_other_exported_elements); } @@ -24799,14 +24798,14 @@ namespace ts { if (flags & (SymbolFlags.Namespace | SymbolFlags.Interface | SymbolFlags.Enum)) { return; } - const exportedDeclarationsCount = countWhere(declarations!, isNotOverloadAndNotAccessor); + const exportedDeclarationsCount = countWhere(declarations, isNotOverloadAndNotAccessor); if (flags & SymbolFlags.TypeAlias && exportedDeclarationsCount <= 2) { // it is legal to merge type alias with other values // so count should be either 1 (just type alias) or 2 (type alias + merged value) return; } if (exportedDeclarationsCount > 1) { - for (const declaration of declarations!) { + for (const declaration of declarations) { if (isNotOverload(declaration)) { diagnostics.add(createDiagnosticForNode(declaration, Diagnostics.Cannot_redeclare_exported_variable_0, unescapeLeadingUnderscores(id))); } @@ -25922,7 +25921,7 @@ namespace ts { } const parentSymbol = getParentOfSymbol(symbol); if (parentSymbol) { - if (parentSymbol.flags & SymbolFlags.ValueModule && parentSymbol.valueDeclaration!.kind === SyntaxKind.SourceFile) { + if (parentSymbol.flags & SymbolFlags.ValueModule && parentSymbol.valueDeclaration.kind === SyntaxKind.SourceFile) { const symbolFile = parentSymbol.valueDeclaration; const referenceFile = getSourceFileOfNode(node); // If `node` accesses an export and that export isn't in the same file, then symbol is a namespace export, so return undefined. @@ -25955,9 +25954,9 @@ namespace ts { if (symbol.flags & SymbolFlags.BlockScoped) { const links = getSymbolLinks(symbol); if (links.isDeclarationWithCollidingName === undefined) { - const container = getEnclosingBlockScopeContainer(symbol.valueDeclaration!); + const container = getEnclosingBlockScopeContainer(symbol.valueDeclaration); if (isStatementWithLocals(container)) { - const nodeLinks = getNodeLinks(symbol.valueDeclaration!); + const nodeLinks = getNodeLinks(symbol.valueDeclaration); if (resolveName(container.parent, symbol.escapedName, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false)) { // redeclaration - always should be renamed links.isDeclarationWithCollidingName = true; @@ -26153,7 +26152,7 @@ namespace ts { const symbol = getNodeLinks(node).resolvedSymbol; if (symbol && (symbol.flags & SymbolFlags.EnumMember)) { // inline property\index accesses only for const enums - if (isConstEnumDeclaration(symbol.valueDeclaration!.parent)) { + if (isConstEnumDeclaration(symbol.valueDeclaration.parent)) { return getEnumMemberValue(symbol.valueDeclaration); } } @@ -26426,7 +26425,7 @@ namespace ts { } // check what declarations in the symbol can contribute to the target meaning let typeReferenceDirectives: string[] | undefined; - for (const decl of symbol.declarations!) { + 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!) { const file = getSourceFileOfNode(decl); diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 2f6dba6084575..2f8ac900f34f6 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -2842,8 +2842,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; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 5687eb21d131b..6538f2867087f 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3371,8 +3371,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 diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 89d53474eeb85..4eeb626382edb 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -441,7 +441,7 @@ namespace ts { /** Given a symbol for a module, checks that it is a shorthand ambient module. */ export function isShorthandAmbientModuleSymbol(moduleSymbol: Symbol): boolean { - return isShorthandAmbientModule(moduleSymbol.valueDeclaration!); + return isShorthandAmbientModule(moduleSymbol.valueDeclaration); } function isShorthandAmbientModule(node: Node): boolean { @@ -3451,11 +3451,11 @@ namespace ts { } export function getLocalSymbolForExportDefault(symbol: Symbol) { - return isExportDefaultSymbol(symbol) ? symbol.declarations![0].localSymbol : undefined; + return isExportDefaultSymbol(symbol) ? symbol.declarations[0].localSymbol : undefined; } function isExportDefaultSymbol(symbol: Symbol): boolean { - return symbol && length(symbol.declarations) > 0 && hasModifier(symbol.declarations![0], ModifierFlags.Default); + return symbol && length(symbol.declarations) > 0 && hasModifier(symbol.declarations[0], ModifierFlags.Default); } /** Return ".ts", ".d.ts", or ".tsx", if that is the extension. */ @@ -3996,7 +3996,7 @@ namespace ts { } export function getClassLikeDeclarationOfSymbol(symbol: Symbol): ClassLikeDeclaration | undefined { - return find(symbol.declarations!, isClassLike); + return find(symbol.declarations, isClassLike); } export function getObjectFlags(type: Type): ObjectFlags { diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index cc21bf55ed4c3..45478967b6f11 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1013,7 +1013,7 @@ namespace FourSlash { } private verifySymbol(symbol: ts.Symbol, declarationRanges: Range[]) { - const declarations = symbol.declarations!; + const { declarations } = symbol; if (declarations.length !== declarationRanges.length) { this.raiseError(`Expected to get ${declarationRanges.length} declarations, got ${declarations.length}`); } diff --git a/src/services/codefixes/convertFunctionToEs6Class.ts b/src/services/codefixes/convertFunctionToEs6Class.ts index 569587887e2a9..68f81fdd86dac 100644 --- a/src/services/codefixes/convertFunctionToEs6Class.ts +++ b/src/services/codefixes/convertFunctionToEs6Class.ts @@ -21,7 +21,7 @@ namespace ts.codefix { return undefined; } - const ctorDeclaration = ctorSymbol.valueDeclaration!; + const ctorDeclaration = ctorSymbol.valueDeclaration; let precedingNode: Node | undefined; let newClassDeclaration: ClassDeclaration | undefined; diff --git a/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts b/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts index 2125d463eb808..02f8ddb4e2986 100644 --- a/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts +++ b/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts @@ -44,7 +44,7 @@ namespace ts.codefix { // so duplicates cannot occur. const implementedType = checker.getTypeAtLocation(implementedTypeNode) as InterfaceType; const implementedTypeSymbols = checker.getPropertiesOfType(implementedType); - const nonPrivateMembers = implementedTypeSymbols.filter(symbol => !(getModifierFlags(symbol.valueDeclaration!) & ModifierFlags.Private)); + const nonPrivateMembers = implementedTypeSymbols.filter(symbol => !(getModifierFlags(symbol.valueDeclaration) & ModifierFlags.Private)); const classType = checker.getTypeAtLocation(classDeclaration)!; diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index f7b0ff952f4fa..b26b1f78aeb9b 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -251,7 +251,7 @@ namespace ts.codefix { const moduleResolutionKind = getEmitModuleResolutionKind(compilerOptions); const addJsExtension = usesJsExtensionOnImports(sourceFile); const choicesForEachExportingModule = flatMap(moduleSymbols, ({ moduleSymbol, importKind }) => { - const modulePathsGroups = getAllModulePaths(program, moduleSymbol.valueDeclaration!.getSourceFile()).map(moduleFileName => { + const modulePathsGroups = getAllModulePaths(program, moduleSymbol.valueDeclaration.getSourceFile()).map(moduleFileName => { const sourceDirectory = getDirectoryPath(sourceFile.fileName); const global = tryGetModuleNameFromAmbientModule(moduleSymbol) || tryGetModuleNameFromTypeRoots(compilerOptions, host, getCanonicalFileName, moduleFileName, addJsExtension) @@ -346,7 +346,7 @@ namespace ts.codefix { } function tryGetModuleNameFromAmbientModule(moduleSymbol: Symbol): string | undefined { - const decl = moduleSymbol.valueDeclaration!; + const decl = moduleSymbol.valueDeclaration; if (isModuleDeclaration(decl) && isStringLiteral(decl.name)) { return decl.name.text; } diff --git a/src/services/completions.ts b/src/services/completions.ts index 55b0edc0f2eff..58d8fe6aa3e37 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -514,7 +514,7 @@ namespace ts.Completions { function getSymbolName(symbol: Symbol, origin: SymbolOriginInfo | undefined, target: ScriptTarget): string { return origin && origin.type === "export" && origin.isDefaultExport && symbol.escapedName === InternalSymbolName.Default // Name of "export default foo;" is "foo". Name of "export default 0" is the filename converted to camelCase. - ? firstDefined(symbol.declarations!, d => isExportAssignment(d) && isIdentifier(d.expression) ? d.expression.text : undefined) // TODO: GH#18217 + ? firstDefined(symbol.declarations, d => isExportAssignment(d) && isIdentifier(d.expression) ? d.expression.text : undefined) || codefix.moduleSymbolToValidIdentifier(origin.moduleSymbol, target) : symbol.name; } @@ -748,7 +748,7 @@ namespace ts.Completions { } function isModuleSymbol(symbol: Symbol): boolean { - return symbol.declarations!.some(d => d.kind === SyntaxKind.SourceFile); + return symbol.declarations.some(d => d.kind === SyntaxKind.SourceFile); } function getCompletionData( @@ -1043,7 +1043,7 @@ namespace ts.Completions { } // If the module is merged with a value, we must get the type of the class and add its propertes (for inherited static methods). - if (!isTypeLocation && symbol.declarations!.some(d => d.kind !== SyntaxKind.SourceFile && d.kind !== SyntaxKind.ModuleDeclaration && d.kind !== SyntaxKind.EnumDeclaration)) { + if (!isTypeLocation && symbol.declarations.some(d => d.kind !== SyntaxKind.SourceFile && d.kind !== SyntaxKind.ModuleDeclaration && d.kind !== SyntaxKind.EnumDeclaration)) { addTypeProperties(typeChecker.getTypeOfSymbolAtLocation(symbol, node)); } diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index fb686b1a357e2..eee675beb69d8 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -135,7 +135,7 @@ namespace ts.FindAllReferences { function getDefinitionKindAndDisplayParts(symbol: Symbol, checker: TypeChecker, node: Node): { displayParts: SymbolDisplayPart[], kind: ScriptElementKind } { const meaning = Core.getIntersectingMeaningFromDeclarations(node, symbol); - const enclosingDeclaration = firstOrUndefined(symbol.declarations!) || node; + const enclosingDeclaration = firstOrUndefined(symbol.declarations) || node; const { displayParts, symbolKind } = SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(checker, symbol, enclosingDeclaration.getSourceFile(), enclosingDeclaration, enclosingDeclaration, meaning); return { displayParts, kind: symbolKind }; @@ -292,7 +292,7 @@ namespace ts.FindAllReferences.Core { } }); - for (const decl of symbol.declarations!) { + for (const decl of symbol.declarations) { switch (decl.kind) { case SyntaxKind.SourceFile: // Don't include the source file itself. (This may not be ideal behavior, but awkward to include an entire file as a reference.) @@ -590,7 +590,7 @@ namespace ts.FindAllReferences.Core { // Go to the symbol we imported from and find references for it. function searchForImportedSymbol(symbol: Symbol, state: State): void { - for (const declaration of symbol.declarations!) { + for (const declaration of symbol.declarations) { const exportingFile = declaration.getSourceFile(); // Need to search in the file even if it's not in the search-file set, because it might export the symbol. getReferencesInSourceFile(exportingFile, state.createSearch(declaration, symbol, ImportExport.Import), state, state.includesSourceFile(exportingFile)); @@ -968,7 +968,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 @@ -977,7 +977,7 @@ namespace ts.FindAllReferences.Core { * position of property accessing, the referenceEntry of such position will be handled in the first case. */ if (!(flags & SymbolFlags.Transient) && search.includes(shorthandValueSymbol)) { - addReference(getNameOfDeclaration(valueDeclaration!), shorthandValueSymbol, state); + addReference(getNameOfDeclaration(valueDeclaration), shorthandValueSymbol, state); } } @@ -1039,7 +1039,7 @@ 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!) { // TODO: GH#18217 + 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); @@ -1068,7 +1068,7 @@ namespace ts.FindAllReferences.Core { return; } - for (const decl of ctr.declarations!) { + for (const decl of ctr.declarations) { Debug.assert(decl.kind === SyntaxKind.Constructor); const body = (decl).body; if (body) { @@ -1189,7 +1189,7 @@ namespace ts.FindAllReferences.Core { // Set the key so that we don't infinitely recurse cachedResults.set(key, false); - const inherits = symbol.declarations!.some(declaration => + const inherits = symbol.declarations.some(declaration => getAllSuperTypeNodes(declaration).some(typeReference => { const type = checker.getTypeAtLocation(typeReference); return !!type && !!type.symbol && explicitlyInheritsFrom(type.symbol, parent, cachedResults, checker); @@ -1486,7 +1486,7 @@ namespace ts.FindAllReferences.Core { export function getReferenceEntriesForShorthandPropertyAssignment(node: Node, checker: TypeChecker, addReference: (node: Node) => void): void { const refSymbol = checker.getSymbolAtLocation(node)!; - const shorthandSymbol = checker.getShorthandAssignmentValueSymbol(refSymbol.valueDeclaration!); + const shorthandSymbol = checker.getShorthandAssignmentValueSymbol(refSymbol.valueDeclaration); if (shorthandSymbol) { for (const declaration of shorthandSymbol.getDeclarations()!) { diff --git a/src/services/goToDefinition.ts b/src/services/goToDefinition.ts index 8140a86e473c1..1a429ea4e0a41 100644 --- a/src/services/goToDefinition.ts +++ b/src/services/goToDefinition.ts @@ -43,8 +43,8 @@ namespace ts.GoToDefinition { // is performed at the location of property access, we would like to go to definition of the property in the short-hand // assignment. This case and others are handled by the following code. if (node.parent.kind === SyntaxKind.ShorthandPropertyAssignment) { - const shorthandSymbol = typeChecker.getShorthandAssignmentValueSymbol(symbol.valueDeclaration!); - return shorthandSymbol ? shorthandSymbol.declarations!.map(decl => createDefinitionInfo(decl, typeChecker, shorthandSymbol, node)) : []; + const shorthandSymbol = typeChecker.getShorthandAssignmentValueSymbol(symbol.valueDeclaration); + return shorthandSymbol ? shorthandSymbol.declarations.map(decl => createDefinitionInfo(decl, typeChecker, shorthandSymbol, node)) : []; } // If the node is the name of a BindingElement within an ObjectBindingPattern instead of just returning the @@ -158,7 +158,7 @@ namespace ts.GoToDefinition { // get the aliased symbol instead. This allows for goto def on an import e.g. // import {A, B} from "mod"; // to jump to the implementation directly. - if (symbol && symbol.flags & SymbolFlags.Alias && shouldSkipAlias(node, symbol.declarations![0])) { + if (symbol && symbol.flags & SymbolFlags.Alias && shouldSkipAlias(node, symbol.declarations[0])) { const aliased = checker.getAliasedSymbol(symbol); if (aliased.declarations) { return aliased; @@ -197,7 +197,7 @@ namespace ts.GoToDefinition { // Applicable only if we are in a new expression, or we are on a constructor declaration // and in either case the symbol has a construct signature definition, i.e. class if (symbol.flags & SymbolFlags.Class && (isNewExpressionTarget(node) || node.kind === SyntaxKind.ConstructorKeyword)) { - const cls = find(symbol.declarations!, isClassLike) || Debug.fail("Expected declaration to have at least one class-like declaration"); + const cls = find(symbol.declarations, isClassLike) || Debug.fail("Expected declaration to have at least one class-like declaration"); return getSignatureDefinition(cls.members, /*selectConstructors*/ true); } } diff --git a/src/services/importTracker.ts b/src/services/importTracker.ts index df81630de6487..ec283d16f98ed 100644 --- a/src/services/importTracker.ts +++ b/src/services/importTracker.ts @@ -62,7 +62,7 @@ namespace ts.FindAllReferences { } // Module augmentations may use this module's exports without importing it. - for (const decl of exportingModuleSymbol.declarations!) { + for (const decl of exportingModuleSymbol.declarations) { if (isExternalModuleAugmentation(decl) && sourceFilesSet.has(decl.getSourceFile().fileName)) { addIndirectUser(decl); } @@ -335,7 +335,7 @@ namespace ts.FindAllReferences { const refs: ModuleReference[] = []; const checker = program.getTypeChecker(); for (const referencingFile of sourceFiles) { - const searchSourceFile = searchModuleSymbol.valueDeclaration!; + const searchSourceFile = searchModuleSymbol.valueDeclaration; if (searchSourceFile.kind === SyntaxKind.SourceFile) { for (const ref of referencingFile.referencedFiles) { if (program.getSourceFileFromReference(referencingFile, ref) === searchSourceFile) { @@ -447,7 +447,7 @@ namespace ts.FindAllReferences { 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(grandParent) + return symbol.declarations.some(d => d === parent) && isBinaryExpression(grandParent) ? getSpecialPropertyExport(grandParent, /*useLhsSymbol*/ false) : undefined; } @@ -557,7 +557,7 @@ namespace ts.FindAllReferences { return Debug.assertDefined(checker.getImmediateAliasedSymbol(importedSymbol)); } - const decl = importedSymbol.valueDeclaration!; + const decl = importedSymbol.valueDeclaration; if (isExportAssignment(decl)) { // `export = class {}` return Debug.assertDefined(decl.expression.symbol); } diff --git a/src/services/services.ts b/src/services/services.ts index 95393c17a2d5b..46b823a778682 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -278,7 +278,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. diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts index 218017e81e37f..9d1cf050400ca 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -162,7 +162,7 @@ namespace ts.SymbolDisplay { else if (isCallExpressionTarget(location) || isNewExpressionTarget(location)) { callExpressionLike = location.parent; } - else if (location.parent && isJsxOpeningLikeElement(location.parent) && isFunctionLike(symbol.valueDeclaration!)) { + else if (location.parent && isJsxOpeningLikeElement(location.parent) && isFunctionLike(symbol.valueDeclaration)) { callExpressionLike = location.parent; } @@ -234,7 +234,7 @@ namespace ts.SymbolDisplay { // get the signature from the declaration and write it const functionDeclaration = location.parent; // Use function declaration to write the signatures only if the symbol corresponding to this declaration - const locationIsSymbolDeclaration = find(symbol.declarations!, declaration => // TODO: GH#18217 + const locationIsSymbolDeclaration = find(symbol.declarations, declaration => declaration === (location.kind === SyntaxKind.ConstructorKeyword ? functionDeclaration.parent : functionDeclaration)); if (locationIsSymbolDeclaration) { @@ -362,7 +362,7 @@ namespace ts.SymbolDisplay { if (symbolFlags & SymbolFlags.EnumMember) { symbolKind = ScriptElementKind.enumMemberElement; addPrefixForAnyFunctionOrVar(symbol, "enum member"); - const declaration = symbol.declarations![0]; + const declaration = symbol.declarations[0]; if (declaration.kind === SyntaxKind.EnumMember) { const constantValue = typeChecker.getConstantValue(declaration); if (constantValue !== undefined) { @@ -402,7 +402,7 @@ namespace ts.SymbolDisplay { } } - switch (symbol.declarations![0].kind) { + switch (symbol.declarations[0].kind) { case SyntaxKind.NamespaceExportDeclaration: displayParts.push(keywordPart(SyntaxKind.ExportKeyword)); displayParts.push(spacePart()); @@ -411,7 +411,7 @@ namespace ts.SymbolDisplay { case SyntaxKind.ExportAssignment: displayParts.push(keywordPart(SyntaxKind.ExportKeyword)); displayParts.push(spacePart()); - displayParts.push(keywordPart((symbol.declarations![0] as ExportAssignment).isExportEquals ? SyntaxKind.EqualsToken : SyntaxKind.DefaultKeyword)); + displayParts.push(keywordPart((symbol.declarations[0] as ExportAssignment).isExportEquals ? SyntaxKind.EqualsToken : SyntaxKind.DefaultKeyword)); break; case SyntaxKind.ExportSpecifier: displayParts.push(keywordPart(SyntaxKind.ExportKeyword)); @@ -503,7 +503,7 @@ namespace ts.SymbolDisplay { // there documentation comments might be attached to the right hand side symbol of their declarations. // The pattern of such special property access is that the parent symbol is the symbol of the file. if (symbol.parent && forEach(symbol.parent.declarations, declaration => declaration.kind === SyntaxKind.SourceFile)) { - for (const declaration of symbol.declarations!) { + for (const declaration of symbol.declarations) { if (!declaration.parent || declaration.parent.kind !== SyntaxKind.BinaryExpression) { continue; } diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 94dde50bf7f20..ca000b80968ac 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -2017,8 +2017,8 @@ declare namespace ts { interface Symbol { flags: SymbolFlags; escapedName: __String; - declarations?: Declaration[]; - valueDeclaration?: Declaration; + declarations: Declaration[]; + valueDeclaration: Declaration; members?: SymbolTable; exports?: SymbolTable; globalExports?: SymbolTable; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 49f5bff1da72d..cca47aa65fdc6 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2017,8 +2017,8 @@ declare namespace ts { interface Symbol { flags: SymbolFlags; escapedName: __String; - declarations?: Declaration[]; - valueDeclaration?: Declaration; + declarations: Declaration[]; + valueDeclaration: Declaration; members?: SymbolTable; exports?: SymbolTable; globalExports?: SymbolTable; From cd5c8529c206fa0f9e455a43d5905f699dac7288 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Wed, 25 Apr 2018 10:52:41 -0700 Subject: [PATCH 32/42] Make Node#symbol and Type#symbol non-optional to reduce assertions --- src/compiler/binder.ts | 30 ++-- src/compiler/checker.ts | 160 +++++++++--------- src/compiler/emitter.ts | 2 +- src/compiler/types.ts | 8 +- src/harness/unittests/symbolWalker.ts | 2 +- .../codefixes/convertFunctionToEs6Class.ts | 2 +- src/services/codefixes/fixAddMissingMember.ts | 2 +- .../codefixes/fixStrictClassInitialization.ts | 4 +- src/services/codefixes/helpers.ts | 2 +- src/services/codefixes/importFixes.ts | 2 +- src/services/completions.ts | 2 +- src/services/documentHighlights.ts | 2 +- src/services/findAllReferences.ts | 9 +- src/services/goToDefinition.ts | 4 +- src/services/importTracker.ts | 6 +- src/services/refactors/extractSymbol.ts | 10 +- src/services/services.ts | 2 +- src/services/signatureHelp.ts | 2 +- src/services/suggestionDiagnostics.ts | 3 +- src/services/symbolDisplay.ts | 14 +- 20 files changed, 133 insertions(+), 135 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index ffbc952e9e7b3..0b11733da4318 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -427,7 +427,7 @@ 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); @@ -453,11 +453,11 @@ namespace ts { const isJSDocTypedefInJSDocNamespace = isJSDocTypedefTag(node) && node.name && node.name.kind === SyntaxKind.Identifier && node.name.isInJSDocNamespace; if ((!isAmbientModule(node) && (hasExportModifier || container.flags & NodeFlags.ExportContext)) || isJSDocTypedefInJSDocNamespace) { 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); + local.exportSymbol = declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes); node.localSymbol = local; return local; } @@ -1523,7 +1523,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: @@ -1535,7 +1535,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: @@ -1565,8 +1565,8 @@ namespace ts { 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) { @@ -1626,7 +1626,7 @@ namespace ts { else { const state = declareModuleSymbol(node); if (state !== ModuleInstanceState.NonInstantiated) { - const symbol = node.symbol!; + const { symbol } = node; // if module was already merged with some function, class or non-const enum, treat it as non-const-enum-only symbol.constEnumOnlyModule = (!(symbol.flags & (SymbolFlags.Function | SymbolFlags.Class | SymbolFlags.RegularEnum))) // Current must be `const enum` only @@ -2262,8 +2262,8 @@ namespace ts { } } - file.symbol!.globalExports = file.symbol!.globalExports || createSymbolTable(); - declareSymbol(file.symbol!.globalExports!, file.symbol, node, SymbolFlags.Alias, SymbolFlags.AliasExcludes); + file.symbol.globalExports = file.symbol.globalExports || createSymbolTable(); + declareSymbol(file.symbol.globalExports, file.symbol, node, SymbolFlags.Alias, SymbolFlags.AliasExcludes); } function bindExportDeclaration(node: ExportDeclaration) { @@ -2327,7 +2327,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) { @@ -2336,7 +2336,7 @@ namespace ts { switch (thisContainer.kind) { case SyntaxKind.FunctionDeclaration: case SyntaxKind.FunctionExpression: - let constructorSymbol = thisContainer.symbol!; + let constructorSymbol = thisContainer.symbol; // For `f.prototype.m = function() { this.x = 0; }`, `this.x = 0` should modify `f`'s members, not the function expression. if (isBinaryExpression(thisContainer.parent) && thisContainer.parent.operatorToken.kind === SyntaxKind.EqualsToken) { const l = thisContainer.parent.left; @@ -2361,7 +2361,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: @@ -2534,7 +2534,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 @@ -2608,7 +2608,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); } } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 62f1319197a9c..7b143e98f3ee9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -972,16 +972,16 @@ namespace ts { function mergeModuleAugmentation(moduleName: StringLiteral | Identifier): void { const moduleAugmentation = moduleName.parent; - if (moduleAugmentation.symbol!.declarations[0] !== moduleAugmentation) { + if (moduleAugmentation.symbol.declarations[0] !== moduleAugmentation) { // this is a combined symbol for multiple augmentations within the same file. // its symbol already has accumulated information for all declarations // so we need to add it just once - do the work only for first declaration - Debug.assert(moduleAugmentation.symbol!.declarations.length > 1); + Debug.assert(moduleAugmentation.symbol.declarations.length > 1); return; } if (isGlobalScopeAugmentation(moduleAugmentation)) { - mergeSymbolTable(globals, moduleAugmentation.symbol!.exports!); + mergeSymbolTable(globals, moduleAugmentation.symbol.exports!); } else { // find a module that about to be augmented @@ -999,7 +999,7 @@ namespace ts { // if module symbol has already been merged - it is safe to use it. // otherwise clone it mainModule = mainModule.flags & SymbolFlags.Transient ? mainModule : cloneSymbol(mainModule); - mergeSymbol(mainModule, moduleAugmentation.symbol!); + mergeSymbol(mainModule, moduleAugmentation.symbol); } else { // moduleName will be a StringLiteral since this is not `declare global`. @@ -1071,7 +1071,7 @@ namespace ts { const classDeclaration = parameter.parent.parent; const parameterSymbol = getSymbol(constructorDeclaration.locals!, parameterName, SymbolFlags.Value); - const propertySymbol = getSymbol(getMembersOfSymbol(classDeclaration.symbol!), parameterName, SymbolFlags.Value); + const propertySymbol = getSymbol(getMembersOfSymbol(classDeclaration.symbol), parameterName, SymbolFlags.Value); if (parameterSymbol && propertySymbol) { return [parameterSymbol, propertySymbol]; @@ -1919,7 +1919,7 @@ namespace ts { } function getTargetOfNamespaceExportDeclaration(node: NamespaceExportDeclaration, dontResolveAlias: boolean): Symbol { - return resolveExternalModuleSymbol(node.parent.symbol!, dontResolveAlias); + return resolveExternalModuleSymbol(node.parent.symbol, dontResolveAlias); } function getTargetOfExportSpecifier(node: ExportSpecifier, meaning: SymbolFlags, dontResolveAlias?: boolean) { @@ -2507,7 +2507,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; } @@ -3021,13 +3021,13 @@ 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!)); + const enumLiteralName = getDeclaredTypeOfSymbol(parentSymbol) === type ? parentName : createQualifiedName(parentName, symbolName(type.symbol)); return createTypeReferenceNode(enumLiteralName, /*typeArguments*/ undefined); } if (type.flags & TypeFlags.EnumLike) { - const name = symbolToName(type.symbol!, context, SymbolFlags.Type, /*expectsIdentifier*/ false); + const name = symbolToName(type.symbol, context, SymbolFlags.Type, /*expectsIdentifier*/ false); return createTypeReferenceNode(name, /*typeArguments*/ undefined); } if (type.flags & (TypeFlags.StringLiteral)) { @@ -3041,8 +3041,8 @@ namespace ts { } if (type.flags & TypeFlags.UniqueESSymbol) { if (!(context.flags! & NodeBuilderFlags.AllowUniqueESSymbolType)) { - if (isValueSymbolAccessible(type.symbol!, context.enclosingDeclaration!)) { - return symbolToTypeNode(type.symbol!, context, SymbolFlags.Value); + if (isValueSymbolAccessible(type.symbol, context.enclosingDeclaration!)) { + return symbolToTypeNode(type.symbol, context, SymbolFlags.Value); } if (context.tracker!.reportInaccessibleUniqueSymbolError) { context.tracker!.reportInaccessibleUniqueSymbolError!(); @@ -3088,7 +3088,7 @@ namespace ts { } if (type.flags & TypeFlags.TypeParameter || objectFlags & ObjectFlags.ClassOrInterface) { if (type.flags & TypeFlags.TypeParameter && contains(context.inferTypeParameters, type)) { - return createInferTypeNode(createTypeParameterDeclaration(getNameOfSymbolAsWritten(type.symbol!))); + return createInferTypeNode(createTypeParameterDeclaration(getNameOfSymbolAsWritten(type.symbol))); } const name = type.symbol ? symbolToName(type.symbol, context, SymbolFlags.Type, /*expectsIdentifier*/ false) : createIdentifier("?"); // Ignore constraint/default when creating a usage (as opposed to declaration) of a type parameter. @@ -3204,17 +3204,17 @@ namespace ts { } function shouldWriteTypeOfFunctionSymbol() { - const isStaticMethodSymbol = !!(symbol!.flags & SymbolFlags.Method) && // typeof static method - some(symbol!.declarations, declaration => hasModifier(declaration, ModifierFlags.Static)); - const isNonLocalFunctionSymbol = !!(symbol!.flags & SymbolFlags.Function) && - (symbol!.parent || // is exported function symbol - forEach(symbol!.declarations, declaration => + const isStaticMethodSymbol = !!(symbol.flags & SymbolFlags.Method) && // typeof static method + some(symbol.declarations, declaration => hasModifier(declaration, ModifierFlags.Static)); + const isNonLocalFunctionSymbol = !!(symbol.flags & SymbolFlags.Function) && + (symbol.parent || // is exported function symbol + forEach(symbol.declarations, declaration => declaration.parent.kind === SyntaxKind.SourceFile || declaration.parent.kind === SyntaxKind.ModuleBlock)); if (isStaticMethodSymbol || isNonLocalFunctionSymbol) { // typeof is allowed only for static/non local functions return (!!(context.flags! & NodeBuilderFlags.UseTypeOfFunction) || contains(context.symbolStack, symbol)) && // it is type of the symbol uses itself recursively // 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 + (!(context.flags! & NodeBuilderFlags.UseStructuralFallback) || isValueSymbolAccessible(symbol, context.enclosingDeclaration!)); // TODO: GH#18217 } } } @@ -3283,9 +3283,9 @@ namespace ts { return undefined; } else if (context.flags! & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral && - type.symbol!.valueDeclaration && - isClassLike(type.symbol!.valueDeclaration) && - !isValueSymbolAccessible(type.symbol!, context.enclosingDeclaration!) + type.symbol.valueDeclaration && + isClassLike(type.symbol.valueDeclaration) && + !isValueSymbolAccessible(type.symbol, context.enclosingDeclaration!) ) { return createAnonymousTypeNode(type); } @@ -3323,7 +3323,7 @@ namespace ts { } let entityName: EntityName; - const nameIdentifier = symbolToTypeReferenceName(type.symbol!); + const nameIdentifier = symbolToTypeReferenceName(type.symbol); if (qualifiedName) { Debug.assert(!qualifiedName.right); qualifiedName = addToQualifiedNameMissingRightIdentifier(qualifiedName, nameIdentifier); @@ -3529,7 +3529,7 @@ namespace ts { function typeParameterToDeclaration(type: TypeParameter, context: NodeBuilderContext, constraint = getConstraintFromTypeParameter(type)): TypeParameterDeclaration { const savedContextFlags = context.flags; context.flags! &= ~NodeBuilderFlags.WriteTypeParametersInQualifiedName; // Avoids potential infinite loop when building for a claimspace with a generic - const name = symbolToName(type.symbol!, context, SymbolFlags.Type, /*expectsIdentifier*/ true); + const name = symbolToName(type.symbol, context, SymbolFlags.Type, /*expectsIdentifier*/ true); const constraintNode = constraint && typeToTypeNodeHelper(constraint, context); const defaultParameter = getDefaultFromTypeParameter(type); const defaultParameterNode = defaultParameter && typeToTypeNodeHelper(defaultParameter, context); @@ -4366,7 +4366,7 @@ namespace ts { } // Use contextual parameter type if one is available let type: Type | undefined; - if (declaration.symbol!.escapedName === "this") { + if (declaration.symbol.escapedName === "this") { type = getContextualThisParameterType(func); } else { @@ -5043,7 +5043,7 @@ namespace ts { } function getBaseTypeNodeOfClass(type: InterfaceType): ExpressionWithTypeArguments | undefined { - const decl = type.symbol!.valueDeclaration; + const decl = type.symbol.valueDeclaration; if (isInJavaScriptFile(decl)) { // Prefer an @augments tag because it may have type parameters. const tag = getJSDocAugmentsTag(decl); @@ -5078,7 +5078,7 @@ namespace ts { */ function getBaseConstructorTypeOfClass(type: InterfaceType): Type { if (!type.resolvedBaseConstructorType) { - const decl = type.symbol!.valueDeclaration; + const decl = type.symbol.valueDeclaration; const extended = getClassExtendsHeritageClauseElement(decl); const baseTypeNode = getBaseTypeNodeOfClass(type); if (!baseTypeNode) { @@ -5098,7 +5098,7 @@ namespace ts { resolveStructuredTypeMembers(baseConstructorType); } if (!popTypeResolution()) { - error(type.symbol!.valueDeclaration, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_base_expression, symbolToString(type.symbol!)); + error(type.symbol.valueDeclaration, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_base_expression, symbolToString(type.symbol)); return type.resolvedBaseConstructorType = unknownType; } if (!(baseConstructorType.flags & TypeFlags.Any) && baseConstructorType !== nullWideningType && !isConstructorType(baseConstructorType)) { @@ -5115,11 +5115,11 @@ namespace ts { if (type.objectFlags & ObjectFlags.Tuple) { type.resolvedBaseTypes = [createArrayType(getUnionType(type.typeParameters!))]; } - else if (type.symbol!.flags & (SymbolFlags.Class | SymbolFlags.Interface)) { - if (type.symbol!.flags & SymbolFlags.Class) { + else if (type.symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) { + if (type.symbol.flags & SymbolFlags.Class) { resolveBaseTypesOfClass(type); } - if (type.symbol!.flags & SymbolFlags.Interface) { + if (type.symbol.flags & SymbolFlags.Interface) { resolveBaseTypesOfInterface(type); } } @@ -5170,7 +5170,7 @@ namespace ts { return type.resolvedBaseTypes = emptyArray; } if (type === baseType || hasBaseType(baseType, type)) { - error(type.symbol!.valueDeclaration, Diagnostics.Type_0_recursively_references_itself_as_a_base_type, + error(type.symbol.valueDeclaration, Diagnostics.Type_0_recursively_references_itself_as_a_base_type, typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType)); return type.resolvedBaseTypes = emptyArray; } @@ -5205,7 +5205,7 @@ namespace ts { function resolveBaseTypesOfInterface(type: InterfaceType): void { type.resolvedBaseTypes = type.resolvedBaseTypes || emptyArray; - for (const declaration of type.symbol!.declarations) { + for (const declaration of type.symbol.declarations) { if (declaration.kind === SyntaxKind.InterfaceDeclaration && getInterfaceBaseTypeNodes(declaration)) { for (const node of getInterfaceBaseTypeNodes(declaration)!) { const baseType = getTypeFromTypeNode(node); @@ -5378,7 +5378,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 { @@ -5566,7 +5566,7 @@ namespace ts { function resolveDeclaredMembers(type: InterfaceType): InterfaceTypeWithDeclaredMembers { if (!(type).declaredProperties) { - const symbol = type.symbol!; + const symbol = type.symbol; const members = getMembersOfSymbol(symbol); (type).declaredProperties = getNamedMembers(members); (type).declaredCallSignatures = getSignaturesOfSymbol(members.get(InternalSymbolName.Call)); @@ -5625,7 +5625,7 @@ namespace ts { */ function getLateBoundNameFromType(type: LiteralType | UniqueESSymbolType): __String { if (type.flags & TypeFlags.UniqueESSymbol) { - return `__@${type.symbol!.escapedName}@${getSymbolId(type.symbol!)}` as __String; + return `__@${type.symbol.escapedName}@${getSymbolId(type.symbol)}` as __String; } if (type.flags & TypeFlags.StringOrNumberLiteral) { return escapeLeadingUnderscores("" + (type).value); @@ -5641,7 +5641,7 @@ namespace ts { function addDeclarationToLateBoundSymbol(symbol: Symbol, member: LateBoundDeclaration, symbolFlags: SymbolFlags) { Debug.assert(!!(getCheckFlags(symbol) & CheckFlags.Late), "Expected a late-bound symbol."); symbol.flags |= symbolFlags; - getSymbolLinks(member.symbol!).lateSymbol = symbol; + getSymbolLinks(member.symbol).lateSymbol = symbol; if (!symbol.declarations) { symbol.declarations = [member]; } @@ -5693,7 +5693,7 @@ namespace ts { const type = checkComputedPropertyName(decl.name); if (isTypeUsableAsLateBoundName(type)) { const memberName = getLateBoundNameFromType(type); - const symbolFlags = decl.symbol!.flags; + const symbolFlags = decl.symbol.flags; // Get or add a late-bound symbol for the member. This allows us to merge late-bound accessor declarations. let lateSymbol = lateSymbols.get(memberName); @@ -6079,7 +6079,7 @@ namespace ts { * Converts an AnonymousType to a ResolvedType. */ function resolveAnonymousTypeMembers(type: AnonymousType) { - const symbol = type.symbol!; + 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!); @@ -6789,7 +6789,7 @@ namespace ts { function getTypeParametersFromDeclaration(declaration: DeclarationWithTypeParameters): TypeParameter[] | undefined { let result: TypeParameter[] | undefined; forEach(getEffectiveTypeParameterDeclarations(declaration), node => { - result = appendIfUnique(result, getDeclaredTypeOfTypeParameter(node.symbol!)); + result = appendIfUnique(result, getDeclaredTypeOfTypeParameter(node.symbol)); }); return result; } @@ -6945,14 +6945,14 @@ 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") { // TODO: GH#18217 + if (i === 0 && paramSymbol.escapedName === "this") { hasThisParameter = true; thisParameter = param.symbol; } else { - parameters.push(paramSymbol!); + parameters.push(paramSymbol); } if (param.type && param.type.kind === SyntaxKind.LiteralType) { @@ -6981,7 +6981,7 @@ namespace ts { } const classType = declaration.kind === SyntaxKind.Constructor ? - getDeclaredTypeOfClassOrInterface(getMergedSymbol((declaration.parent).symbol!)) + getDeclaredTypeOfClassOrInterface(getMergedSymbol((declaration.parent).symbol)) : undefined; const typeParameters = classType ? classType.localTypeParameters : getTypeParametersFromDeclaration(declaration); const returnType = getSignatureReturnTypeFromDeclaration(declaration, isJSConstructSignature, classType); @@ -7350,7 +7350,7 @@ namespace ts { } function getParentSymbolOfTypeParameter(typeParameter: TypeParameter): Symbol | undefined { - return getSymbolOfNode(getDeclarationOfKind(typeParameter.symbol!, SyntaxKind.TypeParameter)!.parent); + return getSymbolOfNode(getDeclarationOfKind(typeParameter.symbol, SyntaxKind.TypeParameter)!.parent); } function getTypeListId(types: Type[] | undefined) { @@ -8002,10 +8002,10 @@ namespace ts { function isSetOfLiteralsFromSameEnum(types: Type[]): boolean { const first = types[0]; if (first.flags & TypeFlags.EnumLiteral) { - const firstEnum = getParentOfSymbol(first.symbol!); + const firstEnum = getParentOfSymbol(first.symbol); for (let i = 1; i < types.length; i++) { const other = types[i]; - if (!(other.flags & TypeFlags.EnumLiteral) || (firstEnum !== getParentOfSymbol(other.symbol!))) { + if (!(other.flags & TypeFlags.EnumLiteral) || (firstEnum !== getParentOfSymbol(other.symbol))) { return false; } } @@ -8769,7 +8769,7 @@ namespace ts { if (!links.resolvedType) { // Deferred resolution of members is handled by resolveObjectTypeMembers const aliasSymbol = getAliasSymbolForTypeNode(node); - if (getMembersOfSymbol(node.symbol!).size === 0 && !aliasSymbol) { + if (getMembersOfSymbol(node.symbol).size === 0 && !aliasSymbol) { links.resolvedType = emptyTypeLiteralType; } else { @@ -8908,7 +8908,7 @@ namespace ts { 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; } @@ -9255,7 +9255,7 @@ namespace ts { function getAnonymousTypeInstantiation(type: AnonymousType, mapper: TypeMapper) { const target = type.objectFlags & ObjectFlags.Instantiated ? type.target! : type; - const symbol = target.symbol!; + const { symbol } = target; const links = getSymbolLinks(symbol); let typeParameters = links.outerTypeParameters; if (!typeParameters) { @@ -9877,12 +9877,12 @@ namespace ts { (source).value === (target).value) return true; if (s & TypeFlags.BooleanLike && t & TypeFlags.Boolean) return true; if (s & TypeFlags.ESSymbolLike && t & TypeFlags.ESSymbol) return true; - if (s & TypeFlags.Enum && t & TypeFlags.Enum && isEnumTypeRelatedTo(source.symbol!, target.symbol!, errorReporter)) return true; + if (s & TypeFlags.Enum && t & TypeFlags.Enum && isEnumTypeRelatedTo(source.symbol, target.symbol, errorReporter)) return true; if (s & TypeFlags.EnumLiteral && t & TypeFlags.EnumLiteral) { - if (s & TypeFlags.Union && t & TypeFlags.Union && isEnumTypeRelatedTo(source.symbol!, target.symbol!, errorReporter)) return true; + 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; @@ -14956,10 +14956,10 @@ namespace ts { propLoop: for (const prop of node.properties) { if (!prop.symbol) continue; if (prop.kind !== SyntaxKind.PropertyAssignment) continue; - if (isDiscriminantProperty(contextualType, prop.symbol!.escapedName)) { + if (isDiscriminantProperty(contextualType, prop.symbol.escapedName)) { const discriminatingType = getTypeOfNode(prop.initializer)!; // TODO: GH#18217 for (const type of (contextualType as UnionType).types) { - const targetType = getTypeOfPropertyOfType(type, prop.symbol!.escapedName); + const targetType = getTypeOfPropertyOfType(type, prop.symbol.escapedName); if (targetType && checkTypeAssignableTo(discriminatingType, targetType, /*errorNode*/ undefined)) { if (match) { if (type === match) continue; // Finding multiple fields which discriminate to the same type is fine @@ -15157,7 +15157,7 @@ namespace ts { let apparentAttributesType = attributesType; const intrinsicClassAttribs = getJsxType(JsxNames.IntrinsicClassAttributes, context); if (intrinsicClassAttribs !== unknownType) { - const typeParams = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(intrinsicClassAttribs.symbol!); + const typeParams = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(intrinsicClassAttribs.symbol); const hostClassType = getReturnTypeOfSignature(sig); apparentAttributesType = intersectTypes( typeParams @@ -15713,7 +15713,7 @@ namespace ts { const jsxChildrenPropertyName = getJsxElementChildrenPropertyName(getJsxNamespaceAt(openingLikeElement)); for (const attributeDecl of attributes.properties) { - const member = attributeDecl.symbol!; + const member = attributeDecl.symbol; if (isJsxAttribute(attributeDecl)) { const exprType = checkJsxAttribute(attributeDecl, checkMode); @@ -15859,7 +15859,7 @@ namespace ts { const indexSignatureType = getIndexTypeOfType(intrinsicElementsType, IndexKind.String); if (indexSignatureType) { links.jsxFlags! |= JsxFlags.IntrinsicIndexedElement; - return links.resolvedSymbol = intrinsicElementsType.symbol!; + return links.resolvedSymbol = intrinsicElementsType.symbol; } // Wasn't found @@ -18295,8 +18295,8 @@ namespace ts { return true; } - const declaringClassDeclaration = getClassLikeDeclarationOfSymbol(declaration.parent.symbol!)!; - const declaringClass = getDeclaredTypeOfSymbol(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) if (!isNodeWithinClass(node, declaringClassDeclaration)) { @@ -19202,7 +19202,7 @@ namespace ts { } const links = getNodeLinks(node); - const type = getTypeOfSymbol(node.symbol!); + const type = getTypeOfSymbol(node.symbol); if (isTypeAny(type)) { return type; } @@ -20460,7 +20460,7 @@ namespace ts { // Only check rest parameter type if it's not a binding pattern. Since binding patterns are // not allowed in a rest parameter, we already have an error from checkGrammarParameterList. - if (node.dotDotDotToken && !isBindingPattern(node.name) && !isArrayType(getTypeOfSymbol(node.symbol!))) { + if (node.dotDotDotToken && !isBindingPattern(node.name) && !isArrayType(getTypeOfSymbol(node.symbol))) { error(node, Diagnostics.A_rest_parameter_must_be_of_an_array_type); } } @@ -20774,7 +20774,7 @@ namespace ts { } if (names.get(memberName)) { - error(getNameOfDeclaration(member.symbol!.valueDeclaration), Diagnostics.Duplicate_identifier_0, memberName); + error(getNameOfDeclaration(member.symbol.valueDeclaration), Diagnostics.Duplicate_identifier_0, memberName); error(member.name, Diagnostics.Duplicate_identifier_0, memberName); } else { @@ -22260,7 +22260,7 @@ namespace ts { case SyntaxKind.PropertyDeclaration: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: - if (member.kind === SyntaxKind.SetAccessor && member.symbol!.flags & SymbolFlags.GetAccessor) { + if (member.kind === SyntaxKind.SetAccessor && member.symbol.flags & SymbolFlags.GetAccessor) { // Already would have reported an error on the getter. break; } @@ -22271,8 +22271,8 @@ namespace ts { break; case SyntaxKind.Constructor: for (const parameter of (member).parameters) { - if (!parameter.symbol!.isReferenced && hasModifier(parameter, ModifierFlags.Private)) { - addDiagnostic(UnusedKind.Local, createDiagnosticForNode(parameter.name, Diagnostics.Property_0_is_declared_but_its_value_is_never_read, symbolName(parameter.symbol!))); + if (!parameter.symbol.isReferenced && hasModifier(parameter, ModifierFlags.Private)) { + addDiagnostic(UnusedKind.Local, createDiagnosticForNode(parameter.name, Diagnostics.Property_0_is_declared_but_its_value_is_never_read, symbolName(parameter.symbol))); } } break; @@ -22296,8 +22296,8 @@ namespace ts { const typeParameters = getEffectiveTypeParameterDeclarations(node); if (!(node.flags & NodeFlags.Ambient) && typeParameters && last(getSymbolOfNode(node)!.declarations) === node) { for (const typeParameter of typeParameters) { - 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!))); + 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))); } } } @@ -23309,7 +23309,7 @@ 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 { @@ -23511,8 +23511,8 @@ namespace ts { } function checkIndexConstraints(type: Type) { - const declaredNumberIndexer = getIndexDeclarationOfSymbol(type.symbol!, IndexKind.Number); - const declaredStringIndexer = getIndexDeclarationOfSymbol(type.symbol!, IndexKind.String); + const declaredNumberIndexer = getIndexDeclarationOfSymbol(type.symbol, IndexKind.Number); + const declaredStringIndexer = getIndexDeclarationOfSymbol(type.symbol, IndexKind.String); const stringIndexType = getIndexTypeOfType(type, IndexKind.String); const numberIndexType = getIndexTypeOfType(type, IndexKind.Number); @@ -23524,7 +23524,7 @@ namespace ts { checkIndexConstraintForProperty(prop, propType, type, declaredNumberIndexer, numberIndexType, IndexKind.Number); }); - 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. @@ -23546,7 +23546,7 @@ namespace ts { // condition 'errorNode === undefined' may appear if types does not declare nor string neither number indexer if (!errorNode && (getObjectFlags(type) & ObjectFlags.Interface)) { const someBaseTypeHasBothIndexers = forEach(getBaseTypes(type), base => getIndexTypeOfType(base, IndexKind.String) && getIndexTypeOfType(base, IndexKind.Number)); - errorNode = someBaseTypeHasBothIndexers ? undefined : type.symbol!.declarations[0]; + errorNode = someBaseTypeHasBothIndexers ? undefined : type.symbol.declarations[0]; } } @@ -23592,7 +23592,7 @@ namespace ts { // check if any base class already has both property and indexer. // check should be performed only if 'type' is the first type that brings property\indexer together const someBaseClassHasBothPropertyAndIndexer = forEach(getBaseTypes(containingType), base => getPropertyOfObjectType(base, prop.escapedName) && getIndexTypeOfType(base, indexKind)); - errorNode = someBaseClassHasBothPropertyAndIndexer ? undefined : containingType.symbol!.declarations[0]; + errorNode = someBaseClassHasBothPropertyAndIndexer ? undefined : containingType.symbol.declarations[0]; } if (errorNode && !isTypeAssignableTo(propertyType, indexType)) { @@ -23690,7 +23690,7 @@ namespace ts { // If the type parameter node does not have the same as the resolved type // parameter at this position, we report an error. - if (source.name.escapedText !== target.symbol!.escapedName) { + if (source.name.escapedText !== target.symbol.escapedName) { return false; } @@ -23876,9 +23876,9 @@ 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!)); + error(node, Diagnostics.Cannot_extend_a_class_0_Class_constructor_is_marked_as_private, getFullyQualifiedName(type.symbol)); } } } @@ -23932,7 +23932,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), @@ -25262,7 +25262,7 @@ namespace ts { case SyntaxKind.ClassExpression: const className = (location).name; if (className) { - copySymbol(location.symbol!, meaning); + copySymbol(location.symbol, meaning); } // falls through // this fall-through is necessary because we would like to handle @@ -25280,7 +25280,7 @@ namespace ts { case SyntaxKind.FunctionExpression: const funcName = (location).name; if (funcName) { - copySymbol(location.symbol!, meaning); + copySymbol(location.symbol, meaning); } break; } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 4047442c485b4..0c04b83436fb9 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -974,7 +974,7 @@ namespace ts { function emitIdentifier(node: Identifier) { const writeText = node.symbol ? writeSymbol : write; - writeText(getTextOfNode(node, /*includeTrivia*/ false), node.symbol!); + writeText(getTextOfNode(node, /*includeTrivia*/ false), node.symbol); emitList(node, node.typeArguments, ListFormat.TypeParameters); // Call emitList directly since it could be an array of TypeParameterDeclarations _or_ type arguments } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 6538f2867087f..a704d09201c9f 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -568,7 +568,7 @@ namespace ts { /* @internal */ id?: number; // Unique id (used to look up NodeLinks) 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) @@ -3371,8 +3371,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 @@ -3642,7 +3642,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) diff --git a/src/harness/unittests/symbolWalker.ts b/src/harness/unittests/symbolWalker.ts index e363b79abaf14..9fc0a2c398ad9 100644 --- a/src/harness/unittests/symbolWalker.ts +++ b/src/harness/unittests/symbolWalker.ts @@ -41,7 +41,7 @@ export default function foo(a: number, b: Bar): void {}`, (file, checker) => { foundCount++; return true; }); - const symbols = checker.getExportsOfModule(file.symbol!); + const symbols = checker.getExportsOfModule(file.symbol); for (const symbol of symbols) { walker.walkSymbol(symbol); } diff --git a/src/services/codefixes/convertFunctionToEs6Class.ts b/src/services/codefixes/convertFunctionToEs6Class.ts index 68f81fdd86dac..fbed5d88cc37d 100644 --- a/src/services/codefixes/convertFunctionToEs6Class.ts +++ b/src/services/codefixes/convertFunctionToEs6Class.ts @@ -176,7 +176,7 @@ namespace ts.codefix { return undefined; } - const memberElements = createClassElementsFromSymbol(initializer.symbol!); + const memberElements = createClassElementsFromSymbol(initializer.symbol); if (initializer.body) { memberElements.unshift(createConstructor(/*decorators*/ undefined, /*modifiers*/ undefined, initializer.parameters, initializer.body)); } diff --git a/src/services/codefixes/fixAddMissingMember.ts b/src/services/codefixes/fixAddMissingMember.ts index 0f846a1e307ae..021ec76554601 100644 --- a/src/services/codefixes/fixAddMissingMember.ts +++ b/src/services/codefixes/fixAddMissingMember.ts @@ -65,7 +65,7 @@ namespace ts.codefix { const classDeclaration = symbol && symbol.declarations && find(symbol.declarations, isClassLike); if (!classDeclaration) return undefined; - const makeStatic = (leftExpressionType as TypeReference).target !== checker.getDeclaredTypeOfSymbol(symbol!); + const makeStatic = (leftExpressionType as TypeReference).target !== checker.getDeclaredTypeOfSymbol(symbol); const classDeclarationSourceFile = classDeclaration.getSourceFile(); const inJs = isSourceFileJavaScript(classDeclarationSourceFile); const call = tryCast(parent.parent, isCallExpression); diff --git a/src/services/codefixes/fixStrictClassInitialization.ts b/src/services/codefixes/fixStrictClassInitialization.ts index 3742d3c6f2ec9..0715052e8db26 100644 --- a/src/services/codefixes/fixStrictClassInitialization.ts +++ b/src/services/codefixes/fixStrictClassInitialization.ts @@ -125,13 +125,13 @@ namespace ts.codefix { return firstDefined(type.types, t => getDefaultValueFromType(checker, t)); } else if (type.isClass()) { - const classDeclaration = getClassLikeDeclarationOfSymbol(type.symbol!); + const classDeclaration = getClassLikeDeclarationOfSymbol(type.symbol); if (!classDeclaration || hasModifier(classDeclaration, ModifierFlags.Abstract)) return undefined; const constructorDeclaration = getFirstConstructorWithBody(classDeclaration); if (constructorDeclaration && constructorDeclaration.parameters.length) return undefined; - return createNew(createIdentifier(type.symbol!.name), /*typeArguments*/ undefined, /*argumentsArray*/ undefined); + return createNew(createIdentifier(type.symbol.name), /*typeArguments*/ undefined, /*argumentsArray*/ undefined); } return undefined; } diff --git a/src/services/codefixes/helpers.ts b/src/services/codefixes/helpers.ts index 921ff859f966f..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); diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index b26b1f78aeb9b..75e1f30b595ed 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -799,7 +799,7 @@ namespace ts.codefix { } for (const sourceFile of allSourceFiles) { if (isExternalOrCommonJsModule(sourceFile)) { - cb(sourceFile.symbol!, sourceFile); + cb(sourceFile.symbol, sourceFile); } } } diff --git a/src/services/completions.ts b/src/services/completions.ts index 58d8fe6aa3e37..73947e298f7b4 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -1617,7 +1617,7 @@ namespace ts.Completions { // 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)!; // TODO: GH#18217 - return typeChecker.getPropertiesOfType(classElementModifierFlags & ModifierFlags.Static ? typeChecker.getTypeOfSymbolAtLocation(type.symbol!, decl) : type); + return typeChecker.getPropertiesOfType(classElementModifierFlags & ModifierFlags.Static ? typeChecker.getTypeOfSymbolAtLocation(type.symbol, decl) : type); }); symbols = filterClassMembersList(baseSymbols, decl.members, classElementModifierFlags); } diff --git a/src/services/documentHighlights.ts b/src/services/documentHighlights.ts index 0b8f5b00fcf51..21649227f8e22 100644 --- a/src/services/documentHighlights.ts +++ b/src/services/documentHighlights.ts @@ -81,7 +81,7 @@ namespace ts.DocumentHighlights { } function getFromAllDeclarations(nodeTest: (node: Node) => node is T, keywords: ReadonlyArray): HighlightSpan[] | undefined { - return useParent(node.parent, nodeTest, decl => mapDefined(decl.symbol!.declarations, d => + return useParent(node.parent, nodeTest, decl => mapDefined(decl.symbol.declarations, d => nodeTest(d) ? find(d.getChildren(sourceFile), c => contains(keywords, c.kind)) : undefined)); } diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index eee675beb69d8..a4a5856a0fbd5 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -233,7 +233,7 @@ namespace ts.FindAllReferences.Core { export function getReferencedSymbolsForNode(position: number, node: Node, program: Program, sourceFiles: ReadonlyArray, cancellationToken: CancellationToken, options: Options = {}, sourceFilesSet: ReadonlyMap = arrayToSet(sourceFiles, f => f.fileName)): SymbolAndEntries[] | undefined { if (isSourceFile(node)) { const reference = GoToDefinition.getReferenceAtPosition(node, position, program); - return reference && getReferencedSymbolsForModule(program, program.getTypeChecker().getMergedSymbol(reference.file.symbol!), sourceFiles, sourceFilesSet); + return reference && getReferencedSymbolsForModule(program, program.getTypeChecker().getMergedSymbol(reference.file.symbol), sourceFiles, sourceFilesSet); } if (!options.implementations) { @@ -1062,8 +1062,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; } @@ -1235,7 +1234,7 @@ namespace ts.FindAllReferences.Core { return container && (ModifierFlags.Static & getModifierFlags(container)) === staticFlag && container.parent.symbol === searchSpaceNode.symbol ? nodeEntry(node) : undefined; }); - return [{ definition: { type: "symbol", symbol: searchSpaceNode.symbol! }, references }]; + return [{ definition: { type: "symbol", symbol: searchSpaceNode.symbol }, references }]; } function getReferencesForThisKeyword(thisOrSuperKeyword: Node, sourceFiles: ReadonlyArray, cancellationToken: CancellationToken): SymbolAndEntries[] | undefined { @@ -1417,7 +1416,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)); })); } } diff --git a/src/services/goToDefinition.ts b/src/services/goToDefinition.ts index 1a429ea4e0a41..b94bd8f1b6a98 100644 --- a/src/services/goToDefinition.ts +++ b/src/services/goToDefinition.ts @@ -32,7 +32,7 @@ namespace ts.GoToDefinition { const sigInfo = createDefinitionFromSignatureDeclaration(typeChecker, calledDeclaration); // For a function, if this is the original function definition, return just sigInfo. // If this is the original constructor definition, parent is the class. - return typeChecker.getRootSymbols(symbol).some(s => calledDeclaration.symbol === s || calledDeclaration.symbol!.parent === s) + return typeChecker.getRootSymbols(symbol).some(s => calledDeclaration.symbol === s || calledDeclaration.symbol.parent === s) ? [sigInfo] : [sigInfo, ...getDefinitionFromSymbol(typeChecker, symbol, node)!]; } @@ -242,7 +242,7 @@ namespace ts.GoToDefinition { } function createDefinitionFromSignatureDeclaration(typeChecker: TypeChecker, decl: SignatureDeclaration): DefinitionInfo { - return createDefinitionInfo(decl, typeChecker, decl.symbol!, decl); + return createDefinitionInfo(decl, typeChecker, decl.symbol, decl); } export function findReferenceInPosition(refs: ReadonlyArray, pos: number): FileReference | undefined { diff --git a/src/services/importTracker.ts b/src/services/importTracker.ts index ec283d16f98ed..8f744b1393efd 100644 --- a/src/services/importTracker.ts +++ b/src/services/importTracker.ts @@ -167,7 +167,7 @@ namespace ts.FindAllReferences { return; } - const moduleSymbol = checker.getMergedSymbol(sourceFileLike.symbol!); + const moduleSymbol = checker.getMergedSymbol(sourceFileLike.symbol); Debug.assert(!!(moduleSymbol.flags & SymbolFlags.Module)); const directImports = getDirectImports(moduleSymbol); if (directImports) { @@ -490,7 +490,7 @@ namespace ts.FindAllReferences { function getExportAssignmentExport(ex: ExportAssignment): ExportedSymbol { // Get the symbol for the `export =` node; its parent is the module it's the export of. - const exportingModuleSymbol = Debug.assertDefined(ex.symbol!.parent, "Expected export symbol to have a parent"); + const exportingModuleSymbol = Debug.assertDefined(ex.symbol.parent, "Expected export symbol to have a parent"); const exportKind = ex.isExportEquals ? ExportKind.ExportEquals : ExportKind.Default; return { kind: ImportExport.Export, symbol, exportInfo: { exportingModuleSymbol, exportKind } }; } @@ -632,7 +632,7 @@ namespace ts.FindAllReferences { } function getContainingModuleSymbol(importer: Importer, checker: TypeChecker): Symbol { - return checker.getMergedSymbol(getSourceFileLikeForImportDeclaration(importer).symbol!); + return checker.getMergedSymbol(getSourceFileLikeForImportDeclaration(importer).symbol); } function getSourceFileLikeForImportDeclaration(node: ImporterOrCallExpression): SourceFileLike { diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index 0d17e040483c0..c0e287346a357 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -377,7 +377,7 @@ namespace ts.refactor.extractSymbol { (errors || (errors = [] as Diagnostic[])).push(createDiagnosticForNode(node, Messages.cannotExtractExportedEntity)); return true; } - declarations.push(node.symbol!); + declarations.push(node.symbol); } // Some things can't be extracted in certain situations @@ -872,7 +872,7 @@ namespace ts.refactor.extractSymbol { typeElements.push(createPropertySignature( /*modifiers*/ undefined, - /*name*/ variableDeclaration.symbol!.name, + /*name*/ variableDeclaration.symbol.name, /*questionToken*/ undefined, /*type*/ variableType, /*initializer*/ undefined)); @@ -907,7 +907,7 @@ namespace ts.refactor.extractSymbol { newNodes.push(createVariableStatement( /*modifiers*/ undefined, createVariableDeclarationList( - [createVariableDeclaration(variableDeclaration.symbol!.name, getTypeDeepCloneUnionUndefined(variableDeclaration.type))], + [createVariableDeclaration(variableDeclaration.symbol.name, getTypeDeepCloneUnionUndefined(variableDeclaration.type))], flags))); } } @@ -1319,7 +1319,7 @@ namespace ts.refactor.extractSymbol { exposedVariableDeclarations: ReadonlyArray, writes: ReadonlyArray | undefined ): ShorthandPropertyAssignment[] { - const variableAssignments = map(exposedVariableDeclarations, v => createShorthandPropertyAssignment(v.symbol!.name)); + 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! @@ -1704,7 +1704,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); diff --git a/src/services/services.ts b/src/services/services.ts index 46b823a778682..572d2d693dc19 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -505,7 +505,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!); // TODO: GH#18217 + 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); } diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts index f630caad2dc8a..7a70f23768489 100644 --- a/src/services/signatureHelp.ts +++ b/src/services/signatureHelp.ts @@ -444,7 +444,7 @@ namespace ts.SignatureHelp { }); return { - name: typeParameter.symbol!.name, + name: typeParameter.symbol.name, documentation: emptyArray, displayParts, isOptional: false diff --git a/src/services/suggestionDiagnostics.ts b/src/services/suggestionDiagnostics.ts index 23f2182bd3768..209f48bfb9e54 100644 --- a/src/services/suggestionDiagnostics.ts +++ b/src/services/suggestionDiagnostics.ts @@ -16,8 +16,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)); } } diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts index 9d1cf050400ca..9fa179ce8cba4 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -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; @@ -212,7 +212,7 @@ namespace ts.SymbolDisplay { 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)); + addRange(displayParts, symbolToDisplayParts(typeChecker, type!.symbol, enclosingDeclaration, /*meaning*/ undefined, SymbolFormatFlags.AllowAnyNodeKind | SymbolFormatFlags.WriteTypeParametersOrArguments)); displayParts.push(lineBreakPart()); } if (useConstructSignatures) { @@ -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); @@ -342,7 +342,7 @@ namespace ts.SymbolDisplay { displayParts.push(spacePart()); } else if (declaration.kind !== SyntaxKind.CallSignature && (declaration).name) { - addFullSymbolName(declaration.symbol!); + addFullSymbolName(declaration.symbol); } addRange(displayParts, signatureToDisplayParts(typeChecker, signature, sourceFile, TypeFormatFlags.WriteTypeArgumentsOfSignature)); } @@ -353,8 +353,8 @@ namespace ts.SymbolDisplay { addInPrefix(); displayParts.push(keywordPart(SyntaxKind.TypeKeyword)); displayParts.push(spacePart()); - addFullSymbolName(declaration.symbol!); - writeTypeParametersOfSymbol(declaration.symbol!, sourceFile); + addFullSymbolName(declaration.symbol); + writeTypeParametersOfSymbol(declaration.symbol, sourceFile); } } } From 03d284d2ef403f82224c73f65c76a860e4d0657f Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Wed, 25 Apr 2018 11:27:12 -0700 Subject: [PATCH 33/42] Make `flags` non-nullable to reduce assertions --- src/compiler/binder.ts | 4 +- src/compiler/checker.ts | 164 +++++++++--------- src/compiler/factory.ts | 46 ++--- src/compiler/sourcemap.ts | 14 +- src/compiler/transformers/es2015.ts | 2 +- src/compiler/transformers/es2017.ts | 2 +- src/compiler/transformers/esnext.ts | 2 +- src/compiler/transformers/ts.ts | 2 +- src/compiler/types.ts | 9 +- src/compiler/utilities.ts | 2 +- src/services/services.ts | 7 +- src/services/symbolDisplay.ts | 4 +- src/services/utilities.ts | 12 +- .../reference/api/tsserverlibrary.d.ts | 3 +- tests/baselines/reference/api/typescript.d.ts | 3 +- 15 files changed, 143 insertions(+), 133 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 0b11733da4318..6fad099337fd7 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1872,7 +1872,7 @@ namespace ts { } function checkStrictModeNumericLiteral(node: NumericLiteral) { - if (inStrictMode && node.numericLiteralFlags! & TokenFlags.Octal) { + if (inStrictMode && node.numericLiteralFlags & TokenFlags.Octal) { file.bindDiagnostics.push(createDiagnosticForNode(node, Diagnostics.Octal_literals_are_not_allowed_in_strict_mode)); } } @@ -3507,7 +3507,7 @@ namespace ts { break; case SyntaxKind.NumericLiteral: - if ((node).numericLiteralFlags! & TokenFlags.BinaryOrOctalSpecifier) { + if ((node).numericLiteralFlags & TokenFlags.BinaryOrOctalSpecifier) { transformFlags |= TransformFlags.AssertES2015; } break; diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7b143e98f3ee9..eee160d6bd798 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -316,7 +316,7 @@ namespace ts { checkSourceFile(file); const diagnostics: Diagnostic[] = []; - Debug.assert(!!(getNodeLinks(file).flags! & NodeCheckFlags.TypeChecked)); + Debug.assert(!!(getNodeLinks(file).flags & NodeCheckFlags.TypeChecked)); checkUnusedIdentifiers(allPotentiallyUnusedIdentifiers.get(file.fileName)!, (kind, diag) => { if (!unusedIsError(kind)) { diagnostics.push({ ...diag, category: DiagnosticCategory.Suggestion }); @@ -651,8 +651,8 @@ namespace ts { buildTypeDisplay(type, writer, enclosingDeclaration?, flags?) { typeToString(type, enclosingDeclaration, flags, emitTextWriterWrapper(writer)); }, - buildSymbolDisplay(symbol, writer, enclosingDeclaration?, meaning?, flags?) { - symbolToString(symbol, enclosingDeclaration, meaning, flags! | SymbolFormatFlags.AllowAnyNodeKind, emitTextWriterWrapper(writer)); + buildSymbolDisplay(symbol, writer, enclosingDeclaration?, meaning?, flags = SymbolFormatFlags.None) { + symbolToString(symbol, enclosingDeclaration, meaning, flags | SymbolFormatFlags.AllowAnyNodeKind, emitTextWriterWrapper(writer)); }, buildSignatureDisplay(signature, writer, enclosing?, flags?, kind?) { signatureToString(signature, enclosing, flags, kind, emitTextWriterWrapper(writer)); @@ -1033,7 +1033,7 @@ 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) { @@ -2889,12 +2889,12 @@ 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) { let sigOutput: SyntaxKind; - if (flags! & TypeFormatFlags.WriteArrowStyleSignature) { + if (flags & TypeFormatFlags.WriteArrowStyleSignature) { sigOutput = kind === SignatureKind.Construct ? SyntaxKind.ConstructorType : SyntaxKind.FunctionType; } else { @@ -2924,8 +2924,8 @@ namespace ts { return result; } - function toNodeBuilderFlags(flags?: TypeFormatFlags): NodeBuilderFlags { - return flags! & TypeFormatFlags.NodeBuilderFlagsMask; + function toNodeBuilderFlags(flags = TypeFormatFlags.None): NodeBuilderFlags { + return flags & TypeFormatFlags.NodeBuilderFlagsMask; } function createNodeBuilder() { @@ -2991,7 +2991,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, symbolStack: undefined, @@ -3000,8 +3000,8 @@ namespace ts { } function typeToTypeNodeHelper(type: Type, context: NodeBuilderContext): TypeNode | undefined { - const inTypeAlias = context.flags! & NodeBuilderFlags.InTypeAlias; - context.flags! &= ~NodeBuilderFlags.InTypeAlias; + const inTypeAlias = context.flags & NodeBuilderFlags.InTypeAlias; + context.flags &= ~NodeBuilderFlags.InTypeAlias; if (!type) { context.encounteredError = true; @@ -3040,7 +3040,7 @@ namespace ts { return (type).intrinsicName === "true" ? createTrue() : createFalse(); } if (type.flags & TypeFlags.UniqueESSymbol) { - if (!(context.flags! & NodeBuilderFlags.AllowUniqueESSymbolType)) { + if (!(context.flags & NodeBuilderFlags.AllowUniqueESSymbolType)) { if (isValueSymbolAccessible(type.symbol, context.enclosingDeclaration!)) { return symbolToTypeNode(type.symbol, context, SymbolFlags.Value); } @@ -3069,8 +3069,8 @@ namespace ts { return createKeywordTypeNode(SyntaxKind.ObjectKeyword); } if (type.flags & TypeFlags.TypeParameter && (type as TypeParameter).isThisType) { - if (context.flags! & NodeBuilderFlags.InObjectTypeLiteral) { - if (!context.encounteredError && !(context.flags! & NodeBuilderFlags.AllowThisInObjectLiteral)) { + if (context.flags & NodeBuilderFlags.InObjectTypeLiteral) { + if (!context.encounteredError && !(context.flags & NodeBuilderFlags.AllowThisInObjectLiteral)) { context.encounteredError = true; } if (context.tracker!.reportInaccessibleThisError) { @@ -3094,7 +3094,7 @@ namespace ts { // Ignore constraint/default when creating a usage (as opposed to declaration) of a type parameter. return createTypeReferenceNode(name, /*typeArguments*/ undefined); } - if (!inTypeAlias && type.aliasSymbol && (context.flags! & NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope || isTypeSymbolAccessible(type.aliasSymbol, context.enclosingDeclaration))) { + if (!inTypeAlias && type.aliasSymbol && (context.flags & NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope || isTypeSymbolAccessible(type.aliasSymbol, context.enclosingDeclaration))) { const name = symbolToTypeReferenceName(type.aliasSymbol); const typeArgumentNodes = mapToTypeNodes(type.aliasTypeArguments, context); return createTypeReferenceNode(name, typeArgumentNodes); @@ -3107,7 +3107,7 @@ namespace ts { return unionOrIntersectionTypeNode; } else { - if (!context.encounteredError && !(context.flags! & NodeBuilderFlags.AllowEmptyUnionOrIntersection)) { + if (!context.encounteredError && !(context.flags & NodeBuilderFlags.AllowEmptyUnionOrIntersection)) { context.encounteredError = true; } return undefined; @@ -3163,7 +3163,7 @@ namespace ts { return symbolToTypeNode(symbol, context, isInstanceType); } // Always use 'typeof T' for type of class, enum, and module objects - else if (symbol.flags & SymbolFlags.Class && !getBaseTypeVariableOfClass(symbol) && !(symbol.valueDeclaration.kind === SyntaxKind.ClassExpression && context.flags! & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral) || + else if (symbol.flags & SymbolFlags.Class && !getBaseTypeVariableOfClass(symbol) && !(symbol.valueDeclaration.kind === SyntaxKind.ClassExpression && context.flags & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral) || symbol.flags & (SymbolFlags.Enum | SymbolFlags.ValueModule) || shouldWriteTypeOfFunctionSymbol()) { return symbolToTypeNode(symbol, context, SymbolFlags.Value); @@ -3212,9 +3212,9 @@ namespace ts { declaration.parent.kind === SyntaxKind.SourceFile || declaration.parent.kind === SyntaxKind.ModuleBlock)); if (isStaticMethodSymbol || isNonLocalFunctionSymbol) { // typeof is allowed only for static/non local functions - return (!!(context.flags! & NodeBuilderFlags.UseTypeOfFunction) || contains(context.symbolStack, symbol)) && // it is type of the symbol uses itself recursively + return (!!(context.flags & NodeBuilderFlags.UseTypeOfFunction) || contains(context.symbolStack, symbol)) && // it is type of the symbol uses itself recursively // 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 + (!(context.flags & NodeBuilderFlags.UseStructuralFallback) || isValueSymbolAccessible(symbol, context.enclosingDeclaration!)); // TODO: GH#18217 } } } @@ -3245,11 +3245,11 @@ namespace ts { } const savedFlags = context.flags; - context.flags! |= NodeBuilderFlags.InObjectTypeLiteral; + context.flags |= NodeBuilderFlags.InObjectTypeLiteral; const members = createTypeNodesFromResolvedType(resolved); context.flags = savedFlags; const typeLiteralNode = createTypeLiteralNode(members); - return setEmitFlags(typeLiteralNode, (context.flags! & NodeBuilderFlags.MultilineObjectLiterals) ? 0 : EmitFlags.SingleLine); + return setEmitFlags(typeLiteralNode, (context.flags & NodeBuilderFlags.MultilineObjectLiterals) ? 0 : EmitFlags.SingleLine); } function symbolToTypeReferenceName(symbol: Symbol) { @@ -3261,7 +3261,7 @@ namespace ts { function typeReferenceToTypeNode(type: TypeReference) { const typeArguments: Type[] = type.typeArguments || emptyArray; if (type.target === globalArrayType) { - if (context.flags! & NodeBuilderFlags.WriteArrayAsGenericType) { + if (context.flags & NodeBuilderFlags.WriteArrayAsGenericType) { const typeArgumentNode = typeToTypeNodeHelper(typeArguments[0], context)!; return createTypeReferenceNode("Array", [typeArgumentNode]); } @@ -3276,13 +3276,13 @@ namespace ts { return createTupleTypeNode(tupleConstituentNodes); } } - if (context.encounteredError || (context.flags! & NodeBuilderFlags.AllowEmptyTuple)) { + if (context.encounteredError || (context.flags & NodeBuilderFlags.AllowEmptyTuple)) { return createTupleTypeNode([]); } context.encounteredError = true; return undefined; } - else if (context.flags! & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral && + else if (context.flags & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral && type.symbol.valueDeclaration && isClassLike(type.symbol.valueDeclaration) && !isValueSymbolAccessible(type.symbol, context.enclosingDeclaration!) @@ -3390,7 +3390,7 @@ namespace ts { } for (const propertySymbol of properties) { - if (context.flags! & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral) { + if (context.flags & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral) { if (propertySymbol.flags & SymbolFlags.Prototype) { continue; } @@ -3398,7 +3398,7 @@ namespace ts { context.tracker!.reportPrivateInBaseOfClassExpression!(unescapeLeadingUnderscores(propertySymbol.escapedName)); } } - const propertyType = getCheckFlags(propertySymbol) & CheckFlags.ReverseMapped && context.flags! & NodeBuilderFlags.InReverseMappedType ? + const propertyType = getCheckFlags(propertySymbol) & CheckFlags.ReverseMapped && context.flags & NodeBuilderFlags.InReverseMappedType ? anyType : getTypeOfSymbol(propertySymbol); const saveEnclosingDeclaration = context.enclosingDeclaration; context.enclosingDeclaration = undefined; @@ -3427,7 +3427,7 @@ namespace ts { } else { const savedFlags = context.flags; - context.flags! |= !!(getCheckFlags(propertySymbol) & CheckFlags.ReverseMapped) ? NodeBuilderFlags.InReverseMappedType : 0; + context.flags |= !!(getCheckFlags(propertySymbol) & CheckFlags.ReverseMapped) ? NodeBuilderFlags.InReverseMappedType : 0; const propertyTypeNode = propertyType ? typeToTypeNodeHelper(propertyType, context) : createKeywordTypeNode(SyntaxKind.AnyKeyword); context.flags = savedFlags; @@ -3476,7 +3476,7 @@ namespace ts { indexerTypeNode, /*initializer*/ undefined); const typeNode = typeToTypeNodeHelper(indexInfo.type || anyType, context)!; // TODO: GH#18217 - if (!indexInfo.type && !(context.flags! & NodeBuilderFlags.AllowEmptyIndexInfoType)) { + if (!indexInfo.type && !(context.flags & NodeBuilderFlags.AllowEmptyIndexInfoType)) { context.encounteredError = true; } return createIndexSignature( @@ -3489,7 +3489,7 @@ namespace ts { function signatureToSignatureDeclarationHelper(signature: Signature, kind: SyntaxKind, context: NodeBuilderContext): SignatureDeclaration { let typeParameters: TypeParameterDeclaration[] | undefined; let typeArguments: TypeNode[] | undefined; - if (context.flags! & NodeBuilderFlags.WriteTypeArgumentsOfSignature && signature.target && signature.mapper && signature.target.typeParameters) { + if (context.flags & NodeBuilderFlags.WriteTypeArgumentsOfSignature && signature.target && signature.mapper && signature.target.typeParameters) { typeArguments = signature.target.typeParameters.map(parameter => typeToTypeNodeHelper(instantiateType(parameter, signature.mapper!), context)!); // TODO: GH#18217 } else { @@ -3515,7 +3515,7 @@ namespace ts { const returnType = getReturnTypeOfSignature(signature); returnTypeNode = returnType && typeToTypeNodeHelper(returnType, context); } - if (context.flags! & NodeBuilderFlags.SuppressAnyReturnType) { + if (context.flags & NodeBuilderFlags.SuppressAnyReturnType) { if (returnTypeNode && returnTypeNode.kind === SyntaxKind.AnyKeyword) { returnTypeNode = undefined; } @@ -3528,7 +3528,7 @@ namespace ts { function typeParameterToDeclaration(type: TypeParameter, context: NodeBuilderContext, constraint = getConstraintFromTypeParameter(type)): TypeParameterDeclaration { const savedContextFlags = context.flags; - context.flags! &= ~NodeBuilderFlags.WriteTypeParametersInQualifiedName; // Avoids potential infinite loop when building for a claimspace with a generic + context.flags &= ~NodeBuilderFlags.WriteTypeParametersInQualifiedName; // Avoids potential infinite loop when building for a claimspace with a generic const name = symbolToName(type.symbol, context, SymbolFlags.Type, /*expectsIdentifier*/ true); const constraintNode = constraint && typeToTypeNodeHelper(constraint, context); const defaultParameter = getDefaultFromTypeParameter(type); @@ -3547,7 +3547,7 @@ namespace ts { } const parameterTypeNode = typeToTypeNodeHelper(parameterType, context); - const modifiers = !(context.flags! & NodeBuilderFlags.OmitParameterModifiers) && preserveModifierFlags && parameterDeclaration && parameterDeclaration.modifiers ? parameterDeclaration.modifiers.map(getSynthesizedClone) : undefined; + const modifiers = !(context.flags & NodeBuilderFlags.OmitParameterModifiers) && preserveModifierFlags && parameterDeclaration && parameterDeclaration.modifiers ? parameterDeclaration.modifiers.map(getSynthesizedClone) : undefined; const dotDotDotToken = !parameterDeclaration || isRestParameter(parameterDeclaration) ? createToken(SyntaxKind.DotDotDotToken) : undefined; const name = parameterDeclaration ? parameterDeclaration.name ? @@ -3585,7 +3585,7 @@ namespace ts { // 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)) { + if (!isTypeParameter && (context.enclosingDeclaration || context.flags & NodeBuilderFlags.UseFullyQualifiedType)) { chain = getSymbolChain(symbol, meaning, /*endOfChain*/ true)!; Debug.assert(chain && chain.length > 0); } @@ -3596,7 +3596,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 accessibleSymbolChain = getAccessibleSymbolChain(symbol, context.enclosingDeclaration, meaning, !!(context.flags & NodeBuilderFlags.UseOnlyExternalAliasing)); let parentSymbol: Symbol | undefined; if (!accessibleSymbolChain || @@ -3642,7 +3642,7 @@ namespace ts { Debug.assert(chain && 0 <= index && index < chain.length); const symbol = chain[index]; let typeParameterNodes: ReadonlyArray | ReadonlyArray | undefined; - if (context.flags! & NodeBuilderFlags.WriteTypeParametersInQualifiedName && index < (chain.length - 1)) { + if (context.flags & NodeBuilderFlags.WriteTypeParametersInQualifiedName && index < (chain.length - 1)) { const parentSymbol = symbol; const nextSymbol = chain[index + 1]; if (getCheckFlags(nextSymbol) & CheckFlags.Instantiated) { @@ -3661,9 +3661,9 @@ namespace ts { function symbolToTypeNode(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags): TypeQueryNode | TypeReferenceNode | ImportTypeNode { const chain = lookupSymbolChain(symbol, context, meaning); - context.flags! |= NodeBuilderFlags.InInitialEntityName; + context.flags |= NodeBuilderFlags.InInitialEntityName; const rootName = getNameOfSymbolAsWritten(chain[0], context); - context.flags! ^= NodeBuilderFlags.InInitialEntityName; + context.flags ^= NodeBuilderFlags.InInitialEntityName; const isTypeOf = meaning === SymbolFlags.Value; if (ambientModuleSymbolRegex.test(rootName)) { @@ -3681,11 +3681,11 @@ namespace ts { const symbol = chain[index]; if (index === 0) { - context.flags! |= NodeBuilderFlags.InInitialEntityName; + context.flags |= NodeBuilderFlags.InInitialEntityName; } const symbolName = getNameOfSymbolAsWritten(symbol, context); if (index === 0) { - context.flags! ^= NodeBuilderFlags.InInitialEntityName; + context.flags ^= NodeBuilderFlags.InInitialEntityName; } const identifier = setEmitFlags(createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping); identifier.symbol = symbol; @@ -3701,7 +3701,7 @@ namespace ts { if (expectsIdentifier && chain.length !== 1 && !context.encounteredError - && !(context.flags! & NodeBuilderFlags.AllowQualifedNameInPlaceOfIdentifier)) { + && !(context.flags & NodeBuilderFlags.AllowQualifedNameInPlaceOfIdentifier)) { context.encounteredError = true; } return createEntityNameFromSymbolChain(chain, chain.length - 1); @@ -3711,11 +3711,11 @@ namespace ts { const symbol = chain[index]; if (index === 0) { - context.flags! |= NodeBuilderFlags.InInitialEntityName; + context.flags |= NodeBuilderFlags.InInitialEntityName; } const symbolName = getNameOfSymbolAsWritten(symbol, context); if (index === 0) { - context.flags! ^= NodeBuilderFlags.InInitialEntityName; + context.flags ^= NodeBuilderFlags.InInitialEntityName; } const identifier = setEmitFlags(createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping); identifier.symbol = symbol; @@ -3734,11 +3734,11 @@ namespace ts { const symbol = chain[index]; if (index === 0) { - context.flags! |= NodeBuilderFlags.InInitialEntityName; + context.flags |= NodeBuilderFlags.InInitialEntityName; } let symbolName = getNameOfSymbolAsWritten(symbol, context); if (index === 0) { - context.flags! ^= NodeBuilderFlags.InInitialEntityName; + context.flags ^= NodeBuilderFlags.InInitialEntityName; } let firstChar = symbolName.charCodeAt(0); const canUsePropertyAccess = isIdentifierStart(firstChar, languageVersion); @@ -3840,7 +3840,7 @@ namespace ts { interface NodeBuilderContext { enclosingDeclaration: Node | undefined; - flags: NodeBuilderFlags | undefined; + flags: NodeBuilderFlags; tracker: SymbolTracker | undefined; // State @@ -3861,9 +3861,9 @@ namespace ts { * It will also use a representation of a number as written instead of a decimal form, e.g. `0o11` instead of `9`. */ function getNameOfSymbolAsWritten(symbol: Symbol, context?: NodeBuilderContext): string { - if (context && symbol.escapedName === InternalSymbolName.Default && !(context.flags! & NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope) && + if (context && symbol.escapedName === InternalSymbolName.Default && !(context.flags & NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope) && // If it's not the first part of an entity name, it must print as `default` - (!(context.flags! & NodeBuilderFlags.InInitialEntityName) || + (!(context.flags & NodeBuilderFlags.InInitialEntityName) || // if the symbol is synthesized, it will only be referenced externally it must print as `default` !symbol.declarations || // if not in the same binding context (source file, module declaration), it must print as `default` @@ -3879,7 +3879,7 @@ namespace ts { if (declaration.parent && declaration.parent.kind === SyntaxKind.VariableDeclaration) { return declarationNameToString((declaration.parent).name); } - if (context && !context.encounteredError && !(context.flags! & NodeBuilderFlags.AllowAnonymousIdentifier)) { + if (context && !context.encounteredError && !(context.flags & NodeBuilderFlags.AllowAnonymousIdentifier)) { context.encounteredError = true; } switch (declaration.kind) { @@ -7045,7 +7045,7 @@ namespace ts { function containsArgumentsReference(declaration: SignatureDeclaration): boolean { const links = getNodeLinks(declaration); if (links.containsArgumentsReference === undefined) { - if (links.flags! & NodeCheckFlags.CaptureArguments) { + if (links.flags & NodeCheckFlags.CaptureArguments) { links.containsArgumentsReference = true; } else { @@ -13851,8 +13851,8 @@ namespace ts { function isParameterAssigned(symbol: Symbol) { const func = getRootDeclaration(symbol.valueDeclaration).parent; const links = getNodeLinks(func); - if (!(links.flags! & NodeCheckFlags.AssignmentsMarked)) { - links.flags! |= NodeCheckFlags.AssignmentsMarked; + if (!(links.flags & NodeCheckFlags.AssignmentsMarked)) { + links.flags |= NodeCheckFlags.AssignmentsMarked; if (!hasParentWithAssignmentsMarked(func)) { markParameterAssignments(func); } @@ -13861,7 +13861,7 @@ namespace ts { } function hasParentWithAssignmentsMarked(node: Node) { - return !!findAncestor(node.parent, node => isFunctionLike(node) && !!(getNodeLinks(node).flags! & NodeCheckFlags.AssignmentsMarked)); + return !!findAncestor(node.parent, node => isFunctionLike(node) && !!(getNodeLinks(node).flags & NodeCheckFlags.AssignmentsMarked)); } function markParameterAssignments(node: Node) { @@ -13946,7 +13946,7 @@ namespace ts { } } - getNodeLinks(container).flags! |= NodeCheckFlags.CaptureArguments; + getNodeLinks(container).flags |= NodeCheckFlags.CaptureArguments; return getTypeOfSymbol(symbol); } @@ -13968,8 +13968,8 @@ namespace ts { let container = getContainingClass(node); while (container !== undefined) { if (container === declaration && container.name !== node) { - getNodeLinks(declaration).flags! |= NodeCheckFlags.ClassWithConstructorReference; - getNodeLinks(node).flags! |= NodeCheckFlags.ConstructorReferenceInClass; + getNodeLinks(declaration).flags |= NodeCheckFlags.ClassWithConstructorReference; + getNodeLinks(node).flags |= NodeCheckFlags.ConstructorReferenceInClass; break; } @@ -13984,8 +13984,8 @@ namespace ts { while (container.kind !== SyntaxKind.SourceFile) { if (container.parent === declaration) { if (container.kind === SyntaxKind.PropertyDeclaration && hasModifier(container, ModifierFlags.Static)) { - getNodeLinks(declaration).flags! |= NodeCheckFlags.ClassWithConstructorReference; - getNodeLinks(node).flags! |= NodeCheckFlags.ConstructorReferenceInClass; + getNodeLinks(declaration).flags |= NodeCheckFlags.ClassWithConstructorReference; + getNodeLinks(node).flags |= NodeCheckFlags.ConstructorReferenceInClass; } break; } @@ -14113,7 +14113,7 @@ namespace ts { if (containedInIterationStatement) { if (usedInFunction) { // mark iteration statement as containing block-scoped binding captured in some function - getNodeLinks(current).flags! |= NodeCheckFlags.LoopWithCapturedBlockScopedBinding; + getNodeLinks(current).flags |= NodeCheckFlags.LoopWithCapturedBlockScopedBinding; } // mark variables that are declared in loop initializer and reassigned inside the body of ForStatement. @@ -14121,15 +14121,15 @@ namespace ts { if (container.kind === SyntaxKind.ForStatement && getAncestor(symbol.valueDeclaration, SyntaxKind.VariableDeclarationList)!.parent === container && isAssignedInBodyOfForStatement(node, container)) { - getNodeLinks(symbol.valueDeclaration).flags! |= NodeCheckFlags.NeedsLoopOutParameter; + getNodeLinks(symbol.valueDeclaration).flags |= NodeCheckFlags.NeedsLoopOutParameter; } // set 'declared inside loop' bit on the block-scoped binding - getNodeLinks(symbol.valueDeclaration).flags! |= NodeCheckFlags.BlockScopedBindingInLoop; + getNodeLinks(symbol.valueDeclaration).flags |= NodeCheckFlags.BlockScopedBindingInLoop; } if (usedInFunction) { - getNodeLinks(symbol.valueDeclaration).flags! |= NodeCheckFlags.CapturedBlockScopedBinding; + getNodeLinks(symbol.valueDeclaration).flags |= NodeCheckFlags.CapturedBlockScopedBinding; } } @@ -14160,13 +14160,13 @@ namespace ts { } function captureLexicalThis(node: Node, container: Node): void { - getNodeLinks(node).flags! |= NodeCheckFlags.LexicalThis; + getNodeLinks(node).flags |= NodeCheckFlags.LexicalThis; if (container.kind === SyntaxKind.PropertyDeclaration || container.kind === SyntaxKind.Constructor) { const classNode = container.parent; - getNodeLinks(classNode).flags! |= NodeCheckFlags.CaptureThis; + getNodeLinks(classNode).flags |= NodeCheckFlags.CaptureThis; } else { - getNodeLinks(container).flags! |= NodeCheckFlags.CaptureThis; + getNodeLinks(container).flags |= NodeCheckFlags.CaptureThis; } } @@ -14397,7 +14397,7 @@ namespace ts { nodeCheckFlag = NodeCheckFlags.SuperInstance; } - getNodeLinks(node).flags! |= nodeCheckFlag; + getNodeLinks(node).flags |= nodeCheckFlag; // Due to how we emit async functions, we need to specialize the emit for an async method that contains a `super` reference. // This is due to the fact that we emit the body of an async function inside of a generator function. As generator @@ -14457,10 +14457,10 @@ namespace ts { // while a property access can. if (container.kind === SyntaxKind.MethodDeclaration && hasModifier(container, ModifierFlags.Async)) { if (isSuperProperty(node.parent) && isAssignmentTarget(node.parent)) { - getNodeLinks(container).flags! |= NodeCheckFlags.AsyncMethodWithSuperBinding; + getNodeLinks(container).flags |= NodeCheckFlags.AsyncMethodWithSuperBinding; } else { - getNodeLinks(container).flags! |= NodeCheckFlags.AsyncMethodWithSuper; + getNodeLinks(container).flags |= NodeCheckFlags.AsyncMethodWithSuper; } } @@ -15851,14 +15851,14 @@ namespace ts { if (!isIdentifier(node.tagName)) return Debug.fail(); const intrinsicProp = getPropertyOfType(intrinsicElementsType, node.tagName.escapedText); if (intrinsicProp) { - links.jsxFlags! |= JsxFlags.IntrinsicNamedElement; + links.jsxFlags |= JsxFlags.IntrinsicNamedElement; return links.resolvedSymbol = intrinsicProp; } // Intrinsic string indexer case const indexSignatureType = getIndexTypeOfType(intrinsicElementsType, IndexKind.String); if (indexSignatureType) { - links.jsxFlags! |= JsxFlags.IntrinsicIndexedElement; + links.jsxFlags |= JsxFlags.IntrinsicIndexedElement; return links.resolvedSymbol = intrinsicElementsType.symbol; } @@ -16199,10 +16199,10 @@ namespace ts { const links = getNodeLinks(node); if (!links.resolvedJsxElementAttributesType) { const symbol = getIntrinsicTagSymbol(node); - if (links.jsxFlags! & JsxFlags.IntrinsicNamedElement) { + if (links.jsxFlags & JsxFlags.IntrinsicNamedElement) { return links.resolvedJsxElementAttributesType = getTypeOfSymbol(symbol); } - else if (links.jsxFlags! & JsxFlags.IntrinsicIndexedElement) { + else if (links.jsxFlags & JsxFlags.IntrinsicIndexedElement) { return links.resolvedJsxElementAttributesType = getIndexInfoOfSymbol(symbol, IndexKind.String)!.type; } else { @@ -19208,13 +19208,13 @@ namespace ts { } // Check if function expression is contextually typed and assign parameter types if so. - if (!(links.flags! & NodeCheckFlags.ContextChecked)) { + if (!(links.flags & NodeCheckFlags.ContextChecked)) { const contextualSignature = getContextualSignature(node); // If a type check is started at a function expression that is an argument of a function call, obtaining the // contextual type may recursively get back to here during overload resolution of the call. If so, we will have // already assigned contextual types. - if (!(links.flags! & NodeCheckFlags.ContextChecked)) { - links.flags! |= NodeCheckFlags.ContextChecked; + if (!(links.flags & NodeCheckFlags.ContextChecked)) { + links.flags |= NodeCheckFlags.ContextChecked; if (contextualSignature) { const signature = getSignaturesOfType(type, SignatureKind.Call)[0]; if (isContextSensitive(node)) { @@ -24108,8 +24108,8 @@ namespace ts { function computeEnumMemberValues(node: EnumDeclaration) { const nodeLinks = getNodeLinks(node); - if (!(nodeLinks.flags! & NodeCheckFlags.EnumValuesComputed)) { - nodeLinks.flags! |= NodeCheckFlags.EnumValuesComputed; + if (!(nodeLinks.flags & NodeCheckFlags.EnumValuesComputed)) { + nodeLinks.flags |= NodeCheckFlags.EnumValuesComputed; let autoValue: number | undefined = 0; for (const member of node.members) { const value = computeMemberValue(member, autoValue); @@ -24407,7 +24407,7 @@ namespace ts { const mergedClass = getDeclarationOfKind(symbol, SyntaxKind.ClassDeclaration); if (mergedClass && inSameLexicalScope(node, mergedClass)) { - getNodeLinks(node).flags! |= NodeCheckFlags.LexicalModuleMergesWithClass; + getNodeLinks(node).flags |= NodeCheckFlags.LexicalModuleMergesWithClass; } } @@ -25115,7 +25115,7 @@ namespace ts { // Fully type check a source file and collect the relevant diagnostics. function checkSourceFileWorker(node: SourceFile) { const links = getNodeLinks(node); - if (!(links.flags! & NodeCheckFlags.TypeChecked)) { + if (!(links.flags & NodeCheckFlags.TypeChecked)) { // If skipLibCheck is enabled, skip type checking if file is a declaration file. // If skipDefaultLibCheck is enabled, skip type checking if file contains a // '/// ' directive. @@ -25169,7 +25169,7 @@ namespace ts { clear(potentialNewTargetCollisions); } - links.flags! |= NodeCheckFlags.TypeChecked; + links.flags |= NodeCheckFlags.TypeChecked; } } @@ -25961,7 +25961,7 @@ namespace ts { // redeclaration - always should be renamed links.isDeclarationWithCollidingName = true; } - else if (nodeLinks.flags! & NodeCheckFlags.CapturedBlockScopedBinding) { + else if (nodeLinks.flags & NodeCheckFlags.CapturedBlockScopedBinding) { // binding is captured in the function // should be renamed if: // - binding is not top level - top level bindings never collide with anything @@ -25977,7 +25977,7 @@ namespace ts { // * variables from initializer are passed to rewritten loop body as parameters so they are not captured directly // * variables that are declared immediately in loop body will become top level variable after loop is rewritten and thus // they will not collide with anything - const isDeclaredInLoop = nodeLinks.flags! & NodeCheckFlags.BlockScopedBindingInLoop; + const isDeclaredInLoop = nodeLinks.flags & NodeCheckFlags.BlockScopedBindingInLoop; const inLoopInitializer = isIterationStatement(container, /*lookInLabeledStatements*/ false); const inLoopBodyBlock = container.kind === SyntaxKind.Block && isIterationStatement(container.parent, /*lookInLabeledStatements*/ false); @@ -27885,7 +27885,7 @@ namespace ts { function checkGrammarNumericLiteral(node: NumericLiteral): boolean { // Grammar checking - if (node.numericLiteralFlags! & TokenFlags.Octal) { + if (node.numericLiteralFlags & TokenFlags.Octal) { let diagnosticMessage: DiagnosticMessage | undefined; if (languageVersion >= ScriptTarget.ES5) { diagnosticMessage = Diagnostics.Octal_literals_are_not_available_when_targeting_ECMAScript_5_and_higher_Use_the_syntax_0; diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 10b03edca9975..d526ac1782063 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -138,9 +138,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++; @@ -171,9 +171,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++; @@ -183,7 +185,7 @@ namespace ts { /** Create a unique name based on the supplied text. This does not consider names injected by the transformer. */ export function createFileLevelUniqueName(text: string): Identifier { const name = createOptimisticUniqueName(text); - name.autoGenerateFlags! |= GeneratedIdentifierFlags.FileLevel; + name.autoGenerateFlags |= GeneratedIdentifierFlags.FileLevel; return name; } @@ -1763,9 +1765,9 @@ 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.flags |= flags & NodeFlags.BlockScoped; node.declarations = createNodeArray(declarations); return node; } @@ -1947,9 +1949,9 @@ 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.flags |= flags & (NodeFlags.Namespace | NodeFlags.NestedNamespace | NodeFlags.GlobalAugmentation); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.name = name; @@ -2505,7 +2507,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; } @@ -2517,7 +2519,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; } @@ -2724,21 +2726,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); } - node.emitNode = {}; + node.emitNode = {} as EmitNode; } return node.emitNode; @@ -2766,7 +2768,7 @@ namespace ts { /* @internal */ export function addEmitFlags(node: T, emitFlags: EmitFlags) { const emitNode = getOrCreateEmitNode(node); - emitNode.flags = emitNode.flags! | emitFlags; + emitNode.flags = emitNode.flags | emitFlags; return node; } @@ -2994,7 +2996,7 @@ 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); @@ -3061,7 +3063,7 @@ namespace ts { : createElementAccess(target, memberName), memberName ); - getOrCreateEmitNode(expression).flags! |= EmitFlags.NoNestedSourceMaps; + getOrCreateEmitNode(expression).flags |= EmitFlags.NoNestedSourceMaps; return expression; } } @@ -3705,13 +3707,13 @@ 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); - emitFlags! |= getEmitFlags(nodeName); - if (!allowSourceMaps) emitFlags! |= EmitFlags.NoSourceMap; - if (!allowComments) emitFlags! |= EmitFlags.NoComments; + emitFlags |= getEmitFlags(nodeName); + if (!allowSourceMaps) emitFlags |= EmitFlags.NoSourceMap; + if (!allowComments) emitFlags |= EmitFlags.NoComments; if (emitFlags) setEmitFlags(name, emitFlags); return name; } diff --git a/src/compiler/sourcemap.ts b/src/compiler/sourcemap.ts index 66ef7650da7b1..a274404f320c9 100644 --- a/src/compiler/sourcemap.ts +++ b/src/compiler/sourcemap.ts @@ -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; @@ -344,14 +344,14 @@ namespace ts { if (source) setSourceFile(source); if (node.kind !== SyntaxKind.NotEmittedStatement - && (emitFlags! & EmitFlags.NoLeadingSourceMap) === 0 + && (emitFlags & EmitFlags.NoLeadingSourceMap) === 0 && pos >= 0) { emitPos(skipSourceTrivia(pos)); } if (source) setSourceFile(oldSource); - if (emitFlags! & EmitFlags.NoNestedSourceMaps) { + if (emitFlags & EmitFlags.NoNestedSourceMaps) { disabled = true; emitCallback(hint, node); disabled = false; @@ -363,7 +363,7 @@ namespace ts { if (source) setSourceFile(source); if (node.kind !== SyntaxKind.NotEmittedStatement - && (emitFlags! & EmitFlags.NoTrailingSourceMap) === 0 + && (emitFlags & EmitFlags.NoTrailingSourceMap) === 0 && end >= 0) { emitPos(end); } @@ -386,18 +386,18 @@ 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); - if ((emitFlags! & EmitFlags.NoTokenLeadingSourceMaps) === 0 && tokenPos >= 0) { + if ((emitFlags & EmitFlags.NoTokenLeadingSourceMaps) === 0 && tokenPos >= 0) { emitPos(tokenPos); } tokenPos = emitCallback(token, writer, tokenPos); if (range) tokenPos = range.end; - if ((emitFlags! & EmitFlags.NoTokenTrailingSourceMaps) === 0 && tokenPos >= 0) { + if ((emitFlags & EmitFlags.NoTokenTrailingSourceMaps) === 0 && tokenPos >= 0) { emitPos(tokenPos); } diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index 5ecf85639d6eb..309606dac718a 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -3628,7 +3628,7 @@ namespace ts { * @param node A string literal. */ function visitNumericLiteral(node: NumericLiteral) { - if (node.numericLiteralFlags! & TokenFlags.BinaryOrOctalSpecifier) { + if (node.numericLiteralFlags & TokenFlags.BinaryOrOctalSpecifier) { return setTextRange(createNumericLiteral(node.text), node); } return node; diff --git a/src/compiler/transformers/es2017.ts b/src/compiler/transformers/es2017.ts index 2e8224df0a064..f3fe12b7027e4 100644 --- a/src/compiler/transformers/es2017.ts +++ b/src/compiler/transformers/es2017.ts @@ -649,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/esnext.ts b/src/compiler/transformers/esnext.ts index ffb0938295bce..85f8e67a17d15 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -918,7 +918,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/ts.ts b/src/compiler/transformers/ts.ts index 0448923591b19..2b0e8261064f5 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -897,7 +897,7 @@ namespace ts { // record an alias as the class name is not in scope for statics. enableSubstitutionForClassAliases(); const alias = getSynthesizedClone(temp); - alias.autoGenerateFlags! &= ~GeneratedIdentifierFlags.ReservedInNestedScopes; + alias.autoGenerateFlags &= ~GeneratedIdentifierFlags.ReservedInNestedScopes; classAliases[getOriginalNodeId(node)] = alias; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index a704d09201c9f..1c0b8735fc38f 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1593,7 +1593,7 @@ namespace ts { export interface NumericLiteral extends LiteralExpression { kind: SyntaxKind.NumericLiteral; /* @internal */ - numericLiteralFlags?: TokenFlags; + numericLiteralFlags: TokenFlags; } export interface TemplateHead extends LiteralLikeNode { @@ -3543,7 +3543,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 resolvedSymbol?: Symbol; // Cached name resolution result @@ -3553,7 +3553,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. @@ -4744,7 +4744,7 @@ 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 @@ -4757,6 +4757,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. diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 4eeb626382edb..b9d7bdb547c42 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -360,7 +360,7 @@ namespace ts { export function getLiteralText(node: LiteralLikeNode, sourceFile: SourceFile) { // If we don't need to downlevel and we can reach the original source text using // the node's parent reference, then simply get the text as it was originally written. - if (!nodeIsSynthesized(node) && node.parent && !(isNumericLiteral(node) && node.numericLiteralFlags! & TokenFlags.ContainsSeparator)) { + if (!nodeIsSynthesized(node) && node.parent && !(isNumericLiteral(node) && node.numericLiteralFlags & TokenFlags.ContainsSeparator)) { return getSourceTextOfNodeFromSourceFile(sourceFile, node); } diff --git a/src/services/services.ts b/src/services/services.ts index 572d2d693dc19..2a7d0adfc085c 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -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; @@ -200,6 +201,7 @@ namespace ts { public end: number; public flags: NodeFlags; public parent: Node; + public symbol: Symbol; public jsDocComments: JSDoc[]; public transformFlags: TransformFlags; @@ -332,6 +334,7 @@ namespace ts { } class TokenObject extends TokenOrIdentifierObject implements Token { + public symbol: Symbol; public kind: TKind; constructor(kind: TKind, pos: number, end: number) { @@ -343,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; @@ -366,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; diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts index 9fa179ce8cba4..2582743816d60 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -600,8 +600,8 @@ namespace ts.SymbolDisplay { } } - function addSignatureDisplayParts(signature: Signature, allSignatures: Signature[], flags?: TypeFormatFlags) { - addRange(displayParts, signatureToDisplayParts(typeChecker, signature, enclosingDeclaration, flags! | TypeFormatFlags.WriteTypeArgumentsOfSignature)); + 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()); displayParts.push(punctuationPart(SyntaxKind.OpenParenToken)); diff --git a/src/services/utilities.ts b/src/services/utilities.ts index e31b3186a9da1..a3d2b4f0f4042 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1395,20 +1395,20 @@ 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); + 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); + typeChecker.writeSymbol(symbol, enclosingDeclaration, meaning, flags | SymbolFormatFlags.UseAliasDefinedOutsideCurrentScope, writer); }); } - export function signatureToDisplayParts(typechecker: TypeChecker, signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags): SymbolDisplayPart[] { - flags! |= TypeFormatFlags.UseAliasDefinedOutsideCurrentScope | TypeFormatFlags.MultilineObjectLiterals | TypeFormatFlags.WriteTypeArgumentsOfSignature | TypeFormatFlags.OmitParameterModifiers; + 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); }); diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index ca000b80968ac..22c02668a4be8 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -2119,7 +2119,7 @@ declare namespace ts { type DestructuringPattern = BindingPattern | ObjectLiteralExpression | ArrayLiteralExpression; interface Type { flags: TypeFlags; - symbol?: Symbol; + symbol: Symbol; pattern?: DestructuringPattern; aliasSymbol?: Symbol; aliasTypeArguments?: Type[]; @@ -2572,6 +2572,7 @@ declare namespace ts { skipTrivia?: (pos: number) => number; } enum EmitFlags { + None = 0, SingleLine = 1, AdviseOnEmitNode = 2, NoSubstitution = 4, diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index cca47aa65fdc6..091c93c4518c4 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2119,7 +2119,7 @@ declare namespace ts { type DestructuringPattern = BindingPattern | ObjectLiteralExpression | ArrayLiteralExpression; interface Type { flags: TypeFlags; - symbol?: Symbol; + symbol: Symbol; pattern?: DestructuringPattern; aliasSymbol?: Symbol; aliasTypeArguments?: Type[]; @@ -2572,6 +2572,7 @@ declare namespace ts { skipTrivia?: (pos: number) => number; } enum EmitFlags { + None = 0, SingleLine = 1, AdviseOnEmitNode = 2, NoSubstitution = 4, From c59c7ecd8756569a4aa1cb68b1f592312600d862 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 30 Apr 2018 15:39:53 -0700 Subject: [PATCH 34/42] Convert some asserts to type guards --- src/compiler/binder.ts | 6 +++--- src/compiler/builderState.ts | 4 ++-- src/compiler/checker.ts | 28 ++++++++++++------------- src/compiler/core.ts | 4 ++-- src/compiler/factory.ts | 4 ++-- src/compiler/transformers/generators.ts | 6 +++--- src/services/findAllReferences.ts | 4 ++-- src/services/refactors/extractSymbol.ts | 4 ++-- src/services/services.ts | 6 +++--- src/services/symbolDisplay.ts | 4 ++-- src/services/transpile.ts | 4 ++-- 11 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 6fad099337fd7..a4a7d2c2108ea 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -2507,9 +2507,9 @@ namespace ts { return action(e, lookupSymbolForPropertyAccess(e)); } else { - const s = getJSInitializerSymbol(forEachIdentifierInEntityName(e.expression, action))!; - Debug.assert(!!s && !!s.exports); - return action(e.name, s.exports!.get(e.name.escapedText)); + const s = getJSInitializerSymbol(forEachIdentifierInEntityName(e.expression, action)); + if (!s || !s.exports) return Debug.fail(); + return action(e.name, s.exports.get(e.name.escapedText)); } } diff --git a/src/compiler/builderState.ts b/src/compiler/builderState.ts index 395d15275ad79..ed41ef4a8d3fa 100644 --- a/src/compiler/builderState.ts +++ b/src/compiler/builderState.ts @@ -210,8 +210,8 @@ namespace ts.BuilderState { return false; } - const info = state.fileInfos.get(sourceFile.path)!; - Debug.assert(!!info); + const info = state.fileInfos.get(sourceFile.path); + if (!info) return Debug.fail(); const prevSignature = info.signature; let latestSignature: string; diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1f2875e9625e0..956a8a88df6d6 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -101,8 +101,8 @@ namespace ts { }, getSymbolsOfParameterPropertyDeclaration: (parameterIn, parameterName) => { const parameter = getParseTreeNode(parameterIn, isParameter); - Debug.assert(parameter !== undefined, "Cannot get symbols of a synthetic parameter that cannot be resolved to a parse-tree node."); - return getSymbolsOfParameterPropertyDeclaration(parameter!, escapeLeadingUnderscores(parameterName)); + 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, getPropertiesOfType, @@ -229,8 +229,8 @@ namespace ts { const links = getSymbolLinks(symbol); if (!links.immediateTarget) { const node = getDeclarationOfAliasSymbol(symbol); - Debug.assert(!!node); - links.immediateTarget = getTargetOfAliasDeclaration(node!, /*dontRecursivelyResolve*/ true); + if (!node) return Debug.fail(); + links.immediateTarget = getTargetOfAliasDeclaration(node, /*dontRecursivelyResolve*/ true); } return links.immediateTarget; @@ -1994,8 +1994,8 @@ namespace ts { const links = getSymbolLinks(symbol); if (!links.target) { links.target = resolvingSymbol; - const node = getDeclarationOfAliasSymbol(symbol)!; - Debug.assert(!!node); + const node = getDeclarationOfAliasSymbol(symbol); + if (!node) return Debug.fail(); const target = getTargetOfAliasDeclaration(node); if (links.target === resolvingSymbol) { links.target = target || unknownSymbol; @@ -2030,8 +2030,8 @@ namespace ts { const links = getSymbolLinks(symbol); if (!links.referenced) { links.referenced = true; - const node = getDeclarationOfAliasSymbol(symbol)!; - Debug.assert(!!node); + const node = getDeclarationOfAliasSymbol(symbol); + if (!node) return Debug.fail(); if (node.kind === SyntaxKind.ExportAssignment) { // export default checkExpressionCached((node).expression); @@ -2928,11 +2928,11 @@ namespace ts { 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); - printer.writeNode(EmitHint.Unspecified, typeNode!, /*sourceFile*/ sourceFile, writer); + printer.writeNode(EmitHint.Unspecified, typeNode, /*sourceFile*/ sourceFile, writer); const result = writer.getText(); const maxLength = compilerOptions.noErrorTruncation || flags & TypeFormatFlags.NoTruncation ? undefined : 100; @@ -10278,8 +10278,8 @@ 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 (isJsxAttributes(errorNode!) || isJsxOpeningLikeElement(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. reportError(Diagnostics.Property_0_does_not_exist_on_type_1, symbolToString(prop), typeToString(target)); @@ -21703,8 +21703,8 @@ namespace ts { const thenFunction = getTypeOfPropertyOfType(type, "then" as __String); if (thenFunction && getSignaturesOfType(thenFunction, SignatureKind.Call).length > 0) { if (errorNode) { - Debug.assert(!!diagnosticMessage); - error(errorNode, diagnosticMessage!); + if (!diagnosticMessage) return Debug.fail(); + error(errorNode, diagnosticMessage); } return undefined; } diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 2f8ac900f34f6..3fd80ba7be88d 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -2952,8 +2952,8 @@ namespace ts { } export function assertDefined(value: T | null | undefined, message?: string): T { - assert(value !== undefined && value !== null, message); - return value!; + if (value === undefined || value === null) return fail(message); + return value; } export function assertEachDefined>(value: A, message?: string): A { diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index d526ac1782063..6311fd9771fae 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -3761,7 +3761,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, @@ -3769,7 +3769,7 @@ namespace ts { node.typeParameters, node.parameters, node.type, - node.body! // TODO: GH#18217 + node.body ); setOriginalNode(updated, node); setTextRange(updated, node); diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts index caf4063c792e0..1280316b763e2 100644 --- a/src/compiler/transformers/generators.ts +++ b/src/compiler/transformers/generators.ts @@ -2041,14 +2041,14 @@ 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!; + blocks![index] = block; blockStack!.pop(); - return block!; + return block; } /** diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index d769333605607..4ddeccd6a276b 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -920,8 +920,8 @@ 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); - searchForImportsOfExport(referenceLocation, referenceSymbol, exportInfo!, state); + if (!exportInfo) return Debug.fail(); + searchForImportsOfExport(referenceLocation, referenceSymbol, exportInfo, state); } // At `export { x } from "foo"`, also search for the imported symbol `"foo".x`. diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index c0e287346a357..0f937815250a9 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -1277,8 +1277,8 @@ namespace ts.refactor.extractSymbol { prevMember = member; } - Debug.assert(prevMember !== undefined); // If the loop didn't return, then it did set prevMember. - return prevMember!; + if (prevMember === undefined) return Debug.fail(); // If the loop didn't return, then it did set prevMember. + return prevMember; } function getNodeToInsertConstantBefore(node: Node, scope: Scope): Statement { diff --git a/src/services/services.ts b/src/services/services.ts index 819e722524684..a11a270b61dca 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2093,16 +2093,16 @@ namespace ts { 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. - if (isLetterOrDigit(fileContents.charCodeAt(matchPosition + descriptor!.text.length))) { + if (isLetterOrDigit(fileContents.charCodeAt(matchPosition + descriptor.text.length))) { continue; } const message = matchArray[2]; - result.push({ descriptor: descriptor!, message, position: matchPosition }); + result.push({ descriptor, message, position: matchPosition }); } } diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts index 2582743816d60..2945d641c0915 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -330,8 +330,8 @@ namespace ts.SymbolDisplay { else { // Method/function type parameter const decl = getDeclarationOfKind(symbol, SyntaxKind.TypeParameter); - Debug.assert(decl !== undefined); - const declaration = decl!.parent; + if (decl === undefined) return Debug.fail(); + const declaration = decl.parent; if (declaration) { if (isFunctionLikeKind(declaration.kind)) { diff --git a/src/services/transpile.ts b/src/services/transpile.ts index 93a768d74b8de..70ca5b6431438 100644 --- a/src/services/transpile.ts +++ b/src/services/transpile.ts @@ -106,9 +106,9 @@ 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: outputText!, diagnostics, sourceMapText }; + return { outputText, diagnostics, sourceMapText }; } /* From 8b7a620e47768af0f46ab125d8f6134c30fed072 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 30 Apr 2018 17:33:53 -0700 Subject: [PATCH 35/42] Make `isNonLocalAlias` a type guard --- src/compiler/checker.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b918e9aab889b..481d74071dcad 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1693,9 +1693,9 @@ namespace ts { function checkResolvedBlockScopedVariable(result: Symbol, errorLocation: Node): void { Debug.assert(!!(result.flags & SymbolFlags.BlockScopedVariable || result.flags & SymbolFlags.Class || result.flags & SymbolFlags.Enum)); // 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)!; + 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) { @@ -1962,16 +1962,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 | undefined, 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; function resolveSymbol(symbol: Symbol | undefined, dontResolveAlias?: boolean): Symbol | undefined; function resolveSymbol(symbol: Symbol | undefined, dontResolveAlias?: boolean): Symbol | undefined { - const shouldResolve = !dontResolveAlias && isNonLocalAlias(symbol); - return shouldResolve ? resolveAlias(symbol!) : symbol; + return !dontResolveAlias && isNonLocalAlias(symbol) ? resolveAlias(symbol) : symbol; } function resolveAlias(symbol: Symbol): Symbol { @@ -26100,7 +26099,7 @@ namespace ts { // We should only get the declaration of an alias if there isn't a local value // declaration for the symbol if (isNonLocalAlias(symbol, /*excludes*/ SymbolFlags.Value)) { - return getDeclarationOfAliasSymbol(symbol!); + return getDeclarationOfAliasSymbol(symbol); } } From 86d3334cbf8e91c782ad1ffee7ee80051ed32195 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 30 Apr 2018 21:45:11 -0700 Subject: [PATCH 36/42] Add overload for `getSymbolOfNode` for `Declaration` --- src/compiler/checker.ts | 104 ++++++++++++++++++++-------------------- 1 file changed, 53 insertions(+), 51 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 481d74071dcad..79ddb55c4e90c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1367,7 +1367,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); } @@ -1695,7 +1695,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); - if(declaration === undefined) return Debug.fail("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) { @@ -1995,7 +1995,7 @@ namespace ts { } function markExportAsReferenced(node: ImportEqualsDeclaration | ExportAssignment | ExportSpecifier) { - const symbol = getSymbolOfNode(node)!; + const symbol = getSymbolOfNode(node); const target = resolveAlias(symbol); if (target) { const markAlias = target === unknownSymbol || @@ -2457,6 +2457,8 @@ namespace ts { return symbol && symbol.mergeId && (merged = mergedSymbols[symbol.mergeId]) ? merged : 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)); } @@ -4380,7 +4382,7 @@ namespace ts { const func = declaration.parent; // For a parameter of a set accessor, use the type of the get accessor if one is present if (func.kind === SyntaxKind.SetAccessor && !hasNonBindableDynamicName(func)) { - const getter = getDeclarationOfKind(getSymbolOfNode(declaration.parent)!, SyntaxKind.GetAccessor); + const getter = getDeclarationOfKind(getSymbolOfNode(declaration.parent), SyntaxKind.GetAccessor); if (getter) { const getterSignature = getSignatureFromDeclaration(getter); const thisParameter = getAccessorThisParameter(func as AccessorDeclaration); @@ -4548,7 +4550,7 @@ namespace ts { return isClassLike(parent) && parent; }); if (parentDeclaration) { - const classType = getDeclaredTypeOfSymbol(getSymbolOfNode(parentDeclaration)!) as InterfaceType; + const classType = getDeclaredTypeOfSymbol(getSymbolOfNode(parentDeclaration)) as InterfaceType; const baseClassType = classType && getBaseTypes(classType)[0]; if (baseClassType) { return getTypeOfPropertyOfType(baseClassType, specialProperty.escapedName); @@ -4994,7 +4996,7 @@ namespace ts { // in-place and returns the same array. function appendTypeParameters(typeParameters: TypeParameter[] | undefined, declarations: ReadonlyArray): TypeParameter[] | undefined { for (const declaration of declarations) { - typeParameters = appendIfUnique(typeParameters, getDeclaredTypeOfTypeParameter(getSymbolOfNode(declaration)!)); + typeParameters = appendIfUnique(typeParameters, getDeclaredTypeOfTypeParameter(getSymbolOfNode(declaration))); } return typeParameters; } @@ -5026,7 +5028,7 @@ namespace ts { case SyntaxKind.ConditionalType: const outerTypeParameters = getOuterTypeParameters(node, includeThisTypes); if (node.kind === SyntaxKind.MappedType) { - return append(outerTypeParameters, getDeclaredTypeOfTypeParameter(getSymbolOfNode((node).typeParameter)!)); + return append(outerTypeParameters, getDeclaredTypeOfTypeParameter(getSymbolOfNode((node).typeParameter))); } else if (node.kind === SyntaxKind.ConditionalType) { return concatenate(outerTypeParameters, getInferTypeParameters(node)); @@ -5397,7 +5399,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: @@ -5442,7 +5444,7 @@ namespace ts { if (declaration.kind === SyntaxKind.EnumDeclaration) { for (const member of (declaration).members) { const memberType = getLiteralType(getEnumMemberValue(member)!, enumCount, getSymbolOfNode(member)); // TODO: GH#18217 - getSymbolLinks(getSymbolOfNode(member)!).declaredType = memberType; + getSymbolLinks(getSymbolOfNode(member)).declaredType = memberType; memberTypeList.push(memberType); } } @@ -6283,7 +6285,7 @@ namespace ts { function getTypeParameterFromMappedType(type: MappedType) { return type.typeParameter || - (type.typeParameter = getDeclaredTypeOfTypeParameter(getSymbolOfNode(type.declaration.typeParameter)!)); + (type.typeParameter = getDeclaredTypeOfTypeParameter(getSymbolOfNode(type.declaration.typeParameter))); } function getConstraintTypeFromMappedType(type: MappedType) { @@ -7075,7 +7077,7 @@ namespace ts { !hasNonBindableDynamicName(declaration) && (!hasThisParameter || !thisParameter)) { const otherKind = declaration.kind === SyntaxKind.GetAccessor ? SyntaxKind.SetAccessor : SyntaxKind.GetAccessor; - const other = getDeclarationOfKind(getSymbolOfNode(declaration)!, otherKind); + const other = getDeclarationOfKind(getSymbolOfNode(declaration), otherKind); if (other) { thisParameter = getAnnotatedAccessorThisParameter(other); } @@ -7134,7 +7136,7 @@ namespace ts { // TypeScript 1.0 spec (April 2014): // If only one accessor includes a type annotation, the other behaves as if it had the same type annotation. if (declaration.kind === SyntaxKind.GetAccessor && !hasNonBindableDynamicName(declaration)) { - const setter = getDeclarationOfKind(getSymbolOfNode(declaration)!, SyntaxKind.SetAccessor); + const setter = getDeclarationOfKind(getSymbolOfNode(declaration), SyntaxKind.SetAccessor); return getAnnotatedAccessorType(setter); } @@ -8812,7 +8814,7 @@ namespace ts { function getTypeFromInferTypeNode(node: InferTypeNode): Type { const links = getNodeLinks(node); if (!links.resolvedType) { - links.resolvedType = getDeclaredTypeOfTypeParameter(getSymbolOfNode(node.typeParameter)!); + links.resolvedType = getDeclaredTypeOfTypeParameter(getSymbolOfNode(node.typeParameter)); } return links.resolvedType; } @@ -14336,7 +14338,7 @@ namespace ts { * @param classDecl a class declaration to check if it extends null */ function classDeclarationExtendsNull(classDecl: ClassDeclaration): boolean { - const classSymbol = getSymbolOfNode(classDecl)!; + const classSymbol = getSymbolOfNode(classDecl); const classInstanceType = getDeclaredTypeOfSymbol(classSymbol); const baseConstructorType = getBaseConstructorTypeOfClass(classInstanceType); @@ -14451,7 +14453,7 @@ namespace ts { } if (isClassLike(container.parent)) { - const symbol = getSymbolOfNode(container.parent)!; + const symbol = getSymbolOfNode(container.parent); const type = hasModifier(container, ModifierFlags.Static) ? getTypeOfSymbol(symbol) : (getDeclaredTypeOfSymbol(symbol)).thisType!; return getFlowTypeOfReference(node, type); } @@ -14622,7 +14624,7 @@ namespace ts { return unknownType; } - const classType = getDeclaredTypeOfSymbol(getSymbolOfNode(classLikeDeclaration)!); + const classType = getDeclaredTypeOfSymbol(getSymbolOfNode(classLikeDeclaration)); const baseClassType = classType && getBaseTypes(classType)[0]; if (!baseClassType) { return unknownType; @@ -15013,7 +15015,7 @@ namespace ts { // For a (non-symbol) computed property, there is no reason to look up the name // in the type. It will just be "__computed", which does not appear in any // SymbolTable. - const symbolName = getSymbolOfNode(element)!.escapedName; + const symbolName = getSymbolOfNode(element).escapedName; const propertyType = getTypeOfPropertyOfContextualType(type, symbolName); if (propertyType) { return propertyType; @@ -15593,7 +15595,7 @@ namespace ts { if (isInJSFile && node.properties.length === 0) { // an empty JS object literal that nonetheless has members is a JS namespace - const symbol = getSymbolOfNode(node)!; + const symbol = getSymbolOfNode(node); if (symbol.exports) { propertiesTable = symbol.exports; symbol.exports.forEach(symbol => propertiesArray.push(getMergedSymbol(symbol))); @@ -15605,7 +15607,7 @@ namespace ts { let offset = 0; for (let i = 0; i < node.properties.length; i++) { const memberDecl = node.properties[i]; - let member = getSymbolOfNode(memberDecl)!; + let member = getSymbolOfNode(memberDecl); const computedNameType = memberDecl.name && memberDecl.name.kind === SyntaxKind.ComputedPropertyName && !isWellKnownSymbolSyntactically(memberDecl.name.expression) ? checkComputedPropertyName(memberDecl.name) : undefined; if (memberDecl.kind === SyntaxKind.PropertyAssignment || @@ -19049,7 +19051,7 @@ namespace ts { for (const element of pattern.elements) { if (!isOmittedExpression(element)) { if (element.name.kind === SyntaxKind.Identifier) { - getSymbolLinks(getSymbolOfNode(element)!).type = getTypeForBindingElement(element); + getSymbolLinks(getSymbolOfNode(element)).type = getTypeForBindingElement(element); } else { assignBindingElementTypes(element.name); @@ -20571,7 +20573,7 @@ namespace ts { checkSourceElement(node.constraint); checkSourceElement(node.default); - const typeParameter = getDeclaredTypeOfTypeParameter(getSymbolOfNode(node)!); + const typeParameter = getDeclaredTypeOfTypeParameter(getSymbolOfNode(node)); if (!hasNonCircularBaseConstraint(typeParameter)) { error(node.constraint, Diagnostics.Type_parameter_0_has_a_circular_constraint, typeToString(typeParameter)); } @@ -20903,7 +20905,7 @@ namespace ts { case "arguments": case "prototype": const message = Diagnostics.Static_property_0_conflicts_with_built_in_property_Function_0_of_constructor_function_1; - const className = getNameOfSymbolAsWritten(getSymbolOfNode(node)!); + const className = getNameOfSymbolAsWritten(getSymbolOfNode(node)); error(memberNameNode, message, memberName, className); break; } @@ -21011,7 +21013,7 @@ namespace ts { checkSourceElement(node.body); - const symbol = getSymbolOfNode(node)!; + const symbol = getSymbolOfNode(node); const firstDeclaration = getDeclarationOfKind(symbol, node.kind); // Only type check the symbol once @@ -21106,7 +21108,7 @@ namespace ts { // TypeScript 1.0 spec (April 2014): 8.4.3 // Accessors for the same member name must specify the same accessibility. const otherKind = node.kind === SyntaxKind.GetAccessor ? SyntaxKind.SetAccessor : SyntaxKind.GetAccessor; - const otherAccessor = getDeclarationOfKind(getSymbolOfNode(node)!, otherKind); + const otherAccessor = getDeclarationOfKind(getSymbolOfNode(node), otherKind); if (otherAccessor) { const nodeFlags = getModifierFlags(node); const otherFlags = getModifierFlags(otherAccessor); @@ -21123,7 +21125,7 @@ namespace ts { checkAccessorDeclarationTypesIdentical(node, otherAccessor, getThisTypeOfDeclaration, Diagnostics.get_and_set_accessor_must_have_the_same_this_type); } } - const returnType = getTypeOfAccessors(getSymbolOfNode(node)!); + const returnType = getTypeOfAccessors(getSymbolOfNode(node)); if (node.kind === SyntaxKind.GetAccessor) { checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnType); } @@ -21633,7 +21635,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: @@ -21945,7 +21947,7 @@ namespace ts { let errorInfo: DiagnosticMessageChain | undefined; switch (node.parent.kind) { case SyntaxKind.ClassDeclaration: - const classSymbol = getSymbolOfNode(node.parent)!; + const classSymbol = getSymbolOfNode(node.parent); const classConstructorType = getTypeOfSymbol(classSymbol); expectedReturnType = getUnionType([classConstructorType, voidType]); break; @@ -22242,7 +22244,7 @@ namespace ts { // first we want to check the local symbol that contain this declaration // - if node.localSymbol !== undefined - this is current declaration is exported and localSymbol points to the local symbol // - if node.localSymbol === undefined - this node is non-exported so we can just pick the result of getSymbolOfNode - const symbol = getSymbolOfNode(node)!; + const symbol = getSymbolOfNode(node); const localSymbol = node.localSymbol || symbol; // Since the javascript won't do semantic analysis like typescript, @@ -22420,7 +22422,7 @@ namespace ts { // Already would have reported an error on the getter. break; } - const symbol = getSymbolOfNode(member)!; + 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))); } @@ -22450,7 +22452,7 @@ 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) && typeParameters && last(getSymbolOfNode(node)!.declarations) === node) { + if (!(node.flags & NodeFlags.Ambient) && typeParameters && last(getSymbolOfNode(node).declarations) === node) { for (const typeParameter of typeParameters) { 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))); @@ -22687,7 +22689,7 @@ namespace ts { return; } - const symbol = getSymbolOfNode(node)!; + const symbol = getSymbolOfNode(node); if (symbol.flags & SymbolFlags.FunctionScopedVariable) { if (!isIdentifier(node.name)) return Debug.fail(); const localDeclarationSymbol = resolveName(node, node.name.escapedText, SymbolFlags.Variable, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false); @@ -22867,7 +22869,7 @@ namespace ts { } return; } - const symbol = getSymbolOfNode(node)!; + const symbol = getSymbolOfNode(node); const type = convertAutoToAny(getTypeOfSymbol(symbol)); if (node === symbol.valueDeclaration) { // Node is the primary declaration of the symbol, just validate the initializer @@ -23687,7 +23689,7 @@ namespace ts { // Static properties cannot be in conflict with indexers, // and properties with literal names were already checked. if (!hasModifier(member, ModifierFlags.Static) && hasNonBindableDynamicName(member)) { - const symbol = getSymbolOfNode(member)!; + const symbol = getSymbolOfNode(member); const propType = getTypeOfSymbol(symbol); checkIndexConstraintForProperty(symbol, propType, type, declaredStringIndexer, stringIndexType, IndexKind.String); checkIndexConstraintForProperty(symbol, propType, type, declaredNumberIndexer, numberIndexType, IndexKind.Number); @@ -23877,7 +23879,7 @@ namespace ts { function checkClassExpression(node: ClassExpression): Type { checkClassLikeDeclaration(node); checkNodeDeferred(node); - return getTypeOfSymbol(getSymbolOfNode(node)!); + return getTypeOfSymbol(getSymbolOfNode(node)); } function checkClassExpressionDeferred(node: ClassExpression) { @@ -23905,7 +23907,7 @@ namespace ts { } checkTypeParameters(getEffectiveTypeParameterDeclarations(node)); checkExportsOnMergedDeclarations(node); - const symbol = getSymbolOfNode(node)!; + const symbol = getSymbolOfNode(node); const type = getDeclaredTypeOfSymbol(symbol); const typeWithThis = getTypeWithThisArgument(type); const staticType = getTypeOfSymbol(symbol); @@ -24185,7 +24187,7 @@ namespace ts { if (isInstancePropertyWithoutInitializer(member)) { const propName = (member).name; if (isIdentifier(propName)) { - const type = getTypeOfSymbol(getSymbolOfNode(member)!); // TODO: GH#18217 + const type = getTypeOfSymbol(getSymbolOfNode(member)); // TODO: GH#18217 if (!(type.flags & TypeFlags.Any || getFalsyFlags(type) & TypeFlags.Undefined)) { if (!constructor || !isPropertyInitializedInConstructor(propName, type, constructor)) { error(member.name, Diagnostics.Property_0_has_no_initializer_and_is_not_definitely_assigned_in_the_constructor, declarationNameToString(propName)); @@ -24219,7 +24221,7 @@ namespace ts { checkTypeNameIsReserved(node.name, Diagnostics.Interface_name_cannot_be_0); checkExportsOnMergedDeclarations(node); - const symbol = getSymbolOfNode(node)!; + const symbol = getSymbolOfNode(node); checkTypeParameterListsIdentical(symbol); // Only check this symbol once @@ -24305,7 +24307,7 @@ namespace ts { } function computeConstantValue(member: EnumMember): string | number | undefined { - const enumKind = getEnumKind(getSymbolOfNode(member.parent)!); + const enumKind = getEnumKind(getSymbolOfNode(member.parent)); const isConstEnum = isConst(member.parent); const initializer = member.initializer!; const value = enumKind === EnumKind.Literal && !isLiteralEnumMember(member) ? undefined : evaluate(initializer); @@ -24328,7 +24330,7 @@ namespace ts { } else { // Only here do we need to check that the initializer is assignable to the enum type. - checkTypeAssignableTo(checkExpression(initializer), getDeclaredTypeOfSymbol(getSymbolOfNode(member.parent)!), initializer, /*headMessage*/ undefined); + checkTypeAssignableTo(checkExpression(initializer), getDeclaredTypeOfSymbol(getSymbolOfNode(member.parent)), initializer, /*headMessage*/ undefined); } return value; @@ -24375,7 +24377,7 @@ namespace ts { case SyntaxKind.ParenthesizedExpression: return evaluate((expr).expression); case SyntaxKind.Identifier: - return nodeIsMissing(expr) ? 0 : evaluateEnumMember(expr, getSymbolOfNode(member.parent)!, (expr).escapedText); + return nodeIsMissing(expr) ? 0 : evaluateEnumMember(expr, getSymbolOfNode(member.parent), (expr).escapedText); case SyntaxKind.ElementAccessExpression: case SyntaxKind.PropertyAccessExpression: const ex = expr; @@ -24448,7 +24450,7 @@ namespace ts { // for the first member. // // Only perform this check once per symbol - const enumSymbol = getSymbolOfNode(node)!; + const enumSymbol = getSymbolOfNode(node); const firstDeclaration = getDeclarationOfKind(enumSymbol, node.kind); if (node === firstDeclaration) { if (enumSymbol.declarations.length > 1) { @@ -24541,7 +24543,7 @@ namespace ts { } checkExportsOnMergedDeclarations(node); - const symbol = getSymbolOfNode(node)!; + const symbol = getSymbolOfNode(node); // The following checks only apply on a non-ambient instantiated module declaration. if (symbol.flags & SymbolFlags.ValueModule @@ -24574,7 +24576,7 @@ namespace ts { // We can detect if augmentation was applied using following rules: // - augmentation for a global scope is always applied // - augmentation for some external module is applied if symbol for augmentation is merged (it was combined with target module). - const checkBody = isGlobalAugmentation || (getSymbolOfNode(node)!.flags & SymbolFlags.Transient); + const checkBody = isGlobalAugmentation || (getSymbolOfNode(node).flags & SymbolFlags.Transient); if (checkBody && node.body) { for (const statement of node.body.statements) { checkModuleAugmentationElement(statement, isGlobalAugmentation); @@ -24712,7 +24714,7 @@ namespace ts { } function checkAliasSymbol(node: ImportEqualsDeclaration | ImportClause | NamespaceImport | ImportSpecifier | ExportSpecifier) { - const symbol = getSymbolOfNode(node)!; + const symbol = getSymbolOfNode(node); const target = resolveAlias(symbol); if (target !== unknownSymbol) { // For external modules symbol represent local symbol for an alias. @@ -24790,7 +24792,7 @@ namespace ts { markExportAsReferenced(node); } if (node.moduleReference.kind !== SyntaxKind.ExternalModuleReference) { - const target = resolveAlias(getSymbolOfNode(node)!); + const target = resolveAlias(getSymbolOfNode(node)); if (target !== unknownSymbol) { if (target.flags & SymbolFlags.Value) { // Target is a value symbol, check that it is not hidden by a local declaration with the same name @@ -24932,7 +24934,7 @@ namespace ts { } function checkExternalModuleExports(node: SourceFile | ModuleDeclaration) { - const moduleSymbol = getSymbolOfNode(node)!; + const moduleSymbol = getSymbolOfNode(node); const links = getSymbolLinks(moduleSymbol); if (!links.exportsChecked) { const exportEqualsSymbol = moduleSymbol.exports!.get("export=" as __String); @@ -25855,7 +25857,7 @@ namespace ts { // 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 classType = getDeclaredTypeOfSymbol(getSymbolOfNode(classNode)!) as InterfaceType; + const classType = getDeclaredTypeOfSymbol(getSymbolOfNode(classNode)) as InterfaceType; const baseType = getBaseTypes(classType)[0]; return baseType && getTypeWithThisArgument(baseType, classType.thisType); } @@ -25873,7 +25875,7 @@ namespace ts { if (isDeclaration(node)) { // In this case, we call getSymbolOfNode instead of getSymbolAtLocation because it is a declaration - const symbol = getSymbolOfNode(node)!; + const symbol = getSymbolOfNode(node); return getTypeOfSymbol(symbol); } @@ -26207,7 +26209,7 @@ namespace ts { return false; } - const isValue = isAliasResolvedToValue(getSymbolOfNode(node)!); + const isValue = isAliasResolvedToValue(getSymbolOfNode(node)); return isValue && node.moduleReference && !nodeIsMissing(node.moduleReference); } @@ -26464,7 +26466,7 @@ namespace ts { function isLiteralConstDeclaration(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration): boolean { if (isConst(node)) { - const type = getTypeOfSymbol(getSymbolOfNode(node)!); + const type = getTypeOfSymbol(getSymbolOfNode(node)); return !!(type.flags & TypeFlags.StringOrNumberLiteral && type.flags & TypeFlags.FreshLiteral); } return false; @@ -26475,7 +26477,7 @@ namespace ts { } function createLiteralConstValue(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration) { - const type = getTypeOfSymbol(getSymbolOfNode(node)!); + const type = getTypeOfSymbol(getSymbolOfNode(node)); return literalTypeToNode(type); } From 9d2914af1c0d5fdadcda4bac25dcbb14608b835e Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 30 Apr 2018 21:47:26 -0700 Subject: [PATCH 37/42] Some more `getSymbolOfNode` changes --- src/compiler/checker.ts | 38 +++++++++++++++++++------------------- src/compiler/utilities.ts | 2 +- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 79ddb55c4e90c..6c1f4932643f4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1278,7 +1278,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 @@ -1340,7 +1340,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; @@ -1387,7 +1387,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; } @@ -2574,7 +2574,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; @@ -5036,7 +5036,7 @@ namespace ts { const outerAndOwnTypeParameters = appendTypeParameters(outerTypeParameters, getEffectiveTypeParameterDeclarations(node) || emptyArray); 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; } } @@ -9088,7 +9088,7 @@ namespace ts { function getESSymbolLikeTypeForNode(node: Node) { if (isValidESSymbolDeclaration(node)) { - const symbol = getSymbolOfNode(node)!; + const symbol = getSymbolOfNode(node); const links = getSymbolLinks(symbol); return links.uniqueESSymbolType || (links.uniqueESSymbolType = createUniqueESSymbolType(symbol)); } @@ -9101,7 +9101,7 @@ namespace ts { 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!; + 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); @@ -17773,7 +17773,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); } @@ -17782,7 +17782,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); } } @@ -18958,7 +18958,7 @@ 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 { @@ -20944,7 +20944,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) { @@ -24187,7 +24187,7 @@ namespace ts { if (isInstancePropertyWithoutInitializer(member)) { const propName = (member).name; if (isIdentifier(propName)) { - const type = getTypeOfSymbol(getSymbolOfNode(member)); // TODO: GH#18217 + const type = getTypeOfSymbol(getSymbolOfNode(member)); if (!(type.flags & TypeFlags.Any || getFalsyFlags(type) & TypeFlags.Undefined)) { if (!constructor || !isPropertyInitializedInConstructor(propName, type, constructor)) { error(member.name, Diagnostics.Property_0_has_no_initializer_and_is_not_definitely_assigned_in_the_constructor, declarationNameToString(propName)); @@ -25412,13 +25412,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); } @@ -25432,11 +25432,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); } @@ -25488,7 +25488,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: @@ -25864,7 +25864,7 @@ namespace ts { if (isTypeDeclaration(node)) { // In this case, we call getSymbolOfNode instead of getSymbolAtLocation because it is a declaration - const symbol = getSymbolOfNode(node)!; + const symbol = getSymbolOfNode(node); return getDeclaredTypeOfSymbol(symbol); } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index c6b07ebb4af00..3d54ce9d9db66 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1009,7 +1009,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); From 366cc3e672dc7833063b19a246d6294706135984 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 2 May 2018 09:08:42 -0700 Subject: [PATCH 38/42] Push undefined suppression into `typeToTypeNodeHelper` --- src/compiler/checker.ts | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a7f6fd42cf3b9..711d959ccdbec 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3019,7 +3019,7 @@ namespace ts { }; } - function typeToTypeNodeHelper(type: Type, context: NodeBuilderContext): TypeNode | undefined { + function typeToTypeNodeHelper(type: Type, context: NodeBuilderContext): TypeNode { if (cancellationToken && cancellationToken.throwIfCancellationRequested) { cancellationToken.throwIfCancellationRequested(); } @@ -3028,7 +3028,7 @@ namespace ts { if (!type) { context.encounteredError = true; - return undefined; + return undefined!; // TODO: GH#18217 } if (type.flags & TypeFlags.Any) { @@ -3133,7 +3133,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)) { @@ -3143,29 +3143,29 @@ namespace ts { } if (type.flags & TypeFlags.Index) { const indexedType = (type).type; - const indexTypeNode = typeToTypeNodeHelper(indexedType, context)!; // TODO: GH#18217 + const indexTypeNode = typeToTypeNodeHelper(indexedType, context); return createTypeOperatorNode(indexTypeNode); } if (type.flags & TypeFlags.IndexedAccess) { - const objectTypeNode = typeToTypeNodeHelper((type).objectType, context)!; // TODO: GH#18217 - const indexTypeNode = typeToTypeNodeHelper((type).indexType, context)!; + const objectTypeNode = typeToTypeNodeHelper((type).objectType, context); + const indexTypeNode = typeToTypeNodeHelper((type).indexType, context); return createIndexedAccessTypeNode(objectTypeNode, indexTypeNode); } if (type.flags & TypeFlags.Conditional) { - const checkTypeNode = typeToTypeNodeHelper((type).checkType, context)!; // TODO: GH#18217 + const checkTypeNode = typeToTypeNodeHelper((type).checkType, context); const saveInferTypeParameters = context.inferTypeParameters; context.inferTypeParameters = (type).root.inferTypeParameters; - const extendsTypeNode = typeToTypeNodeHelper((type).extendsType, context)!; + const extendsTypeNode = typeToTypeNodeHelper((type).extendsType, context); context.inferTypeParameters = saveInferTypeParameters; - const trueTypeNode = typeToTypeNodeHelper(getTrueTypeFromConditionalType(type), context)!; - const falseTypeNode = typeToTypeNodeHelper(getFalseTypeFromConditionalType(type), context)!; + const trueTypeNode = typeToTypeNodeHelper(getTrueTypeFromConditionalType(type), context); + const falseTypeNode = typeToTypeNodeHelper(getFalseTypeFromConditionalType(type), context); return createConditionalTypeNode(checkTypeNode, extendsTypeNode, trueTypeNode, falseTypeNode); } if (type.flags & TypeFlags.Substitution) { 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)); @@ -3281,15 +3281,15 @@ namespace ts { return entityName; } - function typeReferenceToTypeNode(type: TypeReference) { + function typeReferenceToTypeNode(type: TypeReference): TypeNode { const typeArguments: Type[] = type.typeArguments || emptyArray; if (type.target === globalArrayType) { if (context.flags & NodeBuilderFlags.WriteArrayAsGenericType) { - const typeArgumentNode = typeToTypeNodeHelper(typeArguments[0], context)!; + const typeArgumentNode = typeToTypeNodeHelper(typeArguments[0], context); return createTypeReferenceNode("Array", [typeArgumentNode]); } - const elementType = typeToTypeNodeHelper(typeArguments[0], context)!; + const elementType = typeToTypeNodeHelper(typeArguments[0], context); return createArrayTypeNode(elementType); } else if (type.target.objectFlags & ObjectFlags.Tuple) { @@ -3303,7 +3303,7 @@ namespace ts { return createTupleTypeNode([]); } context.encounteredError = true; - return undefined; + return undefined!; // TODO: GH#18217 } else if (context.flags & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral && type.symbol.valueDeclaration && @@ -3498,7 +3498,7 @@ namespace ts { /*questionToken*/ undefined, indexerTypeNode, /*initializer*/ undefined); - const typeNode = typeToTypeNodeHelper(indexInfo.type || anyType, context)!; // TODO: GH#18217 + const typeNode = typeToTypeNodeHelper(indexInfo.type || anyType, context); if (!indexInfo.type && !(context.flags & NodeBuilderFlags.AllowEmptyIndexInfoType)) { context.encounteredError = true; } @@ -3513,7 +3513,7 @@ namespace ts { 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)!); // TODO: GH#18217 + typeArguments = signature.target.typeParameters.map(parameter => typeToTypeNodeHelper(instantiateType(parameter, signature.mapper!), context)); } else { typeParameters = signature.typeParameters && signature.typeParameters.map(parameter => typeParameterToDeclaration(parameter, context)); @@ -3531,7 +3531,7 @@ namespace ts { const parameterName = typePredicate.kind === TypePredicateKind.Identifier ? setEmitFlags(createIdentifier(typePredicate.parameterName), EmitFlags.NoAsciiEscaping) : createThisTypeNode(); - const typeNode = typeToTypeNodeHelper(typePredicate.type, context)!; + const typeNode = typeToTypeNodeHelper(typePredicate.type, context); returnTypeNode = createTypePredicateNode(parameterName, typeNode); } else { From 5cedbc8bec59c23b93bd37489edacffb21684736 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 2 May 2018 09:12:51 -0700 Subject: [PATCH 39/42] `NodeBuilderContext.tracker` is never `undefined` --- src/compiler/checker.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 711d959ccdbec..acacb19cf2d6f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3067,8 +3067,8 @@ namespace ts { if (isValueSymbolAccessible(type.symbol, context.enclosingDeclaration!)) { return symbolToTypeNode(type.symbol, context, SymbolFlags.Value); } - if (context.tracker!.reportInaccessibleUniqueSymbolError) { - context.tracker!.reportInaccessibleUniqueSymbolError!(); + if (context.tracker.reportInaccessibleUniqueSymbolError) { + context.tracker.reportInaccessibleUniqueSymbolError(); } } return createTypeOperatorNode(SyntaxKind.UniqueKeyword, createKeywordTypeNode(SyntaxKind.SymbolKeyword)); @@ -3096,8 +3096,8 @@ namespace ts { if (!context.encounteredError && !(context.flags & NodeBuilderFlags.AllowThisInObjectLiteral)) { context.encounteredError = true; } - if (context.tracker!.reportInaccessibleThisError) { - context.tracker!.reportInaccessibleThisError!(); + if (context.tracker.reportInaccessibleThisError) { + context.tracker.reportInaccessibleThisError(); } } return createThis(); @@ -3417,8 +3417,8 @@ namespace ts { if (propertySymbol.flags & SymbolFlags.Prototype) { continue; } - if (getDeclarationModifierFlagsFromSymbol(propertySymbol) & (ModifierFlags.Private | ModifierFlags.Protected) && context.tracker!.reportPrivateInBaseOfClassExpression) { - context.tracker!.reportPrivateInBaseOfClassExpression!(unescapeLeadingUnderscores(propertySymbol.escapedName)); + if (getDeclarationModifierFlagsFromSymbol(propertySymbol) & (ModifierFlags.Private | ModifierFlags.Protected) && context.tracker.reportPrivateInBaseOfClassExpression) { + context.tracker.reportPrivateInBaseOfClassExpression(unescapeLeadingUnderscores(propertySymbol.escapedName)); } } const propertyType = getCheckFlags(propertySymbol) & CheckFlags.ReverseMapped && context.flags & NodeBuilderFlags.InReverseMappedType ? @@ -3428,8 +3428,8 @@ namespace ts { if (getCheckFlags(propertySymbol) & CheckFlags.Late) { 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); + if (name && context.tracker.trackSymbol) { + context.tracker.trackSymbol(name, saveEnclosingDeclaration, SymbolFlags.Value); } } const propertyName = symbolToName(propertySymbol, context, SymbolFlags.Value, /*expectsIdentifier*/ true); @@ -3604,7 +3604,7 @@ namespace ts { } function lookupSymbolChain(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags) { - context.tracker!.trackSymbol!(symbol, context.enclosingDeclaration, meaning); + context.tracker.trackSymbol!(symbol, context.enclosingDeclaration, meaning); // 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; @@ -3864,7 +3864,7 @@ namespace ts { interface NodeBuilderContext { enclosingDeclaration: Node | undefined; flags: NodeBuilderFlags; - tracker: SymbolTracker | undefined; + tracker: SymbolTracker; // State encounteredError: boolean; From 1f69c4885026b271b8bd1925a1df954cf90441b6 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 2 May 2018 09:14:44 -0700 Subject: [PATCH 40/42] use `Debug.assertDefined` --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index acacb19cf2d6f..faa21bce0d7a4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3609,7 +3609,7 @@ namespace ts { 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 { From 596c644df0dde231e244190bc50c77d6041bb643 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 2 May 2018 10:22:12 -0700 Subject: [PATCH 41/42] Remove unnecessary tag --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index faa21bce0d7a4..ad8fe94d69b52 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8612,7 +8612,7 @@ namespace ts { const stringIndexTypes: Type[] = []; for (const t of (objectType).types) { if (isStringIndexOnlyType(t)) { - stringIndexTypes.push(getIndexTypeOfType(t, IndexKind.String)!); // TODO: GH#18217 + stringIndexTypes.push(getIndexTypeOfType(t, IndexKind.String)!); } else { regularTypes.push(t); From 321f1c2f415636a3ca1744d8821e9343609447d7 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 2 May 2018 10:32:44 -0700 Subject: [PATCH 42/42] Mark `LiteralType.freshType` and `LiteralTupe.regularType` as required --- src/compiler/checker.ts | 14 +++++++------- src/compiler/types.ts | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ad8fe94d69b52..17361974d2a11 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8187,7 +8187,7 @@ namespace ts { t.flags & TypeFlags.StringLiteral && includes & TypeFlags.String || t.flags & TypeFlags.NumberLiteral && includes & TypeFlags.Number || t.flags & TypeFlags.UniqueESSymbol && includes & TypeFlags.ESSymbol || - t.flags & TypeFlags.StringOrNumberLiteral && t.flags & TypeFlags.FreshLiteral && containsType(types, (t).regularType!); + t.flags & TypeFlags.StringOrNumberLiteral && t.flags & TypeFlags.FreshLiteral && containsType(types, (t).regularType); if (remove) { orderedRemoveItemAt(types, i); } @@ -9083,13 +9083,13 @@ namespace ts { freshType.regularType = type; (type).freshType = freshType; } - return (type).freshType!; + return (type).freshType; } return type; } function getRegularTypeOfLiteralType(type: Type): Type { - return type.flags & TypeFlags.StringOrNumberLiteral && type.flags & TypeFlags.FreshLiteral ? (type).regularType! : type; + return type.flags & TypeFlags.StringOrNumberLiteral && type.flags & TypeFlags.FreshLiteral ? (type).regularType : type; } function getLiteralType(value: string | number, enumId?: number, symbol?: Symbol) { @@ -10064,10 +10064,10 @@ namespace ts { function isTypeRelatedTo(source: Type, target: Type, relation: Map) { if (source.flags & TypeFlags.StringOrNumberLiteral && source.flags & TypeFlags.FreshLiteral) { - source = (source).regularType!; + source = (source).regularType; } if (target.flags & TypeFlags.StringOrNumberLiteral && target.flags & TypeFlags.FreshLiteral) { - target = (target).regularType!; + target = (target).regularType; } if (source === target || relation === comparableRelation && !(target.flags & TypeFlags.Never) && isSimpleTypeRelatedTo(target, source, relation) || @@ -10214,10 +10214,10 @@ namespace ts { */ function isRelatedTo(source: Type, target: Type, reportErrors = false, headMessage?: DiagnosticMessage): Ternary { if (source.flags & TypeFlags.StringOrNumberLiteral && source.flags & TypeFlags.FreshLiteral) { - source = (source).regularType!; + source = (source).regularType; } if (target.flags & TypeFlags.StringOrNumberLiteral && target.flags & TypeFlags.FreshLiteral) { - target = (target).regularType!; + target = (target).regularType; } if (source.flags & TypeFlags.Substitution) { source = relation === definitelyAssignableRelation ? (source).typeVariable : (source).substitute; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 3c083de234694..c3d6a0ed9d1a7 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3689,8 +3689,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)