Enable '--strictNullChecks' (#22088)

* Enable '--strictNullChecks'

* Fix API baselines

* Make sys.getEnvironmentVariable non-nullable

* make properties optional instead of using `| undefined` in thier type

* reportDiagnostics should be required

* Declare firstAccessor as non-nullable

* Make `some` a type guard

* Fix `getEnvironmentVariable` definition in tests

* Pretend transformFlags are always defined

* Fix one more use of sys.getEnvironmentVariable

* `requiredResponse` accepts undefined, remove assertions

* Mark optional properties as optional instead of using `| undefined`

* Mark optional properties as optional instead of using ` | undefined`

* Remove unnecessary null assertions

* Put the bang on the declaration instead of every use

* Make `createMapFromTemplate` require a parameter

* Mark `EmitResult.emittedFiles` and `EmitResult.sourceMaps` as optional

* Plumb through undefined in emitLsit and EmitExpressionList

* `ElementAccessExpression.argumentExpression` can not be `undefined`

* Add overloads for `writeTokenText`

* Make `shouldWriteSeparatingLineTerminator` argument non-nullable

* Make `synthesizedNodeStartsOnNewLine` argument required

* `PropertyAssignment.initializer` cannot be undefined

* Use one `!` at declaration site instead of on every use site

* Capture host in a constant and avoid null assertions

* Remove few more unused assertions

* Update baselines

* Use parameter defaults

* Update baselines

* Fix lint

* Make Symbol#valueDeclaration and Symbol#declarations non-optional to reduce assertions

* Make Node#symbol and Type#symbol non-optional to reduce assertions

* Make `flags` non-nullable to reduce assertions

* Convert some asserts to type guards

* Make `isNonLocalAlias` a type guard

* Add overload for `getSymbolOfNode` for `Declaration`

* Some more `getSymbolOfNode` changes

* Push undefined suppression into `typeToTypeNodeHelper`

* `NodeBuilderContext.tracker` is never `undefined`

* use `Debug.assertDefined`

* Remove unnecessary tag

* Mark `LiteralType.freshType` and `LiteralTupe.regularType` as required
This commit is contained in:
Andy
2018-05-22 14:46:57 -07:00
committed by GitHub
parent 3fe946df78
commit e53e56cf82
167 changed files with 4846 additions and 4735 deletions
+80 -78
View File
@@ -123,13 +123,13 @@ namespace ts {
// state used by control flow analysis
let currentFlow: FlowNode;
let currentBreakTarget: FlowLabel;
let currentContinueTarget: FlowLabel;
let currentReturnTarget: FlowLabel;
let currentTrueTarget: FlowLabel;
let currentFalseTarget: FlowLabel;
let preSwitchCaseFlow: FlowNode;
let activeLabels: ActiveLabel[];
let currentBreakTarget: FlowLabel | undefined;
let currentContinueTarget: FlowLabel | undefined;
let currentReturnTarget: FlowLabel | undefined;
let currentTrueTarget: FlowLabel | undefined;
let currentFalseTarget: FlowLabel | undefined;
let preSwitchCaseFlow: FlowNode | undefined;
let activeLabels: ActiveLabel[] | undefined;
let hasExplicitReturn: boolean;
// state used for emit helpers
@@ -180,23 +180,23 @@ namespace ts {
delayedBindJSDocTypedefTag();
}
file = undefined;
options = undefined;
languageVersion = undefined;
parent = undefined;
container = undefined;
thisParentContainer = undefined;
blockScopeContainer = undefined;
lastContainer = undefined;
delayedTypeAliases = undefined;
file = undefined!;
options = undefined!;
languageVersion = undefined!;
parent = undefined!;
container = undefined!;
thisParentContainer = undefined!;
blockScopeContainer = undefined!;
lastContainer = undefined!;
delayedTypeAliases = undefined!;
seenThisKeyword = false;
currentFlow = undefined;
currentFlow = undefined!;
currentBreakTarget = undefined;
currentContinueTarget = undefined;
currentReturnTarget = undefined;
currentTrueTarget = undefined;
currentFalseTarget = undefined;
activeLabels = undefined;
activeLabels = undefined!;
hasExplicitReturn = false;
emitFlags = NodeFlags.None;
subtreeTransformFlags = TransformFlags.None;
@@ -234,7 +234,7 @@ namespace ts {
}
if (symbolFlags & SymbolFlags.Value) {
const valueDeclaration = symbol.valueDeclaration;
const { valueDeclaration } = symbol;
if (!valueDeclaration ||
(valueDeclaration.kind !== node.kind && valueDeclaration.kind === SyntaxKind.ModuleDeclaration)) {
// other kinds of value declarations take precedence over modules
@@ -245,7 +245,7 @@ namespace ts {
// Should not be called on a declaration with a computed property name,
// unless it is a well known Symbol.
function getDeclarationName(node: Declaration): __String {
function getDeclarationName(node: Declaration): __String | undefined {
if (node.kind === SyntaxKind.ExportAssignment) {
return (<ExportAssignment>node).isExportEquals ? InternalSymbolName.ExportEquals : InternalSymbolName.Default;
}
@@ -306,7 +306,7 @@ namespace ts {
}
function getDisplayName(node: Declaration): string {
return isNamedDeclaration(node) ? declarationNameToString(node.name) : unescapeLeadingUnderscores(getDeclarationName(node));
return isNamedDeclaration(node) ? declarationNameToString(node.name) : unescapeLeadingUnderscores(getDeclarationName(node)!); // TODO: GH#18217
}
/**
@@ -317,7 +317,7 @@ namespace ts {
* @param includes - The SymbolFlags that node has in addition to its declaration type (eg: export, ambient, etc.)
* @param excludes - The flags which node cannot be declared alongside in a symbol table. Used to report forbidden declarations.
*/
function declareSymbol(symbolTable: SymbolTable, parent: Symbol, node: Declaration, includes: SymbolFlags, excludes: SymbolFlags, isReplaceableByMethod?: boolean): Symbol {
function declareSymbol(symbolTable: SymbolTable, parent: Symbol | undefined, node: Declaration, includes: SymbolFlags, excludes: SymbolFlags, isReplaceableByMethod?: boolean): Symbol {
Debug.assert(!hasDynamicName(node));
const isDefaultExport = hasModifier(node, ModifierFlags.Default);
@@ -325,7 +325,7 @@ namespace ts {
// The exported symbol for an export default function/class node is always named "default"
const name = isDefaultExport && parent ? InternalSymbolName.Default : getDeclarationName(node);
let symbol: Symbol;
let symbol: Symbol | undefined;
if (name === undefined) {
symbol = createSymbol(SymbolFlags.None, InternalSymbolName.Missing);
}
@@ -432,10 +432,10 @@ namespace ts {
const hasExportModifier = getCombinedModifierFlags(node) & ModifierFlags.Export;
if (symbolFlags & SymbolFlags.Alias) {
if (node.kind === SyntaxKind.ExportSpecifier || (node.kind === SyntaxKind.ImportEqualsDeclaration && hasExportModifier)) {
return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes);
return declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes);
}
else {
return declareSymbol(container.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes);
return declareSymbol(container.locals!, /*parent*/ undefined, node, symbolFlags, symbolExcludes);
}
}
else {
@@ -457,16 +457,16 @@ namespace ts {
if (isJSDocTypeAlias(node)) Debug.assert(isInJavaScriptFile(node)); // We shouldn't add symbols for JSDoc nodes if not in a JS file.
if ((!isAmbientModule(node) && (hasExportModifier || container.flags & NodeFlags.ExportContext)) || isJSDocTypeAlias(node)) {
if (hasModifier(node, ModifierFlags.Default) && !getDeclarationName(node)) {
return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); // No local symbol for an unnamed default!
return declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes); // No local symbol for an unnamed default!
}
const exportKind = symbolFlags & SymbolFlags.Value ? SymbolFlags.ExportValue : 0;
const local = declareSymbol(container.locals, /*parent*/ undefined, node, exportKind, symbolExcludes);
local.exportSymbol = declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes);
const local = declareSymbol(container.locals!, /*parent*/ undefined, node, exportKind, symbolExcludes);
local.exportSymbol = declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes);
node.localSymbol = local;
return local;
}
else {
return declareSymbol(container.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes);
return declareSymbol(container.locals!, /*parent*/ undefined, node, symbolFlags, symbolExcludes);
}
}
}
@@ -547,6 +547,7 @@ namespace ts {
if (node.kind === SyntaxKind.SourceFile) {
node.flags |= emitFlags;
}
if (currentReturnTarget) {
addAntecedent(currentReturnTarget, currentFlow);
currentFlow = finishFlowLabel(currentReturnTarget);
@@ -595,12 +596,12 @@ namespace ts {
}
}
function bindEachFunctionsFirst(nodes: NodeArray<Node>) {
function bindEachFunctionsFirst(nodes: NodeArray<Node> | undefined): void {
bindEach(nodes, n => n.kind === SyntaxKind.FunctionDeclaration ? bind(n) : undefined);
bindEach(nodes, n => n.kind !== SyntaxKind.FunctionDeclaration ? bind(n) : undefined);
}
function bindEach(nodes: NodeArray<Node>, bindFunction = bind) {
function bindEach(nodes: NodeArray<Node> | undefined, bindFunction: (node: Node) => void = bind): void {
if (nodes === undefined) {
return;
}
@@ -820,7 +821,7 @@ namespace ts {
}
}
function createFlowCondition(flags: FlowFlags, antecedent: FlowNode, expression: Expression): FlowNode {
function createFlowCondition(flags: FlowFlags, antecedent: FlowNode, expression: Expression | undefined): FlowNode {
if (antecedent.flags & FlowFlags.Unreachable) {
return antecedent;
}
@@ -907,7 +908,7 @@ namespace ts {
return !isStatementCondition(node) && !isLogicalExpression(node.parent);
}
function bindCondition(node: Expression, trueTarget: FlowLabel, falseTarget: FlowLabel) {
function bindCondition(node: Expression | undefined, trueTarget: FlowLabel, falseTarget: FlowLabel) {
const saveTrueTarget = currentTrueTarget;
const saveFalseTarget = currentFalseTarget;
currentTrueTarget = trueTarget;
@@ -947,7 +948,7 @@ namespace ts {
function bindDoStatement(node: DoStatement): void {
const preDoLabel = createLoopLabel();
const enclosingLabeledStatement = node.parent.kind === SyntaxKind.LabeledStatement
? lastOrUndefined(activeLabels)
? lastOrUndefined(activeLabels!)
: undefined;
// if do statement is wrapped in labeled statement then target labels for break/continue with or without
// label should be the same
@@ -1032,7 +1033,7 @@ namespace ts {
return undefined;
}
function bindBreakOrContinueFlow(node: BreakOrContinueStatement, breakTarget: FlowLabel, continueTarget: FlowLabel) {
function bindBreakOrContinueFlow(node: BreakOrContinueStatement, breakTarget: FlowLabel | undefined, continueTarget: FlowLabel | undefined) {
const flowLabel = node.kind === SyntaxKind.BreakStatement ? breakTarget : continueTarget;
if (flowLabel) {
addAntecedent(flowLabel, currentFlow);
@@ -1162,7 +1163,8 @@ namespace ts {
i++;
}
const preCaseLabel = createBranchLabel();
addAntecedent(preCaseLabel, createFlowSwitchClause(preSwitchCaseFlow, node.parent, clauseStart, i + 1));
addAntecedent(preCaseLabel, createFlowSwitchClause(preSwitchCaseFlow!, node.parent, clauseStart, i + 1));
addAntecedent(preCaseLabel, createFlowSwitchClause(preSwitchCaseFlow!, node.parent, clauseStart, i + 1));
addAntecedent(preCaseLabel, fallthroughFlow);
currentFlow = finishFlowLabel(preCaseLabel);
const clause = clauses[i];
@@ -1178,7 +1180,7 @@ namespace ts {
function bindCaseClause(node: CaseClause): void {
const saveCurrentFlow = currentFlow;
currentFlow = preSwitchCaseFlow;
currentFlow = preSwitchCaseFlow!;
bind(node.expression);
currentFlow = saveCurrentFlow;
bindEach(node.statements);
@@ -1196,7 +1198,7 @@ namespace ts {
}
function popActiveLabel() {
activeLabels.pop();
activeLabels!.pop();
}
function bindLabeledStatement(node: LabeledStatement): void {
@@ -1301,7 +1303,7 @@ namespace ts {
currentFlow = finishFlowLabel(postExpressionLabel);
}
else {
bindLogicalExpression(node, currentTrueTarget, currentFalseTarget);
bindLogicalExpression(node, currentTrueTarget!, currentFalseTarget!);
}
}
else {
@@ -1478,7 +1480,7 @@ namespace ts {
lastContainer = next;
}
function declareSymbolAndAddToSymbolTable(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags): Symbol {
function declareSymbolAndAddToSymbolTable(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags): Symbol | undefined {
switch (container.kind) {
// Modules, source files, and classes need specialized handling for how their
// members are declared (for example, a member of a class will go into a specific
@@ -1495,7 +1497,7 @@ namespace ts {
return declareClassMember(node, symbolFlags, symbolExcludes);
case SyntaxKind.EnumDeclaration:
return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes);
return declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes);
case SyntaxKind.TypeLiteral:
case SyntaxKind.JSDocTypeLiteral:
@@ -1507,7 +1509,7 @@ namespace ts {
// container, and are never in scope otherwise (even inside the body of the
// object / type / interface declaring them). An exception is type parameters,
// which are in scope without qualification (similar to 'locals').
return declareSymbol(container.symbol.members, container.symbol, node, symbolFlags, symbolExcludes);
return declareSymbol(container.symbol.members!, container.symbol, node, symbolFlags, symbolExcludes);
case SyntaxKind.FunctionType:
case SyntaxKind.ConstructorType:
@@ -1534,20 +1536,20 @@ namespace ts {
// their container in the tree). To accomplish this, we simply add their declared
// symbol to the 'locals' of the container. These symbols can then be found as
// the type checker walks up the containers, checking them for matching names.
return declareSymbol(container.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes);
return declareSymbol(container.locals!, /*parent*/ undefined, node, symbolFlags, symbolExcludes);
}
}
function declareClassMember(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags) {
return hasModifier(node, ModifierFlags.Static)
? declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes)
: declareSymbol(container.symbol.members, container.symbol, node, symbolFlags, symbolExcludes);
? declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes)
: declareSymbol(container.symbol.members!, container.symbol, node, symbolFlags, symbolExcludes);
}
function declareSourceFileMember(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags) {
return isExternalModule(file)
? declareModuleMember(node, symbolFlags, symbolExcludes)
: declareSymbol(file.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes);
: declareSymbol(file.locals!, /*parent*/ undefined, node, symbolFlags, symbolExcludes);
}
function hasExportDeclarations(node: ModuleDeclaration | SourceFile): boolean {
@@ -1594,8 +1596,8 @@ namespace ts {
}
}
const symbol = declareSymbolAndAddToSymbolTable(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes);
file.patternAmbientModules = append(file.patternAmbientModules, pattern && { pattern, symbol });
const symbol = declareSymbolAndAddToSymbolTable(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes)!;
file.patternAmbientModules = append<PatternAmbientModule>(file.patternAmbientModules, pattern && { pattern, symbol });
}
}
else {
@@ -1628,7 +1630,7 @@ namespace ts {
// We do that by making an anonymous type literal symbol, and then setting the function
// symbol as its sole member. To the rest of the system, this symbol will be indistinguishable
// from an actual type literal symbol you would have gotten had you used the long form.
const symbol = createSymbol(SymbolFlags.Signature, getDeclarationName(node));
const symbol = createSymbol(SymbolFlags.Signature, getDeclarationName(node)!); // TODO: GH#18217
addDeclarationToSymbol(symbol, node, SymbolFlags.Signature);
const typeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, InternalSymbolName.Type);
@@ -1757,8 +1759,8 @@ namespace ts {
// check for reserved words used as identifiers in strict mode code.
function checkStrictModeIdentifier(node: Identifier) {
if (inStrictMode &&
node.originalKeywordKind >= SyntaxKind.FirstFutureReservedWord &&
node.originalKeywordKind <= SyntaxKind.LastFutureReservedWord &&
node.originalKeywordKind! >= SyntaxKind.FirstFutureReservedWord &&
node.originalKeywordKind! <= SyntaxKind.LastFutureReservedWord &&
!isIdentifierName(node) &&
!(node.flags & NodeFlags.Ambient)) {
@@ -1814,7 +1816,7 @@ namespace ts {
return isIdentifier(node) && (node.escapedText === "eval" || node.escapedText === "arguments");
}
function checkStrictModeEvalOrArguments(contextNode: Node, name: Node) {
function checkStrictModeEvalOrArguments(contextNode: Node, name: Node | undefined) {
if (name && name.kind === SyntaxKind.Identifier) {
const identifier = <Identifier>name;
if (isEvalOrArgumentsIdentifier(identifier)) {
@@ -1925,7 +1927,7 @@ namespace ts {
}
}
function bind(node: Node): void {
function bind(node: Node | undefined): void {
if (!node) {
return;
}
@@ -1980,12 +1982,12 @@ namespace ts {
function bindJSDoc(node: Node) {
if (hasJSDocNodes(node)) {
if (isInJavaScriptFile(node)) {
for (const j of node.jsDoc) {
for (const j of node.jsDoc!) {
bind(j);
}
}
else {
for (const j of node.jsDoc) {
for (const j of node.jsDoc!) {
setParentPointers(node, j);
}
}
@@ -2231,7 +2233,7 @@ namespace ts {
bindSourceFileAsExternalModule();
// Create symbol equivalent for the module.exports = {}
const originalSymbol = file.symbol;
declareSymbol(file.symbol.exports, file.symbol, file, SymbolFlags.Property, SymbolFlags.All);
declareSymbol(file.symbol.exports!, file.symbol, file, SymbolFlags.Property, SymbolFlags.All);
file.symbol = originalSymbol;
}
}
@@ -2243,7 +2245,7 @@ namespace ts {
function bindExportAssignment(node: ExportAssignment) {
if (!container.symbol || !container.symbol.exports) {
// Export assignment in some sort of block construct
bindAnonymousDeclaration(node, SymbolFlags.Alias, getDeclarationName(node));
bindAnonymousDeclaration(node, SymbolFlags.Alias, getDeclarationName(node)!);
}
else {
const flags = node.kind === SyntaxKind.ExportAssignment && exportAssignmentIsAlias(node)
@@ -2287,7 +2289,7 @@ namespace ts {
function bindExportDeclaration(node: ExportDeclaration) {
if (!container.symbol || !container.symbol.exports) {
// Export * in some sort of block construct
bindAnonymousDeclaration(node, SymbolFlags.ExportStar, getDeclarationName(node));
bindAnonymousDeclaration(node, SymbolFlags.ExportStar, getDeclarationName(node)!);
}
else if (!node.exportClause) {
// All export * declarations are collected in an __export symbol
@@ -2319,7 +2321,7 @@ namespace ts {
if (!original) {
return undefined;
}
const s = getJSInitializerSymbol(original);
const s = getJSInitializerSymbol(original)!;
addDeclarationToSymbol(s, id, SymbolFlags.Module | SymbolFlags.JSContainer);
return s;
});
@@ -2327,7 +2329,7 @@ namespace ts {
const flags = isClassExpression(node.right) ?
SymbolFlags.Property | SymbolFlags.ExportValue | SymbolFlags.Class :
SymbolFlags.Property | SymbolFlags.ExportValue;
declareSymbol(symbol.exports, symbol, lhs, flags, SymbolFlags.None);
declareSymbol(symbol.exports!, symbol, lhs, flags, SymbolFlags.None);
}
}
@@ -2348,7 +2350,7 @@ namespace ts {
const flags = exportAssignmentIsAlias(node)
? SymbolFlags.Alias // An export= with an EntityNameExpression or a ClassExpression exports all meanings of that identifier or class
: SymbolFlags.Property | SymbolFlags.ExportValue | SymbolFlags.ValueModule;
declareSymbol(file.symbol.exports, file.symbol, node, flags, SymbolFlags.None);
declareSymbol(file.symbol.exports!, file.symbol, node, flags, SymbolFlags.None);
}
function bindThisPropertyAssignment(node: BinaryExpression | PropertyAccessExpression) {
@@ -2362,7 +2364,7 @@ namespace ts {
if (isBinaryExpression(thisContainer.parent) && thisContainer.parent.operatorToken.kind === SyntaxKind.EqualsToken) {
const l = thisContainer.parent.left;
if (isPropertyAccessEntityNameExpression(l) && isPrototypeAccess(l.expression)) {
constructorSymbol = getJSInitializerSymbolFromName(l.expression.expression, thisParentContainer);
constructorSymbol = getJSInitializerSymbolFromName(l.expression.expression, thisParentContainer)!;
}
}
@@ -2382,7 +2384,7 @@ namespace ts {
// this.foo assignment in a JavaScript class
// Bind this property to the containing class
const containingClass = thisContainer.parent;
const symbolTable = hasModifier(thisContainer, ModifierFlags.Static) ? containingClass.symbol.exports : containingClass.symbol.members;
const symbolTable = hasModifier(thisContainer, ModifierFlags.Static) ? containingClass.symbol.exports! : containingClass.symbol.members!;
declareSymbol(symbolTable, containingClass.symbol, node, SymbolFlags.Property, SymbolFlags.None, /*isReplaceableByMethod*/ true);
break;
case SyntaxKind.SourceFile:
@@ -2461,7 +2463,7 @@ namespace ts {
bindPropertyAssignment(node.expression, node, /*isPrototypeProperty*/ false);
}
function getJSInitializerSymbolFromName(name: EntityNameExpression, lookupContainer?: Node): Symbol {
function getJSInitializerSymbolFromName(name: EntityNameExpression, lookupContainer?: Node): Symbol | undefined {
return getJSInitializerSymbol(lookupSymbolForPropertyAccess(name, lookupContainer));
}
@@ -2482,7 +2484,7 @@ namespace ts {
return original;
}
else {
return symbol = declareSymbol(symbol ? symbol.exports : container.locals, symbol, id, flags, excludeFlags);
return symbol = declareSymbol(symbol ? symbol.exports! : container.locals!, symbol, id, flags, excludeFlags);
}
});
}
@@ -2497,7 +2499,7 @@ namespace ts {
// Declare the method/property
const jsContainerFlag = isToplevelNamespaceableInitializer ? SymbolFlags.JSContainer : 0;
const isMethod = isFunctionLikeDeclaration(getAssignedJavascriptInitializer(propertyAccess));
const isMethod = isFunctionLikeDeclaration(getAssignedJavascriptInitializer(propertyAccess)!); // TODO: GH#18217
const symbolFlags = (isMethod ? SymbolFlags.Method : SymbolFlags.Property) | jsContainerFlag;
const symbolExcludes = (isMethod ? SymbolFlags.MethodExcludes : SymbolFlags.PropertyExcludes) & ~jsContainerFlag;
declareSymbol(symbolTable, symbol, propertyAccess, symbolFlags, symbolExcludes);
@@ -2520,7 +2522,7 @@ namespace ts {
}
}
function forEachIdentifierInEntityName(e: EntityNameExpression, action: (e: Identifier, symbol: Symbol) => Symbol): Symbol {
function forEachIdentifierInEntityName(e: EntityNameExpression, action: (e: Identifier, symbol: Symbol | undefined) => Symbol | undefined): Symbol | undefined {
if (isExportsOrModuleExportsOrAlias(file, e)) {
return file.symbol;
}
@@ -2529,7 +2531,7 @@ namespace ts {
}
else {
const s = getJSInitializerSymbol(forEachIdentifierInEntityName(e.expression, action));
Debug.assert(!!s && !!s.exports);
if (!s || !s.exports) return Debug.fail();
return action(e.name, s.exports.get(e.name.escapedText));
}
}
@@ -2555,7 +2557,7 @@ namespace ts {
}
}
const symbol = node.symbol;
const { symbol } = node;
// TypeScript 1.0 spec (April 2014): 8.4
// Every class automatically contains a static property member named 'prototype', the
@@ -2567,14 +2569,14 @@ namespace ts {
// module might have an exported variable called 'prototype'. We can't allow that as
// that would clash with the built-in 'prototype' for the class.
const prototypeSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Prototype, "prototype" as __String);
const symbolExport = symbol.exports.get(prototypeSymbol.escapedName);
const symbolExport = symbol.exports!.get(prototypeSymbol.escapedName);
if (symbolExport) {
if (node.name) {
node.name.parent = node;
}
file.bindDiagnostics.push(createDiagnosticForNode(symbolExport.declarations[0], Diagnostics.Duplicate_identifier_0, symbolName(prototypeSymbol)));
}
symbol.exports.set(prototypeSymbol.escapedName, prototypeSymbol);
symbol.exports!.set(prototypeSymbol.escapedName, prototypeSymbol);
prototypeSymbol.parent = symbol;
}
@@ -2632,7 +2634,7 @@ namespace ts {
// containing class.
if (isParameterPropertyDeclaration(node)) {
const classDeclaration = <ClassLikeDeclaration>node.parent.parent;
declareSymbol(classDeclaration.symbol.members, classDeclaration.symbol, node, SymbolFlags.Property | (node.questionToken ? SymbolFlags.Optional : SymbolFlags.None), SymbolFlags.PropertyExcludes);
declareSymbol(classDeclaration.symbol.members!, classDeclaration.symbol, node, SymbolFlags.Property | (node.questionToken ? SymbolFlags.Optional : SymbolFlags.None), SymbolFlags.PropertyExcludes);
}
}
@@ -2681,14 +2683,14 @@ namespace ts {
: declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes);
}
function getInferTypeContainer(node: Node): ConditionalTypeNode {
function getInferTypeContainer(node: Node): ConditionalTypeNode | undefined {
const extendsType = findAncestor(node, n => n.parent && isConditionalTypeNode(n.parent) && n.parent.extendsType === n);
return extendsType && extendsType.parent as ConditionalTypeNode;
}
function bindTypeParameter(node: TypeParameterDeclaration) {
if (isJSDocTemplateTag(node.parent)) {
const container = find((node.parent.parent as JSDoc).tags, isJSDocTypeAlias) || getHostSignatureFromJSDoc(node.parent);
const container = find((node.parent.parent as JSDoc).tags!, isJSDocTypeAlias) || getHostSignatureFromJSDoc(node.parent); // TODO: GH#18217
if (container) {
if (!container.locals) {
container.locals = createSymbolTable();
@@ -2708,7 +2710,7 @@ namespace ts {
declareSymbol(container.locals, /*parent*/ undefined, node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes);
}
else {
bindAnonymousDeclaration(node, SymbolFlags.TypeParameter, getDeclarationName(node));
bindAnonymousDeclaration(node, SymbolFlags.TypeParameter, getDeclarationName(node)!); // TODO: GH#18217
}
}
else {
@@ -2720,7 +2722,7 @@ namespace ts {
function shouldReportErrorOnModuleDeclaration(node: ModuleDeclaration): boolean {
const instanceState = getModuleInstanceState(node);
return instanceState === ModuleInstanceState.Instantiated || (instanceState === ModuleInstanceState.ConstEnumOnly && options.preserveConstEnums);
return instanceState === ModuleInstanceState.Instantiated || (instanceState === ModuleInstanceState.ConstEnumOnly && !!options.preserveConstEnums);
}
function checkUnreachable(node: Node): boolean {
@@ -2777,8 +2779,8 @@ namespace ts {
function isNameOfExportsOrModuleExportsAliasDeclaration(sourceFile: SourceFile, node: Identifier): boolean {
const symbol = lookupSymbolForNameWorker(sourceFile, node.escapedText);
return symbol && symbol.valueDeclaration && isVariableDeclaration(symbol.valueDeclaration) &&
symbol.valueDeclaration.initializer && isExportsOrModuleExportsOrAliasOrAssignment(sourceFile, symbol.valueDeclaration.initializer);
return !!symbol && !!symbol.valueDeclaration && isVariableDeclaration(symbol.valueDeclaration) &&
!!symbol.valueDeclaration.initializer && isExportsOrModuleExportsOrAliasOrAssignment(sourceFile, symbol.valueDeclaration.initializer);
}
function isExportsOrModuleExportsOrAliasOrAssignment(sourceFile: SourceFile, node: Expression): boolean {
+32 -31
View File
@@ -3,6 +3,7 @@ namespace ts {
/**
* State to store the changed files, affected files and cache semantic diagnostics
*/
// TODO: GH#18217 Properties of this interface are frequently asserted to be defined.
export interface BuilderProgramState extends BuilderState {
/**
* Cache of semantic diagnostics for files with their Path being the key
@@ -41,7 +42,7 @@ namespace ts {
function hasSameKeys<T, U>(map1: ReadonlyMap<T> | undefined, map2: ReadonlyMap<U> | undefined): boolean {
// Has same size and every key is present in both maps
return map1 as ReadonlyMap<T | U> === map2 || map1 && map2 && map1.size === map2.size && !forEachKey(map1, key => !map2.has(key));
return map1 as ReadonlyMap<T | U> === map2 || map1 !== undefined && map2 !== undefined && map1.size === map2.size && !forEachKey(map1, key => !map2.has(key));
}
/**
@@ -56,45 +57,45 @@ namespace ts {
}
state.changedFilesSet = createMap<true>();
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<BuilderState.FileInfo>;
let newReferences: BuilderState.ReferencedSet;
let oldInfo: Readonly<BuilderState.FileInfo> | undefined;
let newReferences: BuilderState.ReferencedSet | undefined;
// if not using old state, every file is changed
if (!useOldState ||
// File wasnt present in old state
!(oldInfo = oldState.fileInfos.get(sourceFilePath)) ||
!(oldInfo = oldState!.fileInfos.get(sourceFilePath)) ||
// versions dont match
oldInfo.version !== info.version ||
// Referenced files changed
!hasSameKeys(newReferences = referencedMap && referencedMap.get(sourceFilePath), oldReferencedMap && oldReferencedMap.get(sourceFilePath)) ||
// Referenced file was deleted in the new program
newReferences && forEachKey(newReferences, path => !state.fileInfos.has(path) && oldState.fileInfos.has(path))) {
newReferences && forEachKey(newReferences, path => !state.fileInfos.has(path) && oldState!.fileInfos.has(path))) {
// Register file as changed file and do not copy semantic diagnostics, since all changed files need to be re-evaluated
state.changedFilesSet.set(sourceFilePath, true);
}
else if (canCopySemanticDiagnostics) {
// Unchanged file copy diagnostics
const diagnostics = oldState.semanticDiagnosticsPerFile.get(sourceFilePath);
const diagnostics = oldState!.semanticDiagnosticsPerFile!.get(sourceFilePath);
if (diagnostics) {
state.semanticDiagnosticsPerFile.set(sourceFilePath, diagnostics);
state.semanticDiagnosticsPerFile!.set(sourceFilePath, diagnostics);
}
}
});
@@ -106,7 +107,7 @@ namespace ts {
* Verifies that source file is ok to be used in calls that arent handled by next
*/
function assertSourceFileOkWithoutNextAffectedCall(state: BuilderProgramState, sourceFile: SourceFile | undefined) {
Debug.assert(!sourceFile || !state.affectedFiles || state.affectedFiles[state.affectedFilesIndex - 1] !== sourceFile || !state.semanticDiagnosticsPerFile.has(sourceFile.path));
Debug.assert(!sourceFile || !state.affectedFiles || state.affectedFiles[state.affectedFilesIndex! - 1] !== sourceFile || !state.semanticDiagnosticsPerFile!.has(sourceFile.path));
}
/**
@@ -120,25 +121,25 @@ namespace ts {
const { affectedFiles } = state;
if (affectedFiles) {
const { seenAffectedFiles, semanticDiagnosticsPerFile } = state;
let { affectedFilesIndex } = state;
let affectedFilesIndex = state.affectedFilesIndex!; // TODO: GH#18217
while (affectedFilesIndex < affectedFiles.length) {
const affectedFile = affectedFiles[affectedFilesIndex];
if (!seenAffectedFiles.has(affectedFile.path)) {
if (!seenAffectedFiles!.has(affectedFile.path)) {
// Set the next affected file as seen and remove the cached semantic diagnostics
state.affectedFilesIndex = affectedFilesIndex;
semanticDiagnosticsPerFile.delete(affectedFile.path);
semanticDiagnosticsPerFile!.delete(affectedFile.path);
return affectedFile;
}
seenAffectedFiles.set(affectedFile.path, true);
seenAffectedFiles!.set(affectedFile.path, true);
affectedFilesIndex++;
}
// Remove the changed file from the change set
state.changedFilesSet.delete(state.currentChangedFilePath);
state.changedFilesSet.delete(state.currentChangedFilePath!);
state.currentChangedFilePath = undefined;
// Commit the changes in file signature
BuilderState.updateSignaturesFromCache(state, state.currentAffectedFilesSignatures);
state.currentAffectedFilesSignatures.clear();
BuilderState.updateSignaturesFromCache(state, state.currentAffectedFilesSignatures!);
state.currentAffectedFilesSignatures!.clear();
state.affectedFiles = undefined;
}
@@ -161,7 +162,7 @@ namespace ts {
state.currentAffectedFilesSignatures = state.currentAffectedFilesSignatures || createMap();
state.affectedFiles = BuilderState.getFilesAffectedBy(state, state.program, nextKey.value as Path, cancellationToken, computeHash, state.currentAffectedFilesSignatures);
state.currentChangedFilePath = nextKey.value as Path;
state.semanticDiagnosticsPerFile.delete(nextKey.value as Path);
state.semanticDiagnosticsPerFile!.delete(nextKey.value as Path);
state.affectedFilesIndex = 0;
state.seenAffectedFiles = state.seenAffectedFiles || createMap<true>();
}
@@ -176,8 +177,8 @@ namespace ts {
state.changedFilesSet.clear();
}
else {
state.seenAffectedFiles.set((affected as SourceFile).path, true);
state.affectedFilesIndex++;
state.seenAffectedFiles!.set((affected as SourceFile).path, true);
state.affectedFilesIndex!++;
}
}
@@ -195,7 +196,7 @@ namespace ts {
*/
function getSemanticDiagnosticsOfFile(state: BuilderProgramState, sourceFile: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic> {
const path = sourceFile.path;
const cachedDiagnostics = state.semanticDiagnosticsPerFile.get(path);
const cachedDiagnostics = state.semanticDiagnosticsPerFile!.get(path);
// Report the semantic diagnostics from the cache if we already have those diagnostics present
if (cachedDiagnostics) {
return cachedDiagnostics;
@@ -203,7 +204,7 @@ namespace ts {
// Diagnostics werent cached, get them from program, and cache the result
const diagnostics = state.program.getSemanticDiagnostics(sourceFile, cancellationToken);
state.semanticDiagnosticsPerFile.set(path, diagnostics);
state.semanticDiagnosticsPerFile!.set(path, diagnostics);
return diagnostics;
}
@@ -250,7 +251,7 @@ namespace ts {
// Return same program if underlying program doesnt change
let oldState = oldProgram && oldProgram.getState();
if (oldState && newProgram === oldState.program && configFileParsingDiagnostics === newProgram.getConfigFileParsingDiagnostics()) {
newProgram = undefined;
newProgram = undefined!; // TODO: GH#18217
oldState = undefined;
return oldProgram;
}
@@ -266,7 +267,7 @@ namespace ts {
const state = createBuilderProgramState(newProgram, getCanonicalFileName, oldState);
// To ensure that we arent storing any references to old program or new program without state
newProgram = undefined;
newProgram = undefined!; // TODO: GH#18217
oldProgram = undefined;
oldState = undefined;
@@ -336,8 +337,8 @@ namespace ts {
if (!targetSourceFile) {
// Emit and report any errors we ran into.
let sourceMaps: SourceMapData[] = [];
let emitSkipped: boolean;
let diagnostics: Diagnostic[];
let emitSkipped = false;
let diagnostics: Diagnostic[] | undefined;
let emittedFiles: string[] = [];
let affectedEmitResult: AffectedFileResult<EmitResult>;
@@ -423,7 +424,7 @@ namespace ts {
}
}
let diagnostics: Diagnostic[];
let diagnostics: Diagnostic[] | undefined;
for (const sourceFile of state.program.getSourceFiles()) {
diagnostics = addRange(diagnostics, getSemanticDiagnosticsOfFile(state, sourceFile, cancellationToken));
}
+12 -12
View File
@@ -108,7 +108,7 @@ namespace ts.BuilderState {
return;
}
const fileName = resolvedTypeReferenceDirective.resolvedFileName;
const fileName = resolvedTypeReferenceDirective.resolvedFileName!; // TODO: GH#18217
const typeFilePath = toPath(fileName, sourceFileDirectory, getCanonicalFileName);
addReferencedFile(typeFilePath);
});
@@ -127,7 +127,7 @@ namespace ts.BuilderState {
/**
* Returns true if oldState is reusable, that is the emitKind = module/non module has not changed
*/
export function canReuseOldState(newReferencedMap: ReadonlyMap<ReferencedSet>, oldState: Readonly<BuilderState> | undefined) {
export function canReuseOldState(newReferencedMap: ReadonlyMap<ReferencedSet> | undefined, oldState: Readonly<BuilderState> | undefined) {
return oldState && !oldState.referencedMap === !newReferencedMap;
}
@@ -143,7 +143,7 @@ namespace ts.BuilderState {
// Create the reference map, and set the file infos
for (const sourceFile of newProgram.getSourceFiles()) {
const version = sourceFile.version;
const oldInfo = useOldState && oldState.fileInfos.get(sourceFile.path);
const oldInfo = useOldState ? oldState!.fileInfos.get(sourceFile.path) : undefined;
if (referencedMap) {
const newReferences = getReferencedFiles(newProgram, sourceFile, getCanonicalFileName);
if (newReferences) {
@@ -194,7 +194,7 @@ namespace ts.BuilderState {
*/
export function updateSignaturesFromCache(state: BuilderState, signatureCache: Map<string>) {
signatureCache.forEach((signature, path) => {
state.fileInfos.get(path).signature = signature;
state.fileInfos.get(path)!.signature = signature;
state.hasCalledUpdateShapeSignature.set(path, true);
});
}
@@ -211,7 +211,7 @@ namespace ts.BuilderState {
}
const info = state.fileInfos.get(sourceFile.path);
Debug.assert(!!info);
if (!info) return Debug.fail();
const prevSignature = info.signature;
let latestSignature: string;
@@ -224,7 +224,7 @@ namespace ts.BuilderState {
latestSignature = computeHash(emitOutput.outputFiles[0].text);
}
else {
latestSignature = prevSignature;
latestSignature = prevSignature!; // TODO: GH#18217
}
}
cacheToUpdateSignature.set(sourceFile.path, latestSignature);
@@ -251,7 +251,7 @@ namespace ts.BuilderState {
const seenMap = createMap<true>();
const queue = [sourceFile.path];
while (queue.length) {
const path = queue.pop();
const path = queue.pop()!;
if (!seenMap.has(path)) {
seenMap.set(path, true);
const references = state.referencedMap.get(path);
@@ -285,7 +285,7 @@ namespace ts.BuilderState {
* Gets the files referenced by the the file path
*/
function getReferencedByPaths(state: Readonly<BuilderState>, referencedFilePath: Path) {
return arrayFrom(mapDefinedIterator(state.referencedMap.entries(), ([filePath, referencesInFile]) =>
return arrayFrom(mapDefinedIterator(state.referencedMap!.entries(), ([filePath, referencesInFile]) =>
referencesInFile.has(referencedFilePath) ? filePath as Path : undefined
));
}
@@ -314,7 +314,7 @@ namespace ts.BuilderState {
return state.allFilesExcludingDefaultLibraryFile;
}
let result: SourceFile[];
let result: SourceFile[] | undefined;
addSourceFile(firstSourceFile);
for (const sourceFile of programOfThisState.getSourceFiles()) {
if (sourceFile !== firstSourceFile) {
@@ -366,11 +366,11 @@ namespace ts.BuilderState {
seenFileNamesMap.set(sourceFileWithUpdatedShape.path, sourceFileWithUpdatedShape);
const queue = getReferencedByPaths(state, sourceFileWithUpdatedShape.path);
while (queue.length > 0) {
const currentPath = queue.pop();
const currentPath = queue.pop()!;
if (!seenFileNamesMap.has(currentPath)) {
const currentSourceFile = programOfThisState.getSourceFileByPath(currentPath);
const currentSourceFile = programOfThisState.getSourceFileByPath(currentPath)!;
seenFileNamesMap.set(currentPath, currentSourceFile);
if (currentSourceFile && updateShapeSignature(state, programOfThisState, currentSourceFile, cacheToUpdateSignature, cancellationToken, computeHash)) {
if (currentSourceFile && updateShapeSignature(state, programOfThisState, currentSourceFile, cacheToUpdateSignature, cancellationToken, computeHash!)) { // TODO: GH#18217
queue.push(...getReferencedByPaths(state, currentPath));
}
}
+1085 -1009
View File
File diff suppressed because it is too large Load Diff
+38 -40
View File
@@ -814,7 +814,7 @@ namespace ts {
case "string":
return map(values, v => v || "");
default:
return filter(map(values, v => parseCustomTypeOption(<CommandLineOptionOfCustomType>opt.element, v, errors)), v => !!v);
return mapDefined(values, v => parseCustomTypeOption(<CommandLineOptionOfCustomType>opt.element, v, errors));
}
}
@@ -965,7 +965,7 @@ namespace ts {
* Reads the config file, reports errors if any and exits if the config file cannot be found
*/
export function getParsedCommandLineOfConfigFile(configFileName: string, optionsToExtend: CompilerOptions, host: ParseConfigFileHost): ParsedCommandLine | undefined {
let configFileText: string;
let configFileText: string | undefined;
try {
configFileText = host.readFile(configFileName);
}
@@ -1035,7 +1035,7 @@ namespace ts {
function getTsconfigRootOptionsMap() {
if (_tsconfigRootOptions === undefined) {
_tsconfigRootOptions = {
name: undefined, // should never be needed since this is root
name: undefined!, // should never be needed since this is root
type: "object",
elementOptions: commandLineOptionsToMap([
{
@@ -1194,7 +1194,7 @@ namespace ts {
if (parentOption) {
if (isValidOptionValue) {
// Notify option set in the parent if its a valid option value
jsonConversionNotifier.onSetValidOptionKeyValueInParent(parentOption, option, value);
jsonConversionNotifier.onSetValidOptionKeyValueInParent(parentOption, option!, value);
}
}
else if (isRootOptionMap(knownOptions)) {
@@ -1220,7 +1220,7 @@ namespace ts {
return (returnValue ? elements.map : elements.forEach).call(elements, (element: Expression) => convertPropertyValueToJson(element, elementOption));
}
function convertPropertyValueToJson(valueExpression: Expression, option: CommandLineOption): any {
function convertPropertyValueToJson(valueExpression: Expression, option: CommandLineOption | undefined): any {
switch (valueExpression.kind) {
case SyntaxKind.TrueKeyword:
reportInvalidOptionValue(option && option.type !== "boolean");
@@ -1303,9 +1303,9 @@ namespace ts {
return undefined;
function reportInvalidOptionValue(isError: boolean) {
function reportInvalidOptionValue(isError: boolean | undefined) {
if (isError) {
errors.push(createDiagnosticForNodeInSourceFile(sourceFile, valueExpression, Diagnostics.Compiler_option_0_requires_a_value_of_type_1, option.name, getCompilerOptionValueTypeString(option)));
errors.push(createDiagnosticForNodeInSourceFile(sourceFile, valueExpression, Diagnostics.Compiler_option_0_requires_a_value_of_type_1, option!.name, getCompilerOptionValueTypeString(option!)));
}
}
}
@@ -1321,7 +1321,7 @@ namespace ts {
isString(option.type) ? option.type : "string";
}
function isCompilerOptionsValue(option: CommandLineOption, value: any): value is CompilerOptionsValue {
function isCompilerOptionsValue(option: CommandLineOption | undefined, value: any): value is CompilerOptionsValue {
if (option) {
if (isNullOrUndefined(value)) return true; // All options are undefinable/nullable
if (option.type === "list") {
@@ -1330,6 +1330,7 @@ namespace ts {
const expectedType = isString(option.type) ? option.type : "string";
return typeof value === expectedType;
}
return false;
}
/**
@@ -1373,7 +1374,7 @@ namespace ts {
if (hasProperty(options, name)) {
// tsconfig only options cannot be specified via command line,
// so we can assume that only types that can appear here string | number | boolean
if (optionsNameMap.has(name) && optionsNameMap.get(name).category === Diagnostics.Command_line_Options) {
if (optionsNameMap.has(name) && optionsNameMap.get(name)!.category === Diagnostics.Command_line_Options) {
continue;
}
const value = <CompilerOptionsValue>options[name];
@@ -1387,7 +1388,7 @@ namespace ts {
}
else {
if (optionDefinition.type === "list") {
result.set(name, (value as ReadonlyArray<string | number>).map(element => getNameOfCompilerOptionValue(element, customTypeMap)));
result.set(name, (value as ReadonlyArray<string | number>).map(element => getNameOfCompilerOptionValue(element, customTypeMap)!)); // TODO: GH#18217
}
else {
// There is a typeMap associated with this command-line option so use it to map value back to its name
@@ -1436,7 +1437,7 @@ namespace ts {
const { category } = option;
if (isAllowedOption(option)) {
categorizedOptions.add(getLocaleSpecificMessage(category), option);
categorizedOptions.add(getLocaleSpecificMessage(category!), option);
}
}
@@ -1517,7 +1518,7 @@ namespace ts {
}
/*@internal*/
export function setConfigFileInOptions(options: CompilerOptions, configFile: TsConfigSourceFile) {
export function setConfigFileInOptions(options: CompilerOptions, configFile: TsConfigSourceFile | undefined) {
if (configFile) {
Object.defineProperty(options, "configFile", { enumerable: false, writable: false, value: configFile });
}
@@ -1545,7 +1546,7 @@ namespace ts {
*/
function parseJsonConfigFileContentWorker(
json: any,
sourceFile: TsConfigSourceFile,
sourceFile: TsConfigSourceFile | undefined,
host: ParseConfigHost,
basePath: string,
existingOptions: CompilerOptions = {},
@@ -1575,7 +1576,7 @@ namespace ts {
};
function getFileNames(): ExpandResult {
let filesSpecs: ReadonlyArray<string>;
let filesSpecs: ReadonlyArray<string> | undefined;
if (hasProperty(raw, "files") && !isNullOrUndefined(raw.files)) {
if (isArray(raw.files)) {
filesSpecs = <ReadonlyArray<string>>raw.files;
@@ -1588,7 +1589,7 @@ namespace ts {
}
}
let includeSpecs: ReadonlyArray<string>;
let includeSpecs: ReadonlyArray<string> | undefined;
if (hasProperty(raw, "include") && !isNullOrUndefined(raw.include)) {
if (isArray(raw.include)) {
includeSpecs = <ReadonlyArray<string>>raw.include;
@@ -1598,7 +1599,7 @@ namespace ts {
}
}
let excludeSpecs: ReadonlyArray<string>;
let excludeSpecs: ReadonlyArray<string> | undefined;
if (hasProperty(raw, "exclude") && !isNullOrUndefined(raw.exclude)) {
if (isArray(raw.exclude)) {
excludeSpecs = <ReadonlyArray<string>>raw.exclude;
@@ -1692,10 +1693,10 @@ namespace ts {
*/
function parseConfig(
json: any,
sourceFile: TsConfigSourceFile,
sourceFile: TsConfigSourceFile | undefined,
host: ParseConfigHost,
basePath: string,
configFileName: string,
configFileName: string | undefined,
resolutionStack: string[],
errors: Push<Diagnostic>,
): ParsedTsconfig {
@@ -1704,17 +1705,17 @@ namespace ts {
if (resolutionStack.indexOf(resolvedPath) >= 0) {
errors.push(createCompilerDiagnostic(Diagnostics.Circularity_detected_while_resolving_configuration_Colon_0, [...resolutionStack, resolvedPath].join(" -> ")));
return { raw: json || convertToObject(sourceFile, errors) };
return { raw: json || convertToObject(sourceFile!, errors) };
}
const ownConfig = json ?
parseOwnConfigOfJson(json, host, basePath, configFileName, errors) :
parseOwnConfigOfJsonSourceFile(sourceFile, host, basePath, configFileName, errors);
parseOwnConfigOfJsonSourceFile(sourceFile!, host, basePath, configFileName, errors);
if (ownConfig.extendedConfigPath) {
// copy the resolution stack so it is never reused between branches in potential diamond-problem scenarios.
resolutionStack = resolutionStack.concat([resolvedPath]);
const extendedConfig = getExtendedConfig(sourceFile, ownConfig.extendedConfigPath, host, basePath, resolutionStack, errors);
const extendedConfig = getExtendedConfig(sourceFile!, ownConfig.extendedConfigPath, host, basePath, resolutionStack, errors);
if (extendedConfig && isSuccessfulParsedTsconfig(extendedConfig)) {
const baseRaw = extendedConfig.raw;
const raw = ownConfig.raw;
@@ -1754,7 +1755,7 @@ namespace ts {
// It should be removed in future releases - use typeAcquisition instead.
const typeAcquisition = convertTypeAcquisitionFromJsonWorker(json.typeAcquisition || json.typingOptions, basePath, errors, configFileName);
json.compileOnSave = convertCompileOnSaveOptionFromJson(json, basePath, errors);
let extendedConfigPath: string;
let extendedConfigPath: string | undefined;
if (json.extends) {
if (!isString(json.extends)) {
@@ -1776,8 +1777,8 @@ namespace ts {
errors: Push<Diagnostic>
): ParsedTsconfig {
const options = getDefaultCompilerOptions(configFileName);
let typeAcquisition: TypeAcquisition, typingOptionstypeAcquisition: TypeAcquisition;
let extendedConfigPath: string;
let typeAcquisition: TypeAcquisition | undefined, typingOptionstypeAcquisition: TypeAcquisition | undefined;
let extendedConfigPath: string | undefined;
const optionsIterator: JsonConversionNotifier = {
onSetValidOptionKeyValueInParent(parentOption: string, option: CommandLineOption, value: CompilerOptionsValue) {
@@ -1879,7 +1880,7 @@ namespace ts {
const extendedConfig = parseConfig(/*json*/ undefined, extendedResult, host, extendedDirname,
getBaseFileName(extendedConfigPath), resolutionStack, errors);
if (sourceFile) {
sourceFile.extendedSourceFiles.push(...extendedResult.extendedSourceFiles);
sourceFile.extendedSourceFiles!.push(...extendedResult.extendedSourceFiles!);
}
if (isSuccessfulParsedTsconfig(extendedConfig)) {
@@ -1903,13 +1904,10 @@ namespace ts {
function convertCompileOnSaveOptionFromJson(jsonOption: any, basePath: string, errors: Push<Diagnostic>): boolean {
if (!hasProperty(jsonOption, compileOnSaveCommandLineOption.name)) {
return undefined;
return false;
}
const result = convertJsonOption(compileOnSaveCommandLineOption, jsonOption.compileOnSave, basePath, errors);
if (typeof result === "boolean" && result) {
return result;
}
return false;
return typeof result === "boolean" && result;
}
export function convertCompilerOptionsFromJson(jsonOptions: any, basePath: string, configFileName?: string): { options: CompilerOptions, errors: Diagnostic[] } {
@@ -1943,7 +1941,7 @@ namespace ts {
}
function getDefaultTypeAcquisition(configFileName?: string): TypeAcquisition {
return { enable: configFileName && getBaseFileName(configFileName) === "jsconfig.json", include: [], exclude: [] };
return { enable: !!configFileName && getBaseFileName(configFileName) === "jsconfig.json", include: [], exclude: [] };
}
function convertTypeAcquisitionFromJsonWorker(jsonOptions: any,
@@ -2106,18 +2104,18 @@ namespace ts {
* @param errors An array for diagnostic reporting.
*/
function matchFileNames(
filesSpecs: ReadonlyArray<string>,
includeSpecs: ReadonlyArray<string>,
excludeSpecs: ReadonlyArray<string>,
filesSpecs: ReadonlyArray<string> | undefined,
includeSpecs: ReadonlyArray<string> | undefined,
excludeSpecs: ReadonlyArray<string> | undefined,
basePath: string,
options: CompilerOptions,
host: ParseConfigHost,
errors: Push<Diagnostic>,
extraFileExtensions: ReadonlyArray<FileExtensionInfo>,
jsonSourceFile: TsConfigSourceFile
jsonSourceFile: TsConfigSourceFile | undefined
): ExpandResult {
basePath = normalizePath(basePath);
let validatedIncludeSpecs: ReadonlyArray<string>, validatedExcludeSpecs: ReadonlyArray<string>;
let validatedIncludeSpecs: ReadonlyArray<string> | undefined, validatedExcludeSpecs: ReadonlyArray<string> | undefined;
// The exclude spec list is converted into a regular expression, which allows us to quickly
// test whether a file or directory should be excluded before recursively traversing the
@@ -2223,7 +2221,7 @@ namespace ts {
};
}
function validateSpecs(specs: ReadonlyArray<string>, errors: Push<Diagnostic>, allowTrailingRecursion: boolean, jsonSourceFile: TsConfigSourceFile, specKey: string): ReadonlyArray<string> {
function validateSpecs(specs: ReadonlyArray<string>, errors: Push<Diagnostic>, allowTrailingRecursion: boolean, jsonSourceFile: TsConfigSourceFile | undefined, specKey: string): ReadonlyArray<string> {
return specs.filter(spec => {
const diag = specToDiagnostic(spec, allowTrailingRecursion);
if (diag !== undefined) {
@@ -2235,7 +2233,7 @@ namespace ts {
function createDiagnostic(message: DiagnosticMessage, spec: string): Diagnostic {
const element = getTsConfigPropArrayElementValue(jsonSourceFile, specKey, spec);
return element ?
createDiagnosticForNodeInSourceFile(jsonSourceFile, element, message, spec) :
createDiagnosticForNodeInSourceFile(jsonSourceFile!, element, message, spec) :
createCompilerDiagnostic(message, spec);
}
}
@@ -2252,7 +2250,7 @@ namespace ts {
/**
* Gets directories in a set of include patterns that should be watched for changes.
*/
function getWildcardDirectories(include: ReadonlyArray<string>, exclude: ReadonlyArray<string>, path: string, useCaseSensitiveFileNames: boolean): MapLike<WatchDirectoryFlags> {
function getWildcardDirectories(include: ReadonlyArray<string> | undefined, exclude: ReadonlyArray<string> | undefined, path: string, useCaseSensitiveFileNames: boolean): MapLike<WatchDirectoryFlags> {
// We watch a directory recursively if it contains a wildcard anywhere in a directory segment
// of the pattern:
//
@@ -2394,7 +2392,7 @@ namespace ts {
if (optionEnumValue === value) {
return optionStringValue;
}
});
})!; // TODO: GH#18217
}
}
}
+14 -14
View File
@@ -3,8 +3,8 @@ namespace ts {
export interface CommentWriter {
reset(): void;
setSourceFile(sourceFile: SourceFile): void;
setWriter(writer: EmitTextWriter): void;
emitNodeWithComments(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void;
setWriter(writer: EmitTextWriter | undefined): void;
emitNodeWithComments(hint: EmitHint, node: Node | undefined, emitCallback: (hint: EmitHint, node: Node) => void): void;
emitBodyWithDetachedComments(node: Node, detachedRange: TextRange, emitCallback: (node: Node) => void): void;
emitTrailingCommentsOfPosition(pos: number, prefixSpace?: boolean): void;
emitLeadingCommentsOfPosition(pos: number): void;
@@ -20,9 +20,9 @@ namespace ts {
let currentSourceFile: SourceFile;
let currentText: string;
let currentLineMap: ReadonlyArray<number>;
let detachedCommentsInfo: { nodePos: number, detachedCommentEndPos: number}[];
let detachedCommentsInfo: { nodePos: number, detachedCommentEndPos: number}[] | undefined;
let hasWrittenComment = false;
let disabled: boolean = printerOptions.removeComments;
let disabled: boolean = !!printerOptions.removeComments;
return {
reset,
@@ -44,7 +44,7 @@ namespace ts {
hasWrittenComment = false;
const emitNode = node.emitNode;
const emitFlags = emitNode && emitNode.flags;
const emitFlags = emitNode && emitNode.flags || 0;
const { pos, end } = emitNode && emitNode.commentRange || node;
if ((pos < 0 && end < 0) || (pos === end)) {
// Both pos and end are synthesized, so just emit the node without comments.
@@ -114,7 +114,7 @@ namespace ts {
}
}
function emitNodeWithSynthesizedComments(hint: EmitHint, node: Node, emitNode: EmitNode, emitFlags: EmitFlags, emitCallback: (hint: EmitHint, node: Node) => void) {
function emitNodeWithSynthesizedComments(hint: EmitHint, node: Node, emitNode: EmitNode | undefined, emitFlags: EmitFlags, emitCallback: (hint: EmitHint, node: Node) => void) {
const leadingComments = emitNode && emitNode.leadingComments;
if (some(leadingComments)) {
if (extendedDiagnostics) {
@@ -170,7 +170,7 @@ namespace ts {
function writeSynthesizedComment(comment: SynthesizedComment) {
const text = formatSynthesizedComment(comment);
const lineMap = comment.kind === SyntaxKind.MultiLineCommentTrivia ? computeLineStarts(text) : undefined;
writeCommentRange(text, lineMap, writer, 0, text.length, newLine);
writeCommentRange(text, lineMap!, writer, 0, text.length, newLine);
}
function formatSynthesizedComment(comment: SynthesizedComment) {
@@ -364,9 +364,9 @@ namespace ts {
}
function reset() {
currentSourceFile = undefined;
currentText = undefined;
currentLineMap = undefined;
currentSourceFile = undefined!;
currentText = undefined!;
currentLineMap = undefined!;
detachedCommentsInfo = undefined;
}
@@ -382,14 +382,14 @@ namespace ts {
}
function hasDetachedComments(pos: number) {
return detachedCommentsInfo !== undefined && lastOrUndefined(detachedCommentsInfo).nodePos === pos;
return detachedCommentsInfo !== undefined && last(detachedCommentsInfo).nodePos === pos;
}
function forEachLeadingCommentWithoutDetachedComments(cb: (commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean, rangePos: number) => void) {
// get the leading comments from detachedPos
const pos = lastOrUndefined(detachedCommentsInfo).detachedCommentEndPos;
if (detachedCommentsInfo.length - 1) {
detachedCommentsInfo.pop();
const pos = last(detachedCommentsInfo!).detachedCommentEndPos;
if (detachedCommentsInfo!.length - 1) {
detachedCommentsInfo!.pop();
}
else {
detachedCommentsInfo = undefined;
+124 -97
View File
@@ -59,7 +59,7 @@ namespace ts {
return result;
}
export function createMapFromTemplate<T>(template?: MapLike<T>): Map<T> {
export function createMapFromTemplate<T>(template: MapLike<T>): Map<T> {
const map: Map<T> = new MapCtr<T>();
// Copies keys/values from template. Note that for..in will not throw if
@@ -107,7 +107,7 @@ namespace ts {
private data = createDictionaryObject<T>();
public size = 0;
get(key: string): T {
get(key: string): T | undefined {
return this.data[key];
}
@@ -138,15 +138,15 @@ namespace ts {
this.size = 0;
}
keys() {
keys(): Iterator<string> {
return new MapIterator(this.data, (_data, key) => key);
}
values() {
values(): Iterator<T> {
return new MapIterator(this.data, (data, key) => data[key]);
}
entries() {
entries(): Iterator<[string, T]> {
return new MapIterator(this.data, (data, key) => [key, data[key]] as [string, T]);
}
@@ -158,14 +158,14 @@ namespace ts {
};
}
export function toPath(fileName: string, basePath: string, getCanonicalFileName: (path: string) => string): Path {
export function toPath(fileName: string, basePath: string | undefined, getCanonicalFileName: (path: string) => string): Path {
const nonCanonicalizedPath = isRootedDiskPath(fileName)
? normalizePath(fileName)
: getNormalizedAbsolutePath(fileName, basePath);
return <Path>getCanonicalFileName(nonCanonicalizedPath);
}
export function length(array: ReadonlyArray<any>) {
export function length(array: ReadonlyArray<any> | undefined): number {
return array ? array.length : 0;
}
@@ -220,9 +220,9 @@ namespace ts {
* If no such value is found, it applies the callback until the parent pointer is undefined or the callback returns "quit"
* At that point findAncestor returns undefined.
*/
export function findAncestor<T extends Node>(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<T extends Node>(node: Node | undefined, callback: (element: Node) => element is T): T | undefined;
export function findAncestor(node: Node | undefined, callback: (element: Node) => boolean | "quit"): Node | undefined;
export function findAncestor(node: Node, callback: (element: Node) => boolean | "quit"): Node | undefined {
while (node) {
const result = callback(node);
if (result === "quit") {
@@ -340,10 +340,10 @@ namespace ts {
return result;
}
}
Debug.fail();
return Debug.fail();
}
export function contains<T>(array: ReadonlyArray<T>, value: T, equalityComparer: EqualityComparer<T> = equateValues): boolean {
export function contains<T>(array: ReadonlyArray<T> | undefined, value: T, equalityComparer: EqualityComparer<T> = equateValues): boolean {
if (array) {
for (const v of array) {
if (equalityComparer(v, value)) {
@@ -388,7 +388,11 @@ namespace ts {
export function filter<T>(array: T[], f: (x: T) => boolean): T[];
export function filter<T, U extends T>(array: ReadonlyArray<T>, f: (x: T) => x is U): ReadonlyArray<U>;
export function filter<T, U extends T>(array: ReadonlyArray<T>, f: (x: T) => boolean): ReadonlyArray<T>;
export function filter<T>(array: T[], f: (x: T) => boolean): T[] {
export function filter<T, U extends T>(array: T[] | undefined, f: (x: T) => x is U): U[] | undefined;
export function filter<T>(array: T[] | undefined, f: (x: T) => boolean): T[] | undefined;
export function filter<T, U extends T>(array: ReadonlyArray<T> | undefined, f: (x: T) => x is U): ReadonlyArray<U> | undefined;
export function filter<T, U extends T>(array: ReadonlyArray<T> | undefined, f: (x: T) => boolean): ReadonlyArray<T> | undefined;
export function filter<T>(array: ReadonlyArray<T> | undefined, f: (x: T) => boolean): ReadonlyArray<T> | undefined {
if (array) {
const len = array.length;
let i = 0;
@@ -424,8 +428,10 @@ namespace ts {
array.length = 0;
}
export function map<T, U>(array: ReadonlyArray<T>, f: (x: T, i: number) => U): U[] {
let result: U[];
export function map<T, U>(array: ReadonlyArray<T>, f: (x: T, i: number) => U): U[];
export function map<T, U>(array: ReadonlyArray<T> | undefined, f: (x: T, i: number) => U): U[] | undefined;
export function map<T, U>(array: ReadonlyArray<T> | undefined, f: (x: T, i: number) => U): U[] | undefined {
let result: U[] | undefined;
if (array) {
result = [];
for (let i = 0; i < array.length; i++) {
@@ -448,7 +454,9 @@ namespace ts {
// Maps from T to T and avoids allocation if all elements map to themselves
export function sameMap<T>(array: T[], f: (x: T, i: number) => T): T[];
export function sameMap<T>(array: ReadonlyArray<T>, f: (x: T, i: number) => T): ReadonlyArray<T>;
export function sameMap<T>(array: T[], f: (x: T, i: number) => T): T[] {
export function sameMap<T>(array: T[] | undefined, f: (x: T, i: number) => T): T[] | undefined;
export function sameMap<T>(array: ReadonlyArray<T> | undefined, f: (x: T, i: number) => T): ReadonlyArray<T> | undefined;
export function sameMap<T>(array: ReadonlyArray<T> | undefined, f: (x: T, i: number) => T): ReadonlyArray<T> | undefined {
if (array) {
for (let i = 0; i < array.length; i++) {
const item = array[i];
@@ -471,8 +479,10 @@ namespace ts {
*
* @param array The array to flatten.
*/
export function flatten<T>(array: ReadonlyArray<T | ReadonlyArray<T>>): T[] {
let result: T[];
export function flatten<T>(array: ReadonlyArray<T | ReadonlyArray<T> | undefined>): T[];
export function flatten<T>(array: ReadonlyArray<T | ReadonlyArray<T> | undefined> | undefined): T[] | undefined;
export function flatten<T>(array: ReadonlyArray<T | ReadonlyArray<T> | undefined> | undefined): T[] | undefined {
let result: T[] | undefined;
if (array) {
result = [];
for (const v of array) {
@@ -496,8 +506,10 @@ namespace ts {
* @param array The array to map.
* @param mapfn The callback used to map the result into one or more values.
*/
export function flatMap<T, U>(array: ReadonlyArray<T>, mapfn: (x: T, i: number) => U | ReadonlyArray<U> | undefined): U[];
export function flatMap<T, U>(array: ReadonlyArray<T> | undefined, mapfn: (x: T, i: number) => U | ReadonlyArray<U> | undefined): U[] | undefined;
export function flatMap<T, U>(array: ReadonlyArray<T> | undefined, mapfn: (x: T, i: number) => U | ReadonlyArray<U> | undefined): U[] | undefined {
let result: U[];
let result: U[] | undefined;
if (array) {
result = [];
for (let i = 0; i < array.length; i++) {
@@ -553,7 +565,7 @@ namespace ts {
export function sameFlatMap<T>(array: T[], mapfn: (x: T, i: number) => T | ReadonlyArray<T>): T[];
export function sameFlatMap<T>(array: ReadonlyArray<T>, mapfn: (x: T, i: number) => T | ReadonlyArray<T>): ReadonlyArray<T>;
export function sameFlatMap<T>(array: T[], mapfn: (x: T, i: number) => T | T[]): T[] {
let result: T[];
let result: T[] | undefined;
if (array) {
for (let i = 0; i < array.length; i++) {
const item = array[i];
@@ -636,13 +648,15 @@ namespace ts {
* @param keyfn A callback used to select the key for an element.
* @param mapfn A callback used to map a contiguous chunk of values to a single value.
*/
export function spanMap<T, K, U>(array: ReadonlyArray<T>, keyfn: (x: T, i: number) => K, mapfn: (chunk: T[], key: K, start: number, end: number) => U): U[] {
let result: U[];
export function spanMap<T, K, U>(array: ReadonlyArray<T>, keyfn: (x: T, i: number) => K, mapfn: (chunk: T[], key: K, start: number, end: number) => U): U[];
export function spanMap<T, K, U>(array: ReadonlyArray<T> | undefined, keyfn: (x: T, i: number) => K, mapfn: (chunk: T[], key: K, start: number, end: number) => U): U[] | undefined;
export function spanMap<T, K, U>(array: ReadonlyArray<T> | undefined, keyfn: (x: T, i: number) => K, mapfn: (chunk: T[], key: K, start: number, end: number) => U): U[] | undefined {
let result: U[] | undefined;
if (array) {
result = [];
const len = array.length;
let previousKey: K;
let key: K;
let previousKey: K | undefined;
let key: K | undefined;
let start = 0;
let pos = 0;
while (start < len) {
@@ -660,7 +674,7 @@ namespace ts {
}
if (start < pos) {
const v = mapfn(array.slice(start, pos), previousKey, start, pos);
const v = mapfn(array.slice(start, pos), previousKey!, start, pos);
if (v) {
result.push(v);
}
@@ -676,7 +690,9 @@ namespace ts {
return result;
}
export function mapEntries<T, U>(map: ReadonlyMap<T>, f: (key: string, value: T) => [string, U]): Map<U> {
export function mapEntries<T, U>(map: ReadonlyMap<T>, f: (key: string, value: T) => [string, U]): Map<U>;
export function mapEntries<T, U>(map: ReadonlyMap<T> | undefined, f: (key: string, value: T) => [string, U]): Map<U> | undefined;
export function mapEntries<T, U>(map: ReadonlyMap<T> | undefined, f: (key: string, value: T) => [string, U]): Map<U> | undefined {
if (!map) {
return undefined;
}
@@ -688,8 +704,9 @@ namespace ts {
});
return result;
}
export function some<T>(array: ReadonlyArray<T>, predicate?: (value: T) => boolean): boolean {
export function some<T>(array: ReadonlyArray<T> | undefined): array is ReadonlyArray<T>;
export function some<T>(array: ReadonlyArray<T> | undefined, predicate: (value: T) => boolean): boolean;
export function some<T>(array: ReadonlyArray<T> | undefined, predicate?: (value: T) => boolean): boolean {
if (array) {
if (predicate) {
for (const v of array) {
@@ -724,6 +741,8 @@ namespace ts {
export function concatenate<T>(array1: T[], array2: T[]): T[];
export function concatenate<T>(array1: ReadonlyArray<T>, array2: ReadonlyArray<T>): ReadonlyArray<T>;
export function concatenate<T>(array1: T[] | undefined, array2: T[] | undefined): T[];
export function concatenate<T>(array1: ReadonlyArray<T> | undefined, array2: ReadonlyArray<T> | undefined): ReadonlyArray<T>;
export function concatenate<T>(array1: T[], array2: T[]): T[] {
if (!some(array2)) return array1;
if (!some(array1)) return array2;
@@ -766,7 +785,9 @@ namespace ts {
* @param comparer An optional `Comparer` used to sort entries before comparison, though the
* result will remain in the original order in `array`.
*/
export function deduplicate<T>(array: ReadonlyArray<T>, equalityComparer: EqualityComparer<T>, comparer?: Comparer<T>): T[] {
export function deduplicate<T>(array: ReadonlyArray<T>, equalityComparer?: EqualityComparer<T>, comparer?: Comparer<T>): T[];
export function deduplicate<T>(array: ReadonlyArray<T> | undefined, equalityComparer?: EqualityComparer<T>, comparer?: Comparer<T>): T[] | undefined;
export function deduplicate<T>(array: ReadonlyArray<T> | undefined, equalityComparer: EqualityComparer<T>, comparer?: Comparer<T>): T[] | undefined {
return !array ? undefined :
array.length === 0 ? [] :
array.length === 1 ? array.slice() :
@@ -777,7 +798,9 @@ namespace ts {
/**
* Deduplicates an array that has already been sorted.
*/
function deduplicateSorted<T>(array: ReadonlyArray<T>, comparer: EqualityComparer<T> | Comparer<T>) {
function deduplicateSorted<T>(array: ReadonlyArray<T>, comparer: EqualityComparer<T> | Comparer<T>): T[];
function deduplicateSorted<T>(array: ReadonlyArray<T> | undefined, comparer: EqualityComparer<T> | Comparer<T>): T[] | undefined;
function deduplicateSorted<T>(array: ReadonlyArray<T> | undefined, comparer: EqualityComparer<T> | Comparer<T>): T[] | undefined {
if (!array) return undefined;
if (array.length === 0) return [];
@@ -820,7 +843,7 @@ namespace ts {
return deduplicateSorted(sort(array, comparer), equalityComparer || comparer);
}
export function arrayIsEqualTo<T>(array1: ReadonlyArray<T>, array2: ReadonlyArray<T>, equalityComparer: (a: T, b: T) => boolean = equateValues): boolean {
export function arrayIsEqualTo<T>(array1: ReadonlyArray<T> | undefined, array2: ReadonlyArray<T> | undefined, equalityComparer: (a: T, b: T) => boolean = equateValues): boolean {
if (!array1 || !array2) {
return array1 === array2;
}
@@ -863,7 +886,7 @@ namespace ts {
export function compact<T>(array: T[]): T[];
export function compact<T>(array: ReadonlyArray<T>): ReadonlyArray<T>;
export function compact<T>(array: T[]): T[] {
let result: T[];
let result: T[] | undefined;
if (array) {
for (let i = 0; i < array.length; i++) {
const v = array[i];
@@ -939,6 +962,9 @@ namespace ts {
* @param value The value to append to the array. If `value` is `undefined`, nothing is
* appended.
*/
export function append<T>(to: T[], value: T | undefined): T[];
export function append<T>(to: T[] | undefined, value: T): T[];
export function append<T>(to: T[] | undefined, value: T | undefined): T[] | undefined;
export function append<T>(to: T[] | undefined, value: T | undefined): T[] | undefined {
if (value === undefined) return to;
if (to === undefined) return [value];
@@ -964,6 +990,8 @@ namespace ts {
* @param start The offset in `from` at which to start copying values.
* @param end The offset in `from` at which to stop copying values (non-inclusive).
*/
export function addRange<T>(to: T[], from: ReadonlyArray<T> | undefined, start?: number, end?: number): T[];
export function addRange<T>(to: T[] | undefined, from: ReadonlyArray<T> | undefined, start?: number, end?: number): T[] | undefined;
export function addRange<T>(to: T[] | undefined, from: ReadonlyArray<T> | undefined, start?: number, end?: number): T[] | undefined {
if (from === undefined || from.length === 0) return to;
if (to === undefined) return from.slice(start, end);
@@ -1026,7 +1054,7 @@ namespace ts {
/**
* Returns a new sorted array.
*/
export function sort<T>(array: ReadonlyArray<T>, comparer: Comparer<T>) {
export function sort<T>(array: ReadonlyArray<T>, comparer: Comparer<T>): T[] {
return array.slice().sort(comparer);
}
@@ -1120,7 +1148,7 @@ namespace ts {
/**
* Returns the only element of an array if it contains only one element, `undefined` otherwise.
*/
export function singleOrUndefined<T>(array: ReadonlyArray<T>): T | undefined {
export function singleOrUndefined<T>(array: ReadonlyArray<T> | undefined): T | undefined {
return array && array.length === 1
? array[0]
: undefined;
@@ -1132,7 +1160,9 @@ namespace ts {
*/
export function singleOrMany<T>(array: T[]): T | T[];
export function singleOrMany<T>(array: ReadonlyArray<T>): T | ReadonlyArray<T>;
export function singleOrMany<T>(array: T[]): T | T[] {
export function singleOrMany<T>(array: T[] | undefined): T | T[] | undefined;
export function singleOrMany<T>(array: ReadonlyArray<T> | undefined): T | ReadonlyArray<T> | undefined;
export function singleOrMany<T>(array: ReadonlyArray<T> | undefined): T | ReadonlyArray<T> | undefined {
return array && array.length === 1
? array[0]
: array;
@@ -1181,9 +1211,9 @@ namespace ts {
return ~low;
}
export function reduceLeft<T, U>(array: ReadonlyArray<T>, f: (memo: U, value: T, i: number) => U, initial: U, start?: number, count?: number): U;
export function reduceLeft<T>(array: ReadonlyArray<T>, f: (memo: T, value: T, i: number) => T): T;
export function reduceLeft<T>(array: T[], f: (memo: T, value: T, i: number) => T, initial?: T, start?: number, count?: number): T {
export function reduceLeft<T, U>(array: ReadonlyArray<T> | undefined, f: (memo: U, value: T, i: number) => U, initial: U, start?: number, count?: number): U;
export function reduceLeft<T>(array: ReadonlyArray<T>, f: (memo: T, value: T, i: number) => T): T | undefined;
export function reduceLeft<T>(array: T[], f: (memo: T, value: T, i: number) => T, initial?: T, start?: number, count?: number): T | undefined {
if (array && array.length > 0) {
const size = array.length;
if (size > 0) {
@@ -1195,7 +1225,7 @@ namespace ts {
pos++;
}
else {
result = initial;
result = initial!;
}
while (pos <= end) {
result = f(result, array[pos], pos);
@@ -1306,11 +1336,11 @@ namespace ts {
});
}
export function assign<T extends object>(t: T, ...args: T[]) {
export function assign<T extends object>(t: T, ...args: (T | undefined)[]) {
for (const arg of args) {
for (const p in arg) {
if (hasProperty(arg, p)) {
t[p] = arg[p];
for (const p in arg!) {
if (hasProperty(arg!, p)) {
t![p] = arg![p]; // TODO: GH#23368
}
}
}
@@ -1323,7 +1353,7 @@ namespace ts {
* @param left A map-like whose properties should be compared.
* @param right A map-like whose properties should be compared.
*/
export function equalOwnProperties<T>(left: MapLike<T>, right: MapLike<T>, equalityComparer: EqualityComparer<T> = equateValues) {
export function equalOwnProperties<T>(left: MapLike<T> | undefined, right: MapLike<T> | undefined, equalityComparer: EqualityComparer<T> = equateValues) {
if (left === right) return true;
if (!left || !right) return false;
for (const key in left) {
@@ -1503,10 +1533,10 @@ namespace ts {
if (value !== undefined && test(value)) return value;
if (value && typeof (value as any).kind === "number") {
Debug.fail(`Invalid cast. The supplied ${Debug.showSyntaxKind(value as any as Node)} did not pass the test '${Debug.getFunctionName(test)}'.`);
return Debug.fail(`Invalid cast. The supplied ${Debug.showSyntaxKind(value as any as Node)} did not pass the test '${Debug.getFunctionName(test)}'.`);
}
else {
Debug.fail(`Invalid cast. The supplied value did not pass the test '${Debug.getFunctionName(test)}'.`);
return Debug.fail(`Invalid cast. The supplied value did not pass the test '${Debug.getFunctionName(test)}'.`);
}
}
@@ -1535,7 +1565,7 @@ namespace ts {
return () => {
if (callback) {
value = callback();
callback = undefined;
callback = undefined!;
}
return value;
};
@@ -1607,19 +1637,17 @@ namespace ts {
}
}
export function formatStringFromArgs(text: string, args: ArrayLike<string>, baseIndex?: number): string {
baseIndex = baseIndex || 0;
return text.replace(/{(\d+)}/g, (_match, index?: string) => Debug.assertDefined(args[+index + baseIndex]));
export function formatStringFromArgs(text: string, args: ArrayLike<string>, baseIndex = 0): string {
return text.replace(/{(\d+)}/g, (_match, index: string) => Debug.assertDefined(args[+index + baseIndex]));
}
export let localizedDiagnosticMessages: MapLike<string>;
export let localizedDiagnosticMessages: MapLike<string> | undefined;
export function getLocaleSpecificMessage(message: DiagnosticMessage) {
return localizedDiagnosticMessages && localizedDiagnosticMessages[message.key] || message.message;
}
export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage, ...args: (string | number)[]): DiagnosticWithLocation;
export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage, ...args: (string | number | undefined)[]): DiagnosticWithLocation;
export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage): DiagnosticWithLocation {
Debug.assertGreaterThanOrEqual(start, 0);
Debug.assertGreaterThanOrEqual(length, 0);
@@ -1658,7 +1686,7 @@ namespace ts {
return text;
}
export function createCompilerDiagnostic(message: DiagnosticMessage, ...args: (string | number)[]): Diagnostic;
export function createCompilerDiagnostic(message: DiagnosticMessage, ...args: (string | number | undefined)[]): Diagnostic;
export function createCompilerDiagnostic(message: DiagnosticMessage): Diagnostic {
let text = getLocaleSpecificMessage(message);
@@ -1690,8 +1718,8 @@ namespace ts {
};
}
export function chainDiagnosticMessages(details: DiagnosticMessageChain, message: DiagnosticMessage, ...args: string[]): DiagnosticMessageChain;
export function chainDiagnosticMessages(details: DiagnosticMessageChain, message: DiagnosticMessage): DiagnosticMessageChain {
export function chainDiagnosticMessages(details: DiagnosticMessageChain | undefined, message: DiagnosticMessage, ...args: (string | undefined)[]): DiagnosticMessageChain;
export function chainDiagnosticMessages(details: DiagnosticMessageChain | undefined, message: DiagnosticMessage): DiagnosticMessageChain {
let text = getLocaleSpecificMessage(message);
if (arguments.length > 2) {
@@ -1746,9 +1774,9 @@ namespace ts {
return equateValues(a, b);
}
function compareComparableValues(a: string, b: string): Comparison;
function compareComparableValues(a: number, b: number): Comparison;
function compareComparableValues(a: string | number, b: string | number) {
function compareComparableValues(a: string | undefined, b: string | undefined): Comparison;
function compareComparableValues(a: number | undefined, b: number | undefined): Comparison;
function compareComparableValues(a: string | number | undefined, b: string | number | undefined) {
return a === b ? Comparison.EqualTo :
a === undefined ? Comparison.LessThan :
b === undefined ? Comparison.GreaterThan :
@@ -1760,7 +1788,7 @@ namespace ts {
* Compare two numeric values for their order relative to each other.
* To compare strings, use any of the `compareStrings` functions.
*/
export function compareValues(a: number, b: number) {
export function compareValues(a: number | undefined, b: number | undefined): Comparison {
return compareComparableValues(a, b);
}
@@ -1799,7 +1827,7 @@ namespace ts {
* Case-sensitive comparisons compare both strings one code-point at a time using the integer
* value of each code-point.
*/
export function compareStringsCaseSensitive(a: string, b: string) {
export function compareStringsCaseSensitive(a: string | undefined, b: string | undefined): Comparison {
return compareComparableValues(a, b);
}
@@ -1902,7 +1930,7 @@ namespace ts {
return uiLocale;
}
export function setUILocale(value: string) {
export function setUILocale(value: string | undefined) {
if (uiLocale !== value) {
uiLocale = value;
uiComparerCaseSensitive = undefined;
@@ -1924,14 +1952,14 @@ namespace ts {
return comparer(a, b);
}
export function compareProperties<T, K extends keyof T>(a: T, b: T, key: K, comparer: Comparer<T[K]>) {
export function compareProperties<T, K extends keyof T>(a: T | undefined, b: T | undefined, key: K, comparer: Comparer<T[K]>): Comparison {
return a === b ? Comparison.EqualTo :
a === undefined ? Comparison.LessThan :
b === undefined ? Comparison.GreaterThan :
comparer(a[key], b[key]);
}
function getDiagnosticFilePath(diagnostic: Diagnostic): string {
function getDiagnosticFilePath(diagnostic: Diagnostic): string | undefined {
return diagnostic.file ? diagnostic.file.path : undefined;
}
@@ -1949,7 +1977,9 @@ namespace ts {
return compareValues(a ? 1 : 0, b ? 1 : 0);
}
function compareMessageText(text1: string | DiagnosticMessageChain, text2: string | DiagnosticMessageChain): Comparison {
function compareMessageText(t1: string | DiagnosticMessageChain, t2: string | DiagnosticMessageChain): Comparison {
let text1: string | DiagnosticMessageChain | undefined = t1;
let text2: string | DiagnosticMessageChain | undefined = t2;
while (text1 && text2) {
// We still have both chains.
const string1 = isString(text1) ? text1 : text1.messageText;
@@ -2019,7 +2049,7 @@ namespace ts {
export type StrictOptionName = "noImplicitAny" | "noImplicitThis" | "strictNullChecks" | "strictFunctionTypes" | "strictPropertyInitialization" | "alwaysStrict";
export function getStrictOptionValue(compilerOptions: CompilerOptions, flag: StrictOptionName): boolean {
return compilerOptions[flag] === undefined ? compilerOptions.strict : compilerOptions[flag];
return compilerOptions[flag] === undefined ? !!compilerOptions.strict : !!compilerOptions[flag];
}
export function hasZeroOrOneAsteriskCharacter(str: string): boolean {
@@ -2298,11 +2328,11 @@ namespace ts {
* If the path is relative, the root component is `""`.
* If the path is absolute, the root component includes the first path separator (`/`).
*/
export function getNormalizedPathComponents(path: string, currentDirectory: string) {
export function getNormalizedPathComponents(path: string, currentDirectory: string | undefined) {
return reducePathComponents(getPathComponents(path, currentDirectory));
}
export function getNormalizedAbsolutePath(fileName: string, currentDirectory: string) {
export function getNormalizedAbsolutePath(fileName: string, currentDirectory: string | undefined) {
return getPathFromPathComponents(getNormalizedPathComponents(fileName, currentDirectory));
}
@@ -2429,7 +2459,7 @@ namespace ts {
/**
* Combines paths. If a path is absolute, it replaces any previous path.
*/
export function combinePaths(path: string, ...paths: string[]): string {
export function combinePaths(path: string, ...paths: (string | undefined)[]): string {
if (path) path = normalizeSlashes(path);
for (let relativePath of paths) {
if (!relativePath) continue;
@@ -2448,7 +2478,7 @@ namespace ts {
* Combines and resolves paths. If a path is absolute, it replaces any previous path. Any
* `.` and `..` path components are resolved.
*/
export function resolvePath(path: string, ...paths: string[]): string {
export function resolvePath(path: string, ...paths: (string | undefined)[]): string {
const combined = some(paths) ? combinePaths(path, ...paths) : normalizeSlashes(path);
const normalized = getPathFromPathComponents(reducePathComponents(getPathComponents(combined)));
return normalized && hasTrailingDirectorySeparator(combined) ? ensureTrailingDirectorySeparator(normalized) : normalized;
@@ -2657,7 +2687,7 @@ namespace ts {
exclude: excludeMatcher
};
export function getRegularExpressionForWildcard(specs: ReadonlyArray<string>, basePath: string, usage: "files" | "directories" | "exclude"): string | undefined {
export function getRegularExpressionForWildcard(specs: ReadonlyArray<string> | undefined, basePath: string, usage: "files" | "directories" | "exclude"): string | undefined {
const patterns = getRegularExpressionsForWildcards(specs, basePath, usage);
if (!patterns || !patterns.length) {
return undefined;
@@ -2669,7 +2699,7 @@ namespace ts {
return `^(${pattern})${terminator}`;
}
function getRegularExpressionsForWildcards(specs: ReadonlyArray<string>, basePath: string, usage: "files" | "directories" | "exclude"): string[] | undefined {
function getRegularExpressionsForWildcards(specs: ReadonlyArray<string> | undefined, basePath: string, usage: "files" | "directories" | "exclude"): string[] | undefined {
if (specs === undefined || specs.length === 0) {
return undefined;
}
@@ -2690,7 +2720,7 @@ namespace ts {
let subpattern = "";
let hasWrittenComponent = false;
const components = getNormalizedPathComponents(spec, basePath);
const lastComponent = lastOrUndefined(components);
const lastComponent = last(components);
if (usage !== "exclude" && lastComponent === "**") {
return undefined;
}
@@ -2773,15 +2803,15 @@ namespace ts {
export interface FileMatcherPatterns {
/** One pattern for each "include" spec. */
includeFilePatterns: ReadonlyArray<string>;
includeFilePatterns: ReadonlyArray<string> | 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<string>;
}
export function getFileMatcherPatterns(path: string, excludes: ReadonlyArray<string>, includes: ReadonlyArray<string>, useCaseSensitiveFileNames: boolean, currentDirectory: string): FileMatcherPatterns {
export function getFileMatcherPatterns(path: string, excludes: ReadonlyArray<string> | undefined, includes: ReadonlyArray<string> | undefined, useCaseSensitiveFileNames: boolean, currentDirectory: string): FileMatcherPatterns {
path = normalizePath(path);
currentDirectory = normalizePath(currentDirectory);
const absolutePath = combinePaths(currentDirectory, path);
@@ -2795,7 +2825,7 @@ namespace ts {
};
}
export function matchFiles(path: string, extensions: ReadonlyArray<string>, excludes: ReadonlyArray<string>, includes: ReadonlyArray<string>, useCaseSensitiveFileNames: boolean, currentDirectory: string, depth: number | undefined, getFileSystemEntries: (path: string) => FileSystemEntries): string[] {
export function matchFiles(path: string, extensions: ReadonlyArray<string> | undefined, excludes: ReadonlyArray<string> | undefined, includes: ReadonlyArray<string> | undefined, useCaseSensitiveFileNames: boolean, currentDirectory: string, depth: number | undefined, getFileSystemEntries: (path: string) => FileSystemEntries): string[] {
path = normalizePath(path);
currentDirectory = normalizePath(currentDirectory);
@@ -2819,7 +2849,7 @@ namespace ts {
function visitDirectory(path: string, absolutePath: string, depth: number | undefined) {
const { files, directories } = getFileSystemEntries(path);
for (const current of sort(files, compareStringsCaseSensitive)) {
for (const current of sort<string>(files, compareStringsCaseSensitive)) {
const name = combinePaths(path, current);
const absoluteName = combinePaths(absolutePath, current);
if (extensions && !fileExtensionIsOneOf(name, extensions)) continue;
@@ -2842,7 +2872,7 @@ namespace ts {
}
}
for (const current of sort(directories, compareStringsCaseSensitive)) {
for (const current of sort<string>(directories, compareStringsCaseSensitive)) {
const name = combinePaths(path, current);
const absoluteName = combinePaths(absolutePath, current);
if ((!includeDirectoryRegex || includeDirectoryRegex.test(absoluteName)) &&
@@ -2856,7 +2886,7 @@ namespace ts {
/**
* Computes the unique non-wildcard base paths amongst the provided include patterns.
*/
function getBasePaths(path: string, includes: ReadonlyArray<string>, useCaseSensitiveFileNames: boolean) {
function getBasePaths(path: string, includes: ReadonlyArray<string> | undefined, useCaseSensitiveFileNames: boolean): string[] {
// Storage for our results in the form of literal paths (e.g. the paths as written by the user).
const basePaths: string[] = [path];
@@ -2946,19 +2976,19 @@ namespace ts {
...mapDefined(extraFileExtensions, x => x.scriptKind === ScriptKind.Deferred || needJsExtensions && isJavaScriptLike(x.scriptKind) ? x.extension : undefined)
];
return deduplicate(extensions, equateStringsCaseSensitive, compareStringsCaseSensitive);
return deduplicate<string>(extensions, equateStringsCaseSensitive, compareStringsCaseSensitive);
}
function isJavaScriptLike(scriptKind: ScriptKind): boolean {
function isJavaScriptLike(scriptKind: ScriptKind | undefined): boolean {
return scriptKind === ScriptKind.JS || scriptKind === ScriptKind.JSX;
}
export function hasJavaScriptFileExtension(fileName: string) {
return forEach(supportedJavascriptExtensions, extension => fileExtensionIs(fileName, extension));
export function hasJavaScriptFileExtension(fileName: string): boolean {
return some(supportedJavascriptExtensions, extension => fileExtensionIs(fileName, extension));
}
export function hasTypeScriptFileExtension(fileName: string) {
return forEach(supportedTypeScriptExtensions, extension => fileExtensionIs(fileName, extension));
export function hasTypeScriptFileExtension(fileName: string): boolean {
return some(supportedTypeScriptExtensions, extension => fileExtensionIs(fileName, extension));
}
export function isSupportedSourceFileName(fileName: string, compilerOptions?: CompilerOptions, extraFileExtensions?: ReadonlyArray<FileExtensionInfo>) {
@@ -3079,8 +3109,8 @@ namespace ts {
function Symbol(this: Symbol, flags: SymbolFlags, name: __String) {
this.flags = flags;
this.escapedName = name;
this.declarations = undefined;
this.valueDeclaration = undefined;
this.declarations = undefined!;
this.valueDeclaration = undefined!;
this.id = undefined;
this.mergeId = undefined;
this.parent = undefined;
@@ -3103,7 +3133,7 @@ namespace ts {
this.flags = NodeFlags.None;
this.modifierFlagsCache = ModifierFlags.None;
this.transformFlags = TransformFlags.None;
this.parent = undefined;
this.parent = undefined!;
this.original = undefined;
}
@@ -3189,7 +3219,7 @@ namespace ts {
}
export function assertDefined<T>(value: T | null | undefined, message?: string): T {
assert(value !== undefined && value !== null, message);
if (value === undefined || value === null) return fail(message);
return value;
}
@@ -3224,7 +3254,7 @@ namespace ts {
}
function showFlags(flags: number, flagsEnum: { [flag: number]: string }): string {
const out = [];
const out: string[] = [];
for (let pow = 0; pow <= 30; pow++) {
const n = 1 << pow;
if (flags & n) {
@@ -3375,10 +3405,7 @@ namespace ts {
*/
export function extensionFromPath(path: string): Extension {
const ext = tryGetExtensionFromPath(path);
if (ext !== undefined) {
return ext;
}
Debug.fail(`File ${path} has unknown extension.`);
return ext !== undefined ? ext : Debug.fail(`File ${path} has unknown extension.`);
}
export function isAnySupportedFileExtension(path: string): boolean {
+63 -61
View File
@@ -15,7 +15,7 @@ namespace ts {
export function forEachEmittedFile<T>(
host: EmitHost, action: (emitFileNames: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle) => T,
sourceFilesOrTargetSourceFile?: ReadonlyArray<SourceFile> | SourceFile,
emitOnlyDtsFiles?: boolean) {
emitOnlyDtsFiles = false) {
const sourceFiles = isArray(sourceFilesOrTargetSourceFile) ? sourceFilesOrTargetSourceFile : getSourceFilesToEmit(host, sourceFilesOrTargetSourceFile);
const options = host.getCompilerOptions();
if (options.outFile || options.out) {
@@ -38,14 +38,14 @@ namespace ts {
}
/*@internal*/
export function getOutputPathsFor(sourceFile: SourceFile | Bundle, host: EmitHost, forceDtsPaths: boolean) {
export function getOutputPathsFor(sourceFile: SourceFile | Bundle, host: EmitHost, forceDtsPaths: boolean): EmitFileNames {
const options = host.getCompilerOptions();
if (sourceFile.kind === SyntaxKind.Bundle) {
const jsFilePath = options.outFile || options.out;
const jsFilePath = options.outFile || options.out!;
const sourceMapFilePath = getSourceMapFilePath(jsFilePath, options);
const declarationFilePath = (forceDtsPaths || options.declaration) ? removeFileExtension(jsFilePath) + Extension.Dts : undefined;
const declarationMapPath = getAreDeclarationMapsEnabled(options) ? declarationFilePath + ".map" : undefined;
const bundleInfoPath = options.references && jsFilePath && (removeFileExtension(jsFilePath) + infoExtension);
const bundleInfoPath = options.references && jsFilePath ? (removeFileExtension(jsFilePath) + infoExtension) : undefined;
return { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, bundleInfoPath };
}
else {
@@ -97,8 +97,8 @@ namespace ts {
// targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature
export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile, emitOnlyDtsFiles?: boolean, transformers?: TransformerFactory<Bundle | SourceFile>[], declarationTransformers?: TransformerFactory<Bundle | SourceFile>[]): EmitResult {
const compilerOptions = host.getCompilerOptions();
const sourceMapDataList: SourceMapData[] = (compilerOptions.sourceMap || compilerOptions.inlineSourceMap || getAreDeclarationMapsEnabled(compilerOptions)) ? [] : undefined;
const emittedFilesList: string[] = compilerOptions.listEmittedFiles ? [] : undefined;
const sourceMapDataList: SourceMapData[] | undefined = (compilerOptions.sourceMap || compilerOptions.inlineSourceMap || getAreDeclarationMapsEnabled(compilerOptions)) ? [] : undefined;
const emittedFilesList: string[] | undefined = compilerOptions.listEmittedFiles ? [] : undefined;
const emitterDiagnostics = createDiagnosticCollection();
const newLine = host.getNewLine();
const writer = createTextWriter(newLine);
@@ -124,7 +124,7 @@ namespace ts {
emitSkipped,
diagnostics: emitterDiagnostics.getDiagnostics(),
emittedFiles: emittedFilesList,
sourceMaps: sourceMapDataList
sourceMaps: sourceMapDataList,
};
function emitSourceFileOrBundle({ jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, bundleInfoPath }: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle) {
@@ -147,7 +147,7 @@ namespace ts {
}
}
function emitJsFileOrBundle(sourceFileOrBundle: SourceFile | Bundle, jsFilePath: string, sourceMapFilePath: string, bundleInfoPath: string | undefined) {
function emitJsFileOrBundle(sourceFileOrBundle: SourceFile | Bundle, jsFilePath: string, sourceMapFilePath: string | undefined, bundleInfoPath: string | undefined) {
// Make sure not to write js file and source map file if any of them cannot be written
if (host.isEmitBlocked(jsFilePath) || compilerOptions.noEmit || compilerOptions.emitDeclarationOnly) {
emitSkipped = true;
@@ -157,7 +157,7 @@ namespace ts {
return;
}
// Transform the source files
const transform = transformNodes(resolver, host, compilerOptions, [sourceFileOrBundle], transformers, /*allowDtsFiles*/ false);
const transform = transformNodes(resolver, host, compilerOptions, [sourceFileOrBundle], transformers!, /*allowDtsFiles*/ false);
// Create a printer to print the nodes
const printer = createPrinter({ ...compilerOptions, noEmitHelpers: compilerOptions.noEmitHelpers } as PrinterOptions, {
@@ -194,7 +194,7 @@ namespace ts {
const inputListOrBundle = (compilerOptions.outFile || compilerOptions.out) ? [createBundle(nonJsFiles, !isSourceFile(sourceFileOrBundle) ? sourceFileOrBundle.prepends : undefined)] : nonJsFiles;
const declarationTransform = transformNodes(resolver, host, compilerOptions, inputListOrBundle, concatenate([transformDeclarations], declarationTransformers), /*allowDtsFiles*/ false);
if (length(declarationTransform.diagnostics)) {
for (const diagnostic of declarationTransform.diagnostics) {
for (const diagnostic of declarationTransform.diagnostics!) {
emitterDiagnostics.add(diagnostic);
}
}
@@ -224,14 +224,14 @@ namespace ts {
function printSourceFileOrBundle(jsFilePath: string, sourceMapFilePath: string | undefined, sourceFileOrBundle: SourceFile | Bundle, bundleInfoPath: string | undefined, printer: Printer, mapRecorder: SourceMapWriter) {
const bundle = sourceFileOrBundle.kind === SyntaxKind.Bundle ? sourceFileOrBundle : undefined;
const sourceFile = sourceFileOrBundle.kind === SyntaxKind.SourceFile ? sourceFileOrBundle : undefined;
const sourceFiles = bundle ? bundle.sourceFiles : [sourceFile];
const sourceFiles = bundle ? bundle.sourceFiles : [sourceFile!];
mapRecorder.initialize(jsFilePath, sourceMapFilePath || "", sourceFileOrBundle, sourceMapDataList);
if (bundle) {
printer.writeBundle(bundle, writer, bundleInfo);
}
else {
printer.writeFile(sourceFile, writer);
printer.writeFile(sourceFile!, writer);
}
writer.writeLine();
@@ -247,7 +247,7 @@ namespace ts {
}
// Write the output file
writeFile(host, emitterDiagnostics, jsFilePath, writer.getText(), compilerOptions.emitBOM, sourceFiles);
writeFile(host, emitterDiagnostics, jsFilePath, writer.getText(), !!compilerOptions.emitBOM, sourceFiles);
// Write bundled offset information if applicable
if (bundleInfoPath) {
@@ -302,7 +302,7 @@ namespace ts {
emitLeadingCommentsOfPosition,
} = comments;
let currentSourceFile: SourceFile | undefined;
let currentSourceFile!: SourceFile;
let nodeIdToGeneratedName: string[]; // Map of generated names for specific nodes.
let autoGeneratedIdToGeneratedName: string[]; // Map of generated names for temp and loop variables.
let generatedNames: Map<true>; // Set of names generated by the NameGenerator.
@@ -478,8 +478,8 @@ namespace ts {
}
function setWriter(output: EmitTextWriter | undefined) {
writer = output;
comments.setWriter(output);
writer = output!; // TODO: GH#18217
comments.setWriter(output!);
}
function reset() {
@@ -544,8 +544,7 @@ namespace ts {
}
function pipelineEmitWithNotification(hint: EmitHint, node: Node) {
Debug.assertDefined(onEmitNode);
onEmitNode(hint, node, getNextPipelinePhase(PipelinePhase.Notification, hint));
Debug.assertDefined(onEmitNode)(hint, node, getNextPipelinePhase(PipelinePhase.Notification, hint));
}
function pipelineEmitWithComments(hint: EmitHint, node: Node) {
@@ -560,9 +559,8 @@ namespace ts {
}
function pipelineEmitWithSourceMap(hint: EmitHint, node: Node) {
Debug.assertDefined(onEmitSourceMapOfNode);
Debug.assert(hint !== EmitHint.SourceFile && hint !== EmitHint.IdentifierName);
onEmitSourceMapOfNode(hint, node, pipelineEmitWithHint);
Debug.assertDefined(onEmitSourceMapOfNode)(hint, node, pipelineEmitWithHint);
}
function pipelineEmitWithHint(hint: EmitHint, node: Node): void {
@@ -1503,7 +1501,7 @@ namespace ts {
// check if numeric literal is a decimal literal that was originally written with a dot
const text = getLiteralTextOfNode(<LiteralExpression>expression);
return !expression.numericLiteralFlags
&& !stringContains(text, tokenToString(SyntaxKind.DotToken));
&& !stringContains(text, tokenToString(SyntaxKind.DotToken)!);
}
else if (isPropertyAccessExpression(expression) || isElementAccessExpression(expression)) {
// check if constant enum value is integer
@@ -1841,7 +1839,7 @@ namespace ts {
emitEmbeddedStatement(node, node.statement);
}
function emitForBinding(node: VariableDeclarationList | Expression) {
function emitForBinding(node: VariableDeclarationList | Expression | undefined) {
if (node !== undefined) {
if (node.kind === SyntaxKind.VariableDeclarationList) {
emit(node);
@@ -1973,7 +1971,7 @@ namespace ts {
writeKeyword("function");
emit(node.asteriskToken);
writeSpace();
emitIdentifierName(node.name);
emitIdentifierName(node.name!); // TODO: GH#18217
emitSignatureAndBody(node, emitSignatureHead);
}
@@ -2052,7 +2050,7 @@ namespace ts {
return false;
}
let previousStatement: Statement;
let previousStatement: Statement | undefined;
for (const statement of body.statements) {
if (shouldWriteSeparatingLineTerminator(previousStatement, statement, ListFormat.PreserveLines)) {
return false;
@@ -2189,7 +2187,7 @@ namespace ts {
while (body.kind === SyntaxKind.ModuleDeclaration) {
writePunctuation(".");
emit((<ModuleDeclaration>body).name);
body = (<ModuleDeclaration>body).body;
body = (<ModuleDeclaration>body).body!;
}
writeSpace();
@@ -2406,7 +2404,7 @@ namespace ts {
function emitJsxAttribute(node: JsxAttribute) {
emit(node.name);
emitNodeWithPrefix("=", writePunctuation, node.initializer, emit);
emitNodeWithPrefix("=", writePunctuation, node.initializer!, emit); // TODO: GH#18217
}
function emitJsxSpreadAttribute(node: JsxSpreadAttribute) {
@@ -2562,7 +2560,7 @@ namespace ts {
}
function emitSyntheticTripleSlashReferencesIfNeeded(node: Bundle) {
emitTripleSlashDirectives(node.hasNoDefaultLib, node.syntheticFileReferences || [], node.syntheticTypeReferences || []);
emitTripleSlashDirectives(!!node.hasNoDefaultLib, node.syntheticFileReferences || [], node.syntheticTypeReferences || []);
}
function emitTripleSlashDirectivesIfNeeded(node: SourceFile) {
@@ -2693,7 +2691,7 @@ namespace ts {
write = savedWrite;
}
function emitModifiers(node: Node, modifiers: NodeArray<Modifier>) {
function emitModifiers(node: Node, modifiers: NodeArray<Modifier> | undefined) {
if (modifiers && modifiers.length) {
emitList(node, modifiers, ListFormat.Modifiers);
writeSpace();
@@ -2758,15 +2756,15 @@ namespace ts {
}
}
function emitDecorators(parentNode: Node, decorators: NodeArray<Decorator>) {
function emitDecorators(parentNode: Node, decorators: NodeArray<Decorator> | undefined) {
emitList(parentNode, decorators, ListFormat.Decorators);
}
function emitTypeArguments(parentNode: Node, typeArguments: NodeArray<TypeNode>) {
function emitTypeArguments(parentNode: Node, typeArguments: NodeArray<TypeNode> | undefined) {
emitList(parentNode, typeArguments, ListFormat.TypeArguments);
}
function emitTypeParameters(parentNode: SignatureDeclaration | InterfaceDeclaration | TypeAliasDeclaration | ClassDeclaration | ClassExpression, typeParameters: NodeArray<TypeParameterDeclaration>) {
function emitTypeParameters(parentNode: SignatureDeclaration | InterfaceDeclaration | TypeAliasDeclaration | ClassDeclaration | ClassExpression, typeParameters: NodeArray<TypeParameterDeclaration> | undefined) {
if (isFunctionLike(parentNode) && parentNode.typeArguments) { // Quick info uses type arguments in place of type parameters on instantiated signatures
return emitTypeArguments(parentNode, parentNode.typeArguments);
}
@@ -2807,12 +2805,12 @@ namespace ts {
emitList(parentNode, parameters, ListFormat.IndexSignatureParameters);
}
function emitList(parentNode: TextRange, children: NodeArray<Node>, format: ListFormat, start?: number, count?: number) {
function emitList(parentNode: TextRange, children: NodeArray<Node> | undefined, format: ListFormat, start?: number, count?: number) {
emitNodeList(emit, parentNode, children, format, start, count);
}
function emitExpressionList(parentNode: TextRange, children: NodeArray<Node>, format: ListFormat, start?: number, count?: number) {
emitNodeList(emitExpression, parentNode, children, format, start, count);
function emitExpressionList(parentNode: TextRange, children: NodeArray<Node> | undefined, format: ListFormat, start?: number, count?: number) {
emitNodeList(emitExpression as (node: Node) => void, parentNode, children, format, start, count); // TODO: GH#18217
}
function writeDelimiter(format: ListFormat) {
@@ -2833,13 +2831,13 @@ namespace ts {
}
}
function emitNodeList(emit: (node: Node) => void, parentNode: TextRange, children: NodeArray<Node>, format: ListFormat, start = 0, count = children ? children.length - start : 0) {
function emitNodeList(emit: (node: Node) => void, parentNode: TextRange, children: NodeArray<Node> | undefined, format: ListFormat, start = 0, count = children ? children.length - start : 0) {
const isUndefined = children === undefined;
if (isUndefined && format & ListFormat.OptionalIfUndefined) {
return;
}
const isEmpty = isUndefined || start >= children.length || count === 0;
const isEmpty = children === undefined || start >= children.length || count === 0;
if (isEmpty && format & ListFormat.OptionalIfEmpty) {
if (onBeforeEmitNodeArray) {
onBeforeEmitNodeArray(children);
@@ -2853,7 +2851,8 @@ namespace ts {
if (format & ListFormat.BracketsMask) {
writePunctuation(getOpeningBracket(format));
if (isEmpty && !isUndefined) {
emitTrailingCommentsOfPosition(children.pos, /*prefixSpace*/ true); // Emit comments within empty bracketed lists
// TODO: GH#18217
emitTrailingCommentsOfPosition(children!.pos, /*prefixSpace*/ true); // Emit comments within empty bracketed lists
}
}
@@ -2874,7 +2873,7 @@ namespace ts {
// Write the opening line terminator or leading whitespace.
const mayEmitInterveningComments = (format & ListFormat.NoInterveningComments) === 0;
let shouldEmitInterveningComments = mayEmitInterveningComments;
if (shouldWriteLeadingLineTerminator(parentNode, children, format)) {
if (shouldWriteLeadingLineTerminator(parentNode, children!, format)) { // TODO: GH#18217
writeLine();
shouldEmitInterveningComments = false;
}
@@ -2888,10 +2887,10 @@ namespace ts {
}
// Emit each child.
let previousSibling: Node;
let shouldDecreaseIndentAfterEmit: boolean;
let previousSibling: Node | undefined;
let shouldDecreaseIndentAfterEmit = false;
for (let i = 0; i < count; i++) {
const child = children[start + i];
const child = children![start + i];
// Write the delimiter if this is not the first node.
if (previousSibling) {
@@ -2945,7 +2944,7 @@ namespace ts {
}
// Write a trailing comma, if requested.
const hasTrailingComma = (format & ListFormat.AllowTrailingComma) && children.hasTrailingComma;
const hasTrailingComma = (format & ListFormat.AllowTrailingComma) && children!.hasTrailingComma;
if (format & ListFormat.CommaDelimited && hasTrailingComma) {
writePunctuation(",");
}
@@ -2967,7 +2966,7 @@ namespace ts {
}
// Write the closing line terminator or closing whitespace.
if (shouldWriteClosingLineTerminator(parentNode, children, format)) {
if (shouldWriteClosingLineTerminator(parentNode, children!, format)) {
writeLine();
}
else if (format & ListFormat.SpaceBetweenBraces) {
@@ -2981,7 +2980,8 @@ namespace ts {
if (format & ListFormat.BracketsMask) {
if (isEmpty && !isUndefined) {
emitLeadingCommentsOfPosition(children.end); // Emit leading comments within empty lists
// TODO: GH#18217
emitLeadingCommentsOfPosition(children!.end); // Emit leading comments within empty lists
}
writePunctuation(getClosingBracket(format));
}
@@ -3077,16 +3077,18 @@ namespace ts {
if (onBeforeEmitToken) {
onBeforeEmitToken(node);
}
writer(tokenToString(node.kind));
writer(tokenToString(node.kind)!);
if (onAfterEmitToken) {
onAfterEmitToken(node);
}
}
function writeTokenText(token: SyntaxKind, writer: (s: string) => void, pos?: number) {
const tokenString = tokenToString(token);
function writeTokenText(token: SyntaxKind, writer: (s: string) => void): void;
function writeTokenText(token: SyntaxKind, writer: (s: string) => void, pos: number): number;
function writeTokenText(token: SyntaxKind, writer: (s: string) => void, pos?: number): number {
const tokenString = tokenToString(token)!;
writer(tokenString);
return pos < 0 ? pos : pos + tokenString.length;
return pos! < 0 ? pos! : pos! + tokenString.length;
}
function writeLineOrSpace(node: Node) {
@@ -3160,7 +3162,7 @@ namespace ts {
}
}
function shouldWriteSeparatingLineTerminator(previousNode: Node, nextNode: Node, format: ListFormat) {
function shouldWriteSeparatingLineTerminator(previousNode: Node | undefined, nextNode: Node, format: ListFormat) {
if (format & ListFormat.MultiLine) {
return true;
}
@@ -3205,7 +3207,7 @@ namespace ts {
}
}
function synthesizedNodeStartsOnNewLine(node: Node, format?: ListFormat) {
function synthesizedNodeStartsOnNewLine(node: Node, format: ListFormat) {
if (nodeIsSynthesized(node)) {
const startsOnNewLine = getStartsOnNewLine(node);
if (startsOnNewLine === undefined) {
@@ -3255,7 +3257,7 @@ namespace ts {
return idText(node);
}
else if (node.kind === SyntaxKind.StringLiteral && (<StringLiteral>node).textSourceNode) {
return getTextOfNode((<StringLiteral>node).textSourceNode, includeTrivia);
return getTextOfNode((<StringLiteral>node).textSourceNode!, includeTrivia);
}
else if (isLiteralExpression(node) && (nodeIsSynthesized(node) || !node.parent)) {
return node.text;
@@ -3266,7 +3268,7 @@ namespace ts {
function getLiteralTextOfNode(node: LiteralLikeNode): string {
if (node.kind === SyntaxKind.StringLiteral && (<StringLiteral>node).textSourceNode) {
const textSourceNode = (<StringLiteral>node).textSourceNode;
const textSourceNode = (<StringLiteral>node).textSourceNode!;
if (isIdentifier(textSourceNode)) {
return getEmitFlags(node) & EmitFlags.NoAsciiEscaping ?
`"${escapeString(getTextOfNode(textSourceNode))}"` :
@@ -3299,8 +3301,8 @@ namespace ts {
if (node && getEmitFlags(node) & EmitFlags.ReuseTempVariableScope) {
return;
}
tempFlags = tempFlagsStack.pop();
reservedNames = reservedNamesStack.pop();
tempFlags = tempFlagsStack.pop()!;
reservedNames = reservedNamesStack.pop()!;
}
function reserveNameInNestedScopes(name: string) {
@@ -3430,7 +3432,7 @@ namespace ts {
else {
// Auto, Loop, and Unique names are cached based on their unique
// autoGenerateId.
const autoGenerateId = name.autoGenerateId;
const autoGenerateId = name.autoGenerateId!;
return autoGeneratedIdToGeneratedName[autoGenerateId] || (autoGeneratedIdToGeneratedName[autoGenerateId] = makeName(name));
}
}
@@ -3461,7 +3463,7 @@ namespace ts {
* Returns a value indicating whether a name is unique within a container.
*/
function isUniqueLocalName(name: string, container: Node): boolean {
for (let node = container; isNodeDescendantOf(node, container); node = node.nextContainer) {
for (let node = container; isNodeDescendantOf(node, container); node = node.nextContainer!) {
if (node.locals) {
const local = node.locals.get(escapeLeadingUnderscores(name));
// We conservatively include alias symbols to cover cases where they're emitted as locals
@@ -3563,7 +3565,7 @@ namespace ts {
* Generates a unique name for an ImportDeclaration or ExportDeclaration.
*/
function generateNameForImportOrExportDeclaration(node: ImportDeclaration | ExportDeclaration) {
const expr = getExternalModuleName(node);
const expr = getExternalModuleName(node)!; // TODO: GH#18217
const baseName = isStringLiteral(expr) ?
makeIdentifierFromModuleName(expr.text) : "module";
return makeUniqueName(baseName);
@@ -3599,8 +3601,8 @@ namespace ts {
return makeUniqueName(
getTextOfNode(node),
isUniqueName,
!!(flags & GeneratedIdentifierFlags.Optimistic),
!!(flags & GeneratedIdentifierFlags.ReservedInNestedScopes)
!!(flags! & GeneratedIdentifierFlags.Optimistic),
!!(flags! & GeneratedIdentifierFlags.ReservedInNestedScopes)
);
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.EnumDeclaration:
@@ -3641,7 +3643,7 @@ namespace ts {
);
}
Debug.fail("Unsupported GeneratedIdentifierKind.");
return Debug.fail("Unsupported GeneratedIdentifierKind.");
}
/**
@@ -3657,7 +3659,7 @@ namespace ts {
// if "node" is a different generated name (having a different
// "autoGenerateId"), use it and stop traversing.
if (isIdentifier(node)
&& !!(node.autoGenerateFlags & GeneratedIdentifierFlags.Node)
&& !!(node.autoGenerateFlags! & GeneratedIdentifierFlags.Node)
&& node.autoGenerateId !== autoGenerateId) {
break;
}
+86 -84
View File
@@ -39,13 +39,13 @@ namespace ts {
* Creates a shallow, memberwise clone of a node with no source map location.
*/
/* @internal */
export function getSynthesizedClone<T extends Node>(node: T | undefined): T | undefined {
export function getSynthesizedClone<T extends Node>(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 = <T>createSynthesizedNode(node.kind);
@@ -116,7 +116,7 @@ namespace ts {
export function createIdentifier(text: string): Identifier;
/* @internal */
export function createIdentifier(text: string, typeArguments: ReadonlyArray<TypeNode | TypeParameterDeclaration>): Identifier; // tslint:disable-line unified-signatures
export function createIdentifier(text: string, typeArguments: ReadonlyArray<TypeNode | TypeParameterDeclaration> | undefined): Identifier; // tslint:disable-line unified-signatures
export function createIdentifier(text: string, typeArguments?: ReadonlyArray<TypeNode | TypeParameterDeclaration>): Identifier {
const node = <Identifier>createSynthesizedNode(SyntaxKind.Identifier);
node.escapedText = escapeLeadingUnderscores(text);
@@ -142,9 +142,9 @@ namespace ts {
/** Create a unique temporary variable. */
export function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined): Identifier;
/* @internal */ export function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined, reservedInNestedScopes: boolean): Identifier; // tslint:disable-line unified-signatures
export function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined, reservedInNestedScopes?: boolean): Identifier {
const name = createIdentifier("");
/* @internal */ export function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined, reservedInNestedScopes: boolean): GeneratedIdentifier; // tslint:disable-line unified-signatures
export function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined, reservedInNestedScopes?: boolean): GeneratedIdentifier {
const name = createIdentifier("") as GeneratedIdentifier;
name.autoGenerateFlags = GeneratedIdentifierFlags.Auto;
name.autoGenerateId = nextAutoGenerateId;
nextAutoGenerateId++;
@@ -175,9 +175,11 @@ namespace ts {
return name;
}
/* @internal */ export function createOptimisticUniqueName(text: string): GeneratedIdentifier;
/** Create a unique name based on the supplied text. */
export function createOptimisticUniqueName(text: string): Identifier {
const name = createIdentifier(text);
export function createOptimisticUniqueName(text: string): Identifier;
export function createOptimisticUniqueName(text: string): GeneratedIdentifier {
const name = createIdentifier(text) as GeneratedIdentifier;
name.autoGenerateFlags = GeneratedIdentifierFlags.Unique | GeneratedIdentifierFlags.Optimistic;
name.autoGenerateId = nextAutoGenerateId;
nextAutoGenerateId++;
@@ -196,7 +198,7 @@ namespace ts {
/* @internal */ export function getGeneratedNameForNode(node: Node, flags: GeneratedIdentifierFlags): Identifier; // tslint:disable-line unified-signatures
export function getGeneratedNameForNode(node: Node, flags?: GeneratedIdentifierFlags): Identifier {
const name = createIdentifier(isIdentifier(node) ? idText(node) : "");
name.autoGenerateFlags = GeneratedIdentifierFlags.Node | flags;
name.autoGenerateFlags = GeneratedIdentifierFlags.Node | flags!;
name.autoGenerateId = nextAutoGenerateId;
name.original = node;
nextAutoGenerateId++;
@@ -713,7 +715,7 @@ namespace ts {
: node;
}
export function createTypeLiteralNode(members: ReadonlyArray<TypeElement>) {
export function createTypeLiteralNode(members: ReadonlyArray<TypeElement> | undefined) {
const node = createSynthesizedNode(SyntaxKind.TypeLiteral) as TypeLiteralNode;
node.members = createNodeArray(members);
return node;
@@ -846,7 +848,7 @@ namespace ts {
export function createTypeOperatorNode(operatorOrType: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | TypeNode, type?: TypeNode) {
const node = createSynthesizedNode(SyntaxKind.TypeOperator) as TypeOperatorNode;
node.operator = typeof operatorOrType === "number" ? operatorOrType : SyntaxKind.KeyOfKeyword;
node.type = parenthesizeElementTypeMember(typeof operatorOrType === "number" ? type : operatorOrType);
node.type = parenthesizeElementTypeMember(typeof operatorOrType === "number" ? type! : operatorOrType);
return node;
}
@@ -970,10 +972,10 @@ namespace ts {
: node;
}
export function createPropertyAccess(expression: Expression, name: string | Identifier) {
export function createPropertyAccess(expression: Expression, name: string | Identifier | undefined) {
const node = <PropertyAccessExpression>createSynthesizedNode(SyntaxKind.PropertyAccessExpression);
node.expression = parenthesizeForAccess(expression);
node.name = asName(name);
node.name = asName(name)!; // TODO: GH#18217
setEmitFlags(node, EmitFlags.NoIndentation);
return node;
}
@@ -1001,7 +1003,7 @@ namespace ts {
: node;
}
export function createCall(expression: Expression, typeArguments: ReadonlyArray<TypeNode> | undefined, argumentsArray: ReadonlyArray<Expression>) {
export function createCall(expression: Expression, typeArguments: ReadonlyArray<TypeNode> | undefined, argumentsArray: ReadonlyArray<Expression> | undefined) {
const node = <CallExpression>createSynthesizedNode(SyntaxKind.CallExpression);
node.expression = parenthesizeForAccess(expression);
node.typeArguments = asNodeArray(typeArguments);
@@ -1034,15 +1036,15 @@ namespace ts {
}
export function createTaggedTemplate(tag: Expression, template: TemplateLiteral): TaggedTemplateExpression;
export function createTaggedTemplate(tag: Expression, typeArguments: ReadonlyArray<TypeNode>, template: TemplateLiteral): TaggedTemplateExpression;
export function createTaggedTemplate(tag: Expression, typeArguments: ReadonlyArray<TypeNode> | undefined, template: TemplateLiteral): TaggedTemplateExpression;
/** @internal */
export function createTaggedTemplate(tag: Expression, typeArgumentsOrTemplate: ReadonlyArray<TypeNode> | TemplateLiteral, template?: TemplateLiteral): TaggedTemplateExpression;
export function createTaggedTemplate(tag: Expression, typeArgumentsOrTemplate: ReadonlyArray<TypeNode> | TemplateLiteral, template?: TemplateLiteral) {
export function createTaggedTemplate(tag: Expression, typeArgumentsOrTemplate: ReadonlyArray<TypeNode> | TemplateLiteral | undefined, template?: TemplateLiteral): TaggedTemplateExpression;
export function createTaggedTemplate(tag: Expression, typeArgumentsOrTemplate: ReadonlyArray<TypeNode> | TemplateLiteral | undefined, template?: TemplateLiteral) {
const node = <TaggedTemplateExpression>createSynthesizedNode(SyntaxKind.TaggedTemplateExpression);
node.tag = parenthesizeForAccess(tag);
if (template) {
node.typeArguments = asNodeArray(typeArgumentsOrTemplate as ReadonlyArray<TypeNode>);
node.template = template!;
node.template = template;
}
else {
node.typeArguments = undefined;
@@ -1052,8 +1054,8 @@ namespace ts {
}
export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, template: TemplateLiteral): TaggedTemplateExpression;
export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: ReadonlyArray<TypeNode>, template: TemplateLiteral): TaggedTemplateExpression;
export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArgumentsOrTemplate: ReadonlyArray<TypeNode> | TemplateLiteral, template?: TemplateLiteral) {
export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: ReadonlyArray<TypeNode> | undefined, template: TemplateLiteral): TaggedTemplateExpression;
export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArgumentsOrTemplate: ReadonlyArray<TypeNode> | TemplateLiteral | undefined, template?: TemplateLiteral) {
return node.tag !== tag
|| (template
? node.typeArguments !== typeArgumentsOrTemplate || node.template !== template
@@ -1093,7 +1095,7 @@ namespace ts {
asteriskToken: AsteriskToken | undefined,
name: string | Identifier | undefined,
typeParameters: ReadonlyArray<TypeParameterDeclaration> | undefined,
parameters: ReadonlyArray<ParameterDeclaration>,
parameters: ReadonlyArray<ParameterDeclaration> | undefined,
type: TypeNode | undefined,
body: Block) {
const node = <FunctionExpression>createSynthesizedNode(SyntaxKind.FunctionExpression);
@@ -1288,7 +1290,7 @@ namespace ts {
node.condition = parenthesizeForConditionalHead(condition);
node.questionToken = whenFalse ? <QuestionToken>questionTokenOrWhenTrue : createToken(SyntaxKind.QuestionToken);
node.whenTrue = parenthesizeSubexpressionOfConditionalExpression(whenFalse ? whenTrueOrWhenFalse : <Expression>questionTokenOrWhenTrue);
node.colonToken = whenFalse ? colonToken : createToken(SyntaxKind.ColonToken);
node.colonToken = whenFalse ? colonToken! : createToken(SyntaxKind.ColonToken);
node.whenFalse = parenthesizeSubexpressionOfConditionalExpression(whenFalse ? whenFalse : whenTrueOrWhenFalse);
return node;
}
@@ -1360,8 +1362,8 @@ namespace ts {
}
export function createYield(expression?: Expression): YieldExpression;
export function createYield(asteriskToken: AsteriskToken, expression: Expression): YieldExpression;
export function createYield(asteriskTokenOrExpression?: AsteriskToken | Expression, expression?: Expression) {
export function createYield(asteriskToken: AsteriskToken | undefined, expression: Expression): YieldExpression;
export function createYield(asteriskTokenOrExpression?: AsteriskToken | undefined | Expression, expression?: Expression) {
const node = <YieldExpression>createSynthesizedNode(SyntaxKind.YieldExpression);
node.asteriskToken = asteriskTokenOrExpression && asteriskTokenOrExpression.kind === SyntaxKind.AsteriskToken ? <AsteriskToken>asteriskTokenOrExpression : undefined;
node.expression = asteriskTokenOrExpression && asteriskTokenOrExpression.kind !== SyntaxKind.AsteriskToken ? asteriskTokenOrExpression : expression;
@@ -1391,7 +1393,7 @@ namespace ts {
modifiers: ReadonlyArray<Modifier> | undefined,
name: string | Identifier | undefined,
typeParameters: ReadonlyArray<TypeParameterDeclaration> | undefined,
heritageClauses: ReadonlyArray<HeritageClause>,
heritageClauses: ReadonlyArray<HeritageClause> | undefined,
members: ReadonlyArray<ClassElement>) {
const node = <ClassExpression>createSynthesizedNode(SyntaxKind.ClassExpression);
node.decorators = undefined;
@@ -1408,7 +1410,7 @@ namespace ts {
modifiers: ReadonlyArray<Modifier> | undefined,
name: Identifier | undefined,
typeParameters: ReadonlyArray<TypeParameterDeclaration> | undefined,
heritageClauses: ReadonlyArray<HeritageClause>,
heritageClauses: ReadonlyArray<HeritageClause> | undefined,
members: ReadonlyArray<ClassElement>) {
return node.modifiers !== modifiers
|| node.name !== name
@@ -1423,14 +1425,14 @@ namespace ts {
return <OmittedExpression>createSynthesizedNode(SyntaxKind.OmittedExpression);
}
export function createExpressionWithTypeArguments(typeArguments: ReadonlyArray<TypeNode>, expression: Expression) {
export function createExpressionWithTypeArguments(typeArguments: ReadonlyArray<TypeNode> | undefined, expression: Expression) {
const node = <ExpressionWithTypeArguments>createSynthesizedNode(SyntaxKind.ExpressionWithTypeArguments);
node.expression = parenthesizeForAccess(expression);
node.typeArguments = asNodeArray(typeArguments);
return node;
}
export function updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, typeArguments: ReadonlyArray<TypeNode>, expression: Expression) {
export function updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, typeArguments: ReadonlyArray<TypeNode> | undefined, expression: Expression) {
return node.typeArguments !== typeArguments
|| node.expression !== expression
? updateNode(createExpressionWithTypeArguments(typeArguments, expression), node)
@@ -1625,7 +1627,7 @@ namespace ts {
: node;
}
export function createForOf(awaitModifier: AwaitKeywordToken, initializer: ForInitializer, expression: Expression, statement: Statement) {
export function createForOf(awaitModifier: AwaitKeywordToken | undefined, initializer: ForInitializer, expression: Expression, statement: Statement) {
const node = <ForOfStatement>createSynthesizedNode(SyntaxKind.ForOfStatement);
node.awaitModifier = awaitModifier;
node.initializer = initializer;
@@ -1634,7 +1636,7 @@ namespace ts {
return node;
}
export function updateForOf(node: ForOfStatement, awaitModifier: AwaitKeywordToken, initializer: ForInitializer, expression: Expression, statement: Statement) {
export function updateForOf(node: ForOfStatement, awaitModifier: AwaitKeywordToken | undefined, initializer: ForInitializer, expression: Expression, statement: Statement) {
return node.awaitModifier !== awaitModifier
|| node.initializer !== initializer
|| node.expression !== expression
@@ -1769,7 +1771,7 @@ namespace ts {
: node;
}
export function createVariableDeclarationList(declarations: ReadonlyArray<VariableDeclaration>, flags?: NodeFlags) {
export function createVariableDeclarationList(declarations: ReadonlyArray<VariableDeclaration>, flags = NodeFlags.None) {
const node = <VariableDeclarationList>createSynthesizedNode(SyntaxKind.VariableDeclarationList);
node.flags |= flags & NodeFlags.BlockScoped;
node.declarations = createNodeArray(declarations);
@@ -1830,7 +1832,7 @@ namespace ts {
modifiers: ReadonlyArray<Modifier> | undefined,
name: string | Identifier | undefined,
typeParameters: ReadonlyArray<TypeParameterDeclaration> | undefined,
heritageClauses: ReadonlyArray<HeritageClause>,
heritageClauses: ReadonlyArray<HeritageClause> | undefined,
members: ReadonlyArray<ClassElement>) {
const node = <ClassDeclaration>createSynthesizedNode(SyntaxKind.ClassDeclaration);
node.decorators = asNodeArray(decorators);
@@ -1848,7 +1850,7 @@ namespace ts {
modifiers: ReadonlyArray<Modifier> | undefined,
name: Identifier | undefined,
typeParameters: ReadonlyArray<TypeParameterDeclaration> | undefined,
heritageClauses: ReadonlyArray<HeritageClause>,
heritageClauses: ReadonlyArray<HeritageClause> | undefined,
members: ReadonlyArray<ClassElement>) {
return node.decorators !== decorators
|| node.modifiers !== modifiers
@@ -1953,7 +1955,7 @@ namespace ts {
: node;
}
export function createModuleDeclaration(decorators: ReadonlyArray<Decorator> | undefined, modifiers: ReadonlyArray<Modifier> | undefined, name: ModuleName, body: ModuleBody | undefined, flags?: NodeFlags) {
export function createModuleDeclaration(decorators: ReadonlyArray<Decorator> | undefined, modifiers: ReadonlyArray<Modifier> | undefined, name: ModuleName, body: ModuleBody | undefined, flags = NodeFlags.None) {
const node = <ModuleDeclaration>createSynthesizedNode(SyntaxKind.ModuleDeclaration);
node.flags |= flags & (NodeFlags.Namespace | NodeFlags.NestedNamespace | NodeFlags.GlobalAugmentation);
node.decorators = asNodeArray(decorators);
@@ -2044,7 +2046,7 @@ namespace ts {
decorators: ReadonlyArray<Decorator> | undefined,
modifiers: ReadonlyArray<Modifier> | undefined,
importClause: ImportClause | undefined,
moduleSpecifier: Expression | undefined) {
moduleSpecifier: Expression) {
return node.decorators !== decorators
|| node.modifiers !== modifiers
|| node.importClause !== importClause
@@ -2105,7 +2107,7 @@ namespace ts {
: node;
}
export function createExportAssignment(decorators: ReadonlyArray<Decorator> | undefined, modifiers: ReadonlyArray<Modifier> | undefined, isExportEquals: boolean, expression: Expression) {
export function createExportAssignment(decorators: ReadonlyArray<Decorator> | undefined, modifiers: ReadonlyArray<Modifier> | undefined, isExportEquals: boolean | undefined, expression: Expression) {
const node = <ExportAssignment>createSynthesizedNode(SyntaxKind.ExportAssignment);
node.decorators = asNodeArray(decorators);
node.modifiers = asNodeArray(modifiers);
@@ -2402,7 +2404,7 @@ namespace ts {
export function createSpreadAssignment(expression: Expression) {
const node = <SpreadAssignment>createSynthesizedNode(SyntaxKind.SpreadAssignment);
node.expression = expression !== undefined ? parenthesizeExpressionForList(expression) : undefined;
node.expression = expression !== undefined ? parenthesizeExpressionForList(expression) : undefined!; // TODO: GH#18217
return node;
}
@@ -2512,7 +2514,7 @@ namespace ts {
/* @internal */
export function createEndOfDeclarationMarker(original: Node) {
const node = <EndOfDeclarationMarker>createSynthesizedNode(SyntaxKind.EndOfDeclarationMarker);
node.emitNode = {};
node.emitNode = {} as EmitNode;
node.original = original;
return node;
}
@@ -2524,7 +2526,7 @@ namespace ts {
/* @internal */
export function createMergeDeclarationMarker(original: Node) {
const node = <MergeDeclarationMarker>createSynthesizedNode(SyntaxKind.MergeDeclarationMarker);
node.emitNode = {};
node.emitNode = {} as EmitNode;
node.original = original;
return node;
}
@@ -2701,12 +2703,7 @@ namespace ts {
// Utilities
function asName(name: string | Identifier): Identifier;
function asName(name: string | BindingName): BindingName;
function asName(name: string | PropertyName): PropertyName;
function asName(name: string | EntityName): EntityName;
function asName(name: string | Identifier | ThisTypeNode): Identifier | ThisTypeNode;
function asName(name: string | Identifier | BindingName | PropertyName | QualifiedName | ThisTypeNode) {
function asName<T extends Identifier | BindingName | PropertyName | EntityName | ThisTypeNode | undefined>(name: string | T): T | Identifier {
return isString(name) ? createIdentifier(name) : name;
}
@@ -2714,6 +2711,8 @@ namespace ts {
return isString(value) || typeof value === "number" ? createLiteral(value) : value;
}
function asNodeArray<T extends Node>(array: ReadonlyArray<T>): NodeArray<T>;
function asNodeArray<T extends Node>(array: ReadonlyArray<T> | undefined): NodeArray<T> | undefined;
function asNodeArray<T extends Node>(array: ReadonlyArray<T> | undefined): NodeArray<T> | undefined {
return array ? createNodeArray(array) : undefined;
}
@@ -2748,21 +2747,21 @@ namespace ts {
* various transient transformation properties.
*/
/* @internal */
export function getOrCreateEmitNode(node: Node) {
export function getOrCreateEmitNode(node: Node): EmitNode {
if (!node.emitNode) {
if (isParseTreeNode(node)) {
// To avoid holding onto transformation artifacts, we keep track of any
// parse tree node we are annotating. This allows us to clean them up after
// all transformations have completed.
if (node.kind === SyntaxKind.SourceFile) {
return node.emitNode = { annotatedNodes: [node] };
return node.emitNode = { annotatedNodes: [node] } as EmitNode;
}
const sourceFile = getSourceFileOfNode(node);
getOrCreateEmitNode(sourceFile).annotatedNodes.push(node);
getOrCreateEmitNode(sourceFile).annotatedNodes!.push(node);
}
node.emitNode = {};
node.emitNode = {} as EmitNode;
}
return node.emitNode;
@@ -2878,7 +2877,7 @@ namespace ts {
return emitNode && emitNode.leadingComments;
}
export function setSyntheticLeadingComments<T extends Node>(node: T, comments: SynthesizedComment[]) {
export function setSyntheticLeadingComments<T extends Node>(node: T, comments: SynthesizedComment[] | undefined) {
getOrCreateEmitNode(node).leadingComments = comments;
return node;
}
@@ -2892,7 +2891,7 @@ namespace ts {
return emitNode && emitNode.trailingComments;
}
export function setSyntheticTrailingComments<T extends Node>(node: T, comments: SynthesizedComment[]) {
export function setSyntheticTrailingComments<T extends Node>(node: T, comments: SynthesizedComment[] | undefined) {
getOrCreateEmitNode(node).trailingComments = comments;
return node;
}
@@ -2913,7 +2912,7 @@ namespace ts {
/**
* Gets the constant value to emit for an expression.
*/
export function getConstantValue(node: PropertyAccessExpression | ElementAccessExpression) {
export function getConstantValue(node: PropertyAccessExpression | ElementAccessExpression): string | number | undefined {
const emitNode = node.emitNode;
return emitNode && emitNode.constantValue;
}
@@ -3015,7 +3014,7 @@ namespace ts {
return node;
}
function mergeEmitNode(sourceEmitNode: EmitNode, destEmitNode: EmitNode) {
function mergeEmitNode(sourceEmitNode: EmitNode, destEmitNode: EmitNode | undefined) {
const {
flags,
leadingComments,
@@ -3027,21 +3026,21 @@ namespace ts {
helpers,
startsOnNewLine,
} = sourceEmitNode;
if (!destEmitNode) destEmitNode = {};
if (!destEmitNode) destEmitNode = {} as EmitNode;
// We are using `.slice()` here in case `destEmitNode.leadingComments` is pushed to later.
if (leadingComments) destEmitNode.leadingComments = addRange(leadingComments.slice(), destEmitNode.leadingComments);
if (trailingComments) destEmitNode.trailingComments = addRange(trailingComments.slice(), destEmitNode.trailingComments);
if (flags) destEmitNode.flags = flags;
if (commentRange) destEmitNode.commentRange = commentRange;
if (sourceMapRange) destEmitNode.sourceMapRange = sourceMapRange;
if (tokenSourceMapRanges) destEmitNode.tokenSourceMapRanges = mergeTokenSourceMapRanges(tokenSourceMapRanges, destEmitNode.tokenSourceMapRanges);
if (tokenSourceMapRanges) destEmitNode.tokenSourceMapRanges = mergeTokenSourceMapRanges(tokenSourceMapRanges, destEmitNode.tokenSourceMapRanges!);
if (constantValue !== undefined) destEmitNode.constantValue = constantValue;
if (helpers) destEmitNode.helpers = addRange(destEmitNode.helpers, helpers);
if (startsOnNewLine !== undefined) destEmitNode.startsOnNewLine = startsOnNewLine;
return destEmitNode;
}
function mergeTokenSourceMapRanges(sourceRanges: TextRange[], destRanges: TextRange[]) {
function mergeTokenSourceMapRanges(sourceRanges: (TextRange | undefined)[], destRanges: (TextRange | undefined)[]) {
if (!destRanges) destRanges = [];
for (const key in sourceRanges) {
destRanges[key] = sourceRanges[key];
@@ -3178,7 +3177,7 @@ namespace ts {
}
}
function createJsxFactoryExpression(jsxFactoryEntity: EntityName, reactNamespace: string, parent: JsxOpeningLikeElement | JsxOpeningFragment): Expression {
function createJsxFactoryExpression(jsxFactoryEntity: EntityName | undefined, reactNamespace: string, parent: JsxOpeningLikeElement | JsxOpeningFragment): Expression {
return jsxFactoryEntity ?
createJsxFactoryExpressionFromEntityName(jsxFactoryEntity, parent) :
createPropertyAccess(
@@ -3187,7 +3186,7 @@ namespace ts {
);
}
export function createExpressionForJsxElement(jsxFactoryEntity: EntityName, reactNamespace: string, tagName: Expression, props: Expression, children: ReadonlyArray<Expression>, parentElement: JsxOpeningLikeElement, location: TextRange): LeftHandSideExpression {
export function createExpressionForJsxElement(jsxFactoryEntity: EntityName | undefined, reactNamespace: string, tagName: Expression, props: Expression, children: ReadonlyArray<Expression>, parentElement: JsxOpeningLikeElement, location: TextRange): LeftHandSideExpression {
const argumentsList = [tagName];
if (props) {
argumentsList.push(props);
@@ -3219,7 +3218,7 @@ namespace ts {
);
}
export function createExpressionForJsxFragment(jsxFactoryEntity: EntityName, reactNamespace: string, children: ReadonlyArray<Expression>, parentElement: JsxOpeningFragment, location: TextRange): LeftHandSideExpression {
export function createExpressionForJsxFragment(jsxFactoryEntity: EntityName | undefined, reactNamespace: string, children: ReadonlyArray<Expression>, parentElement: JsxOpeningFragment, location: TextRange): LeftHandSideExpression {
const tagName = createPropertyAccess(
createReactNamespace(reactNamespace, parentElement),
"Fragment"
@@ -3347,7 +3346,7 @@ namespace ts {
export function createForOfBindingStatement(node: ForInitializer, boundValue: Expression): Statement {
if (isVariableDeclarationList(node)) {
const firstDeclaration = firstOrUndefined(node.declarations);
const firstDeclaration = first(node.declarations);
const updatedDeclaration = updateVariableDeclaration(
firstDeclaration,
firstDeclaration.name,
@@ -3377,7 +3376,7 @@ namespace ts {
}
}
export function restoreEnclosingLabel(node: Statement, outermostLabeledStatement: LabeledStatement, afterRestoreLabelCallback?: (node: LabeledStatement) => void): Statement {
export function restoreEnclosingLabel(node: Statement, outermostLabeledStatement: LabeledStatement | undefined, afterRestoreLabelCallback?: (node: LabeledStatement) => void): Statement {
if (!outermostLabeledStatement) {
return node;
}
@@ -3421,7 +3420,7 @@ namespace ts {
}
}
export function createCallBinding(expression: Expression, recordTempVariable: (temp: Identifier) => void, languageVersion?: ScriptTarget, cacheIdentifiers?: boolean): CallBinding {
export function createCallBinding(expression: Expression, recordTempVariable: (temp: Identifier) => void, languageVersion?: ScriptTarget, cacheIdentifiers = false): CallBinding {
const callee = skipOuterExpressions(expression, OuterExpressionKinds.All);
let thisArg: Expression;
let target: LeftHandSideExpression;
@@ -3431,7 +3430,7 @@ namespace ts {
}
else if (callee.kind === SyntaxKind.SuperKeyword) {
thisArg = createThis();
target = languageVersion < ScriptTarget.ES2015
target = languageVersion! < ScriptTarget.ES2015
? setTextRange(createIdentifier("_super"), callee)
: <PrimaryExpression>callee;
}
@@ -3505,7 +3504,7 @@ namespace ts {
// stack size exceeded" errors.
return expressions.length > 10
? createCommaList(expressions)
: reduceLeft(expressions, createComma);
: reduceLeft(expressions, createComma)!;
}
export function createExpressionFromEntityName(node: EntityName | Expression): Expression {
@@ -3531,11 +3530,11 @@ namespace ts {
}
}
export function createExpressionForObjectLiteralElementLike(node: ObjectLiteralExpression, property: ObjectLiteralElementLike, receiver: Expression): Expression {
export function createExpressionForObjectLiteralElementLike(node: ObjectLiteralExpression, property: ObjectLiteralElementLike, receiver: Expression): Expression | undefined {
switch (property.kind) {
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
return createExpressionForAccessorDeclaration(node.properties, property, receiver, node.multiLine);
return createExpressionForAccessorDeclaration(node.properties, property, receiver, !!node.multiLine);
case SyntaxKind.PropertyAssignment:
return createExpressionForPropertyAssignment(property, receiver);
case SyntaxKind.ShorthandPropertyAssignment:
@@ -3557,7 +3556,7 @@ namespace ts {
/*typeParameters*/ undefined,
getAccessor.parameters,
/*type*/ undefined,
getAccessor.body
getAccessor.body! // TODO: GH#18217
);
setTextRange(getterFunction, getAccessor);
setOriginalNode(getterFunction, getAccessor);
@@ -3573,7 +3572,7 @@ namespace ts {
/*typeParameters*/ undefined,
setAccessor.parameters,
/*type*/ undefined,
setAccessor.body
setAccessor.body! // TODO: GH#18217
);
setTextRange(setterFunction, setAccessor);
setOriginalNode(setterFunction, setAccessor);
@@ -3648,7 +3647,7 @@ namespace ts {
/*typeParameters*/ undefined,
method.parameters,
/*type*/ undefined,
method.body
method.body! // TODO: GH#18217
),
/*location*/ method
),
@@ -3738,7 +3737,7 @@ namespace ts {
return getName(node, allowComments, allowSourceMaps);
}
function getName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean, emitFlags?: EmitFlags) {
function getName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean, emitFlags: EmitFlags = 0) {
const nodeName = getNameOfDeclaration(node);
if (nodeName && isIdentifier(nodeName) && !isGeneratedIdentifier(nodeName)) {
const name = getMutableClone(nodeName);
@@ -3780,7 +3779,7 @@ namespace ts {
export function getNamespaceMemberName(ns: Identifier, name: Identifier, allowComments?: boolean, allowSourceMaps?: boolean): PropertyAccessExpression {
const qualifiedName = createPropertyAccess(ns, nodeIsSynthesized(name) ? name : getSynthesizedClone(name));
setTextRange(qualifiedName, name);
let emitFlags: EmitFlags;
let emitFlags: EmitFlags = 0;
if (!allowSourceMaps) emitFlags |= EmitFlags.NoSourceMap;
if (!allowComments) emitFlags |= EmitFlags.NoComments;
if (emitFlags) setEmitFlags(qualifiedName, emitFlags);
@@ -3792,7 +3791,7 @@ namespace ts {
}
export function convertFunctionDeclarationToExpression(node: FunctionDeclaration) {
Debug.assert(!!node.body);
if (!node.body) return Debug.fail();
const updated = createFunctionExpression(
node.modifiers,
node.asteriskToken,
@@ -3867,9 +3866,11 @@ namespace ts {
* This function needs to be called whenever we transform the statement
* list of a source file, namespace, or function-like body.
*/
export function addCustomPrologue(target: Statement[], source: ReadonlyArray<Statement>, statementOffset: number, visitor?: (node: Node) => VisitResult<Node>): number {
export function addCustomPrologue(target: Statement[], source: ReadonlyArray<Statement>, statementOffset: number, visitor?: (node: Node) => VisitResult<Node>): number;
export function addCustomPrologue(target: Statement[], source: ReadonlyArray<Statement>, statementOffset: number | undefined, visitor?: (node: Node) => VisitResult<Node>): number | undefined;
export function addCustomPrologue(target: Statement[], source: ReadonlyArray<Statement>, statementOffset: number | undefined, visitor?: (node: Node) => VisitResult<Node>): number | undefined {
const numStatements = source.length;
while (statementOffset < numStatements) {
while (statementOffset !== undefined && statementOffset < numStatements) {
const statement = source[statementOffset];
if (getEmitFlags(statement) & EmitFlags.CustomPrologue) {
append(target, visitor ? visitNode(statement, visitor, isStatement) : statement);
@@ -3951,7 +3952,7 @@ namespace ts {
* @param isLeftSideOfBinary A value indicating whether the operand is the left side of the
* BinaryExpression.
*/
function binaryOperandNeedsParentheses(binaryOperator: SyntaxKind, operand: Expression, isLeftSideOfBinary: boolean, leftOperand: Expression) {
function binaryOperandNeedsParentheses(binaryOperator: SyntaxKind, operand: Expression, isLeftSideOfBinary: boolean, leftOperand: Expression | undefined) {
// If the operand has lower precedence, then it needs to be parenthesized to preserve the
// intent of the expression. For example, if the operand is `a + b` and the operator is
// `*`, then we need to parenthesize the operand to preserve the intended order of
@@ -4196,7 +4197,7 @@ namespace ts {
}
export function parenthesizeListElements(elements: NodeArray<Expression>) {
let result: Expression[];
let result: Expression[] | undefined;
for (let i = 0; i < elements.length; i++) {
const element = parenthesizeExpressionForList(elements[i]);
if (result !== undefined || element !== elements[i]) {
@@ -4273,7 +4274,7 @@ namespace ts {
return createNodeArray(sameMap(members, parenthesizeElementTypeMember));
}
export function parenthesizeTypeParameters(typeParameters: ReadonlyArray<TypeNode>) {
export function parenthesizeTypeParameters(typeParameters: ReadonlyArray<TypeNode> | undefined) {
if (some(typeParameters)) {
const params: TypeNode[] = [];
for (let i = 0; i < typeParameters.length; ++i) {
@@ -4475,7 +4476,7 @@ namespace ts {
/**
* Get the name of that target module from an import or export declaration
*/
export function getLocalNameForExternalImport(node: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration, sourceFile: SourceFile): Identifier {
export function getLocalNameForExternalImport(node: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration, sourceFile: SourceFile): Identifier | undefined {
const namespaceDeclaration = getNamespaceDeclarationNode(node);
if (namespaceDeclaration && !isDefaultImport(node)) {
const name = namespaceDeclaration.name;
@@ -4499,7 +4500,7 @@ namespace ts {
* Otherwise, a new StringLiteral node representing the module name will be returned.
*/
export function getExternalModuleNameLiteral(importNode: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration, sourceFile: SourceFile, host: EmitHost, resolver: EmitResolver, compilerOptions: CompilerOptions) {
const moduleName = getExternalModuleName(importNode);
const moduleName = getExternalModuleName(importNode)!; // TODO: GH#18217
if (moduleName.kind === SyntaxKind.StringLiteral) {
return tryGetModuleNameFromDeclaration(importNode, host, resolver, compilerOptions)
|| tryRenameExternalModule(<StringLiteral>moduleName, sourceFile)
@@ -4525,7 +4526,7 @@ namespace ts {
* 2. --out or --outFile is used, making the name relative to the rootDir
* Otherwise, a new StringLiteral node representing the module name will be returned.
*/
export function tryGetModuleNameFromFile(file: SourceFile, host: EmitHost, options: CompilerOptions): StringLiteral {
export function tryGetModuleNameFromFile(file: SourceFile | undefined, host: EmitHost, options: CompilerOptions): StringLiteral | undefined {
if (!file) {
return undefined;
}
@@ -4561,8 +4562,9 @@ namespace ts {
// `1` in `({ a: b = 1 } = ...)`
// `1` in `({ a: {b} = 1 } = ...)`
// `1` in `({ a: [b] = 1 } = ...)`
return isAssignmentExpression(bindingElement.initializer, /*excludeCompoundAssignment*/ true)
? bindingElement.initializer.right
const initializer = bindingElement.initializer;
return isAssignmentExpression(initializer, /*excludeCompoundAssignment*/ true)
? initializer.right
: undefined;
}
@@ -4587,7 +4589,7 @@ namespace ts {
/**
* Gets the name of an BindingOrAssignmentElement.
*/
export function getTargetOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): BindingOrAssignmentElementTarget {
export function getTargetOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): BindingOrAssignmentElementTarget | undefined {
if (isDeclarationBindingElement(bindingElement)) {
// `a` in `let { a } = ...`
// `a` in `let { a = 1 } = ...`
@@ -4662,7 +4664,7 @@ namespace ts {
/**
* Determines whether an BindingOrAssignmentElement is a rest element.
*/
export function getRestIndicatorOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): BindingOrAssignmentElementRestIndicator {
export function getRestIndicatorOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): BindingOrAssignmentElementRestIndicator | undefined {
switch (bindingElement.kind) {
case SyntaxKind.Parameter:
case SyntaxKind.BindingElement:
+28 -29
View File
@@ -2,12 +2,12 @@ namespace ts {
/* @internal */
export function trace(host: ModuleResolutionHost, message: DiagnosticMessage, ...args: any[]): void;
export function trace(host: ModuleResolutionHost): void {
host.trace(formatMessage.apply(undefined, arguments));
host.trace!(formatMessage.apply(undefined, arguments));
}
/* @internal */
export function isTraceEnabled(compilerOptions: CompilerOptions, host: ModuleResolutionHost): boolean {
return compilerOptions.traceResolution && host.trace !== undefined;
return !!compilerOptions.traceResolution && host.trace !== undefined;
}
/** Array that is only intended to be pushed to, never read. */
@@ -16,11 +16,11 @@ namespace ts {
push(value: T): void;
}
function withPackageId(packageId: PackageId | undefined, r: PathAndExtension | undefined): Resolved {
function withPackageId(packageId: PackageId | undefined, r: PathAndExtension | undefined): Resolved | undefined {
return r && { path: r.path, extension: r.ext, packageId };
}
function noPackageId(r: PathAndExtension | undefined): Resolved {
function noPackageId(r: PathAndExtension | undefined): Resolved | undefined {
return withPackageId(/*packageId*/ undefined, r);
}
@@ -51,7 +51,7 @@ namespace ts {
interface PathAndPackageId {
readonly fileName: string;
readonly packageId: PackageId;
readonly packageId: PackageId | undefined;
}
/** Used with `Extensions.DtsOnly` to extract the path from TypeScript results. */
function resolvedTypeScriptOnly(resolved: Resolved | undefined): PathAndPackageId | undefined {
@@ -141,7 +141,7 @@ namespace ts {
return options.typeRoots;
}
let currentDirectory: string;
let currentDirectory: string | undefined;
if (options.configFilePath) {
currentDirectory = getDirectoryPath(options.configFilePath);
}
@@ -164,10 +164,10 @@ namespace ts {
// And if it doesn't exist, tough.
}
let typeRoots: string[];
let typeRoots: string[] | undefined;
forEachAncestorDirectory(normalizePath(currentDirectory), directory => {
const atTypes = combinePaths(directory, nodeModulesAtTypes);
if (host.directoryExists(atTypes)) {
if (host.directoryExists!(atTypes)) {
(typeRoots || (typeRoots = [])).push(atTypes);
}
return undefined;
@@ -254,7 +254,6 @@ namespace ts {
}
function secondaryLookup(): PathAndPackageId | undefined {
let resolvedFile: PathAndPackageId;
const initialLocationForSecondaryLookup = containingFile && getDirectoryPath(containingFile);
if (initialLocationForSecondaryLookup !== undefined) {
@@ -263,7 +262,7 @@ namespace ts {
trace(host, Diagnostics.Looking_up_in_node_modules_folder_initial_location_0, initialLocationForSecondaryLookup);
}
const result = loadModuleFromNodeModules(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, failedLookupLocations, moduleResolutionState, /*cache*/ undefined);
resolvedFile = resolvedTypeScriptOnly(result && result.value);
const resolvedFile = resolvedTypeScriptOnly(result && result.value);
if (!resolvedFile && traceEnabled) {
trace(host, Diagnostics.Type_reference_directive_0_was_not_resolved, typeReferenceDirectiveName);
}
@@ -334,7 +333,7 @@ namespace ts {
}
export interface PerModuleNameCache {
get(directory: string): ResolvedModuleWithFailedLookupLocations;
get(directory: string): ResolvedModuleWithFailedLookupLocations | undefined;
set(directory: string, result: ResolvedModuleWithFailedLookupLocations): void;
}
@@ -366,9 +365,9 @@ namespace ts {
return perFolderCache;
}
function getOrCreateCacheForModuleName(nonRelativeModuleName: string) {
function getOrCreateCacheForModuleName(nonRelativeModuleName: string): PerModuleNameCache {
if (isExternalModuleNameRelative(nonRelativeModuleName)) {
return undefined;
return undefined!; // TODO: GH#18217
}
let perModuleNameCache = moduleNameToDirectoryMap.get(nonRelativeModuleName);
if (!perModuleNameCache) {
@@ -383,7 +382,7 @@ namespace ts {
return { get, set };
function get(directory: string): ResolvedModuleWithFailedLookupLocations {
function get(directory: string): ResolvedModuleWithFailedLookupLocations | undefined {
return directoryPathMap.get(toPath(directory, currentDirectory, getCanonicalFileName));
}
@@ -427,7 +426,7 @@ namespace ts {
}
}
function getCommonPrefix(directory: Path, resolution: string) {
function getCommonPrefix(directory: Path, resolution: string | undefined) {
if (resolution === undefined) {
return undefined;
}
@@ -492,13 +491,13 @@ namespace ts {
result = classicNameResolver(moduleName, containingFile, compilerOptions, host, cache);
break;
default:
Debug.fail(`Unexpected moduleResolution: ${moduleResolution}`);
return Debug.fail(`Unexpected moduleResolution: ${moduleResolution}`);
}
if (perFolderCache) {
perFolderCache.set(moduleName, result);
// put result in per-module name cache
const perModuleNameCache = cache.getOrCreateCacheForModuleName(moduleName);
const perModuleNameCache = cache!.getOrCreateCacheForModuleName(moduleName);
if (perModuleNameCache) {
perModuleNameCache.set(containingDirectory, result);
}
@@ -611,8 +610,8 @@ namespace ts {
const candidate = normalizePath(combinePaths(containingDirectory, moduleName));
let matchedRootDir: string;
let matchedNormalizedPrefix: string;
let matchedRootDir: string | undefined;
let matchedNormalizedPrefix: string | undefined;
for (const rootDir of state.compilerOptions.rootDirs) {
// rootDirs are expected to be absolute
// in case of tsconfig.json this will happen automatically - compiler will expand relative names
@@ -698,9 +697,9 @@ namespace ts {
if (state.traceEnabled) {
trace(state.host, Diagnostics.Module_name_0_matched_pattern_1, moduleName, matchedPatternText);
}
return forEach(state.compilerOptions.paths[matchedPatternText], subst => {
return forEach(state.compilerOptions.paths![matchedPatternText], subst => {
const path = matchedStar ? subst.replace("*", matchedStar) : subst;
const candidate = normalizePath(combinePaths(state.compilerOptions.baseUrl, path));
const candidate = normalizePath(combinePaths(state.compilerOptions.baseUrl!, path));
if (state.traceEnabled) {
trace(state.host, Diagnostics.Trying_substitution_0_candidate_module_location_Colon_1, subst, path);
}
@@ -781,7 +780,7 @@ namespace ts {
let originalPath: string | undefined;
if (!compilerOptions.preserveSymlinks && resolvedValue) {
originalPath = resolvedValue.path;
const path = realPath(resolved.value.path, host, traceEnabled);
const path = realPath(resolvedValue.path, host, traceEnabled);
if (path === originalPath) {
originalPath = undefined;
}
@@ -899,7 +898,7 @@ namespace ts {
return !host.directoryExists || host.directoryExists(directoryName);
}
function loadModuleFromFileNoPackageId(extensions: Extensions, candidate: string, failedLookupLocations: Push<string>, onlyRecordFailures: boolean, state: ModuleResolutionState): Resolved {
function loadModuleFromFileNoPackageId(extensions: Extensions, candidate: string, failedLookupLocations: Push<string>, onlyRecordFailures: boolean, state: ModuleResolutionState): Resolved | undefined {
return noPackageId(loadModuleFromFile(extensions, candidate, failedLookupLocations, onlyRecordFailures, state));
}
@@ -910,7 +909,7 @@ namespace ts {
function loadModuleFromFile(extensions: Extensions, candidate: string, failedLookupLocations: Push<string>, onlyRecordFailures: boolean, state: ModuleResolutionState): PathAndExtension | undefined {
if (extensions === Extensions.Json) {
const extensionLess = tryRemoveExtension(candidate, Extension.Json);
return extensionLess && tryAddingExtensions(extensionLess, extensions, failedLookupLocations, onlyRecordFailures, state);
return extensionLess === undefined ? undefined : tryAddingExtensions(extensionLess, extensions, failedLookupLocations, onlyRecordFailures, state);
}
// First, try adding an extension. An import of "foo" could be matched by a file "foo.ts", or "foo.js" by "foo.js.ts"
@@ -954,7 +953,7 @@ namespace ts {
function tryExtension(ext: Extension): PathAndExtension | undefined {
const path = tryFile(candidate + ext, failedLookupLocations, onlyRecordFailures, state);
return path && { path, ext };
return path === undefined ? undefined : { path, ext };
}
}
@@ -1025,7 +1024,7 @@ namespace ts {
if (!endsWith(subModuleName, Extension.Dts)) {
subModuleName = addExtensionAndIndex(subModuleName);
}
const packageId: PackageId = typeof packageJsonContent.name === "string" && typeof packageJsonContent.version === "string"
const packageId: PackageId | undefined = typeof packageJsonContent.name === "string" && typeof packageJsonContent.version === "string"
? { name: packageJsonContent.name, subModuleName, version: packageJsonContent.version }
: undefined;
if (traceEnabled) {
@@ -1141,7 +1140,7 @@ namespace ts {
return idx === -1 ? { packageName: moduleName, rest: "" } : { packageName: moduleName.slice(0, idx), rest: moduleName.slice(idx + 1) };
}
function loadModuleFromNodeModules(extensions: Extensions, moduleName: string, directory: string, failedLookupLocations: Push<string>, state: ModuleResolutionState, cache: NonRelativeModuleNameResolutionCache): SearchResult<Resolved> {
function loadModuleFromNodeModules(extensions: Extensions, moduleName: string, directory: string, failedLookupLocations: Push<string>, state: ModuleResolutionState, cache: NonRelativeModuleNameResolutionCache | undefined): SearchResult<Resolved> {
return loadModuleFromNodeModulesWorker(extensions, moduleName, directory, failedLookupLocations, state, /*typesOnly*/ false, cache);
}
function loadModuleFromNodeModulesAtTypes(moduleName: string, directory: string, failedLookupLocations: Push<string>, state: ModuleResolutionState): SearchResult<Resolved> {
@@ -1149,7 +1148,7 @@ namespace ts {
return loadModuleFromNodeModulesWorker(Extensions.DtsOnly, moduleName, directory, failedLookupLocations, state, /*typesOnly*/ true, /*cache*/ undefined);
}
function loadModuleFromNodeModulesWorker(extensions: Extensions, moduleName: string, directory: string, failedLookupLocations: Push<string>, state: ModuleResolutionState, typesOnly: boolean, cache: NonRelativeModuleNameResolutionCache): SearchResult<Resolved> {
function loadModuleFromNodeModulesWorker(extensions: Extensions, moduleName: string, directory: string, failedLookupLocations: Push<string>, state: ModuleResolutionState, typesOnly: boolean, cache: NonRelativeModuleNameResolutionCache | undefined): SearchResult<Resolved> {
const perModuleNameCache = cache && cache.getOrCreateCacheForModuleName(moduleName);
return forEachAncestorDirectory(normalizeSlashes(directory), ancestorDirectory => {
if (getBaseFileName(ancestorDirectory) !== "node_modules") {
@@ -1289,7 +1288,7 @@ namespace ts {
* This is the minumum code needed to expose that functionality; the rest is in LSHost.
*/
/* @internal */
export function loadModuleFromGlobalCache(moduleName: string, projectName: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, globalCache: string): ResolvedModuleWithFailedLookupLocations {
export function loadModuleFromGlobalCache(moduleName: string, projectName: string | undefined, compilerOptions: CompilerOptions, host: ModuleResolutionHost, globalCache: string): ResolvedModuleWithFailedLookupLocations {
const traceEnabled = isTraceEnabled(compilerOptions, host);
if (traceEnabled) {
trace(host, Diagnostics.Auto_discovery_for_typings_is_enabled_in_project_0_Running_extra_resolution_pass_for_module_1_using_cache_location_2, projectName, moduleName, globalCache);
+111 -111
View File
@@ -10,10 +10,10 @@ namespace ts {
}
// tslint:disable variable-name
let NodeConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
let TokenConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
let IdentifierConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
let SourceFileConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
let NodeConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node;
let TokenConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node;
let IdentifierConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node;
let SourceFileConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node;
// tslint:enable variable-name
export function createNode(kind: SyntaxKind, pos?: number, end?: number): Node {
@@ -31,11 +31,11 @@ namespace ts {
}
}
function visitNode<T>(cbNode: (node: Node) => T, node: Node): T | undefined {
function visitNode<T>(cbNode: (node: Node) => T, node: Node | undefined): T | undefined {
return node && cbNode(node);
}
function visitNodes<T>(cbNode: (node: Node) => T, cbNodes: (node: NodeArray<Node>) => T | undefined, nodes: NodeArray<Node>): T | undefined {
function visitNodes<T>(cbNode: (node: Node) => T, cbNodes: ((node: NodeArray<Node>) => T | undefined) | undefined, nodes: NodeArray<Node> | undefined): T | undefined {
if (nodes) {
if (cbNodes) {
return cbNodes(nodes);
@@ -481,7 +481,7 @@ namespace ts {
return visitNodes(cbNode, cbNodes, (<JSDocTemplateTag>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, (<JSDocTypedefTag>node).typeExpression) ||
visitNode(cbNode, (<JSDocTypedefTag>node).fullName);
}
@@ -500,7 +500,7 @@ namespace ts {
visitNode(cbNode, (<SignatureDeclaration>node).type);
case SyntaxKind.JSDocTypeLiteral:
if ((node as JSDocTypeLiteral).jsDocPropertyTags) {
for (const tag of (node as JSDocTypeLiteral).jsDocPropertyTags) {
for (const tag of (node as JSDocTypeLiteral).jsDocPropertyTags!) {
visitNode(cbNode, tag);
}
}
@@ -524,7 +524,7 @@ namespace ts {
return result;
}
export function parseIsolatedEntityName(text: string, languageVersion: ScriptTarget): EntityName {
export function parseIsolatedEntityName(text: string, languageVersion: ScriptTarget): EntityName | undefined {
return Parser.parseIsolatedEntityName(text, languageVersion);
}
@@ -551,7 +551,7 @@ namespace ts {
// from this SourceFile that are being held onto may change as a result (including
// becoming detached from any SourceFile). It is recommended that this SourceFile not
// be used once 'update' is called on it.
export function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile {
export function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks = false): SourceFile {
const newSourceFile = IncrementalParser.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks);
// Because new source file node is created, it may not have the flag PossiblyContainDynamicImport. This is the case if there is no new edit to add dynamic import.
// We will manually port the flag to the new source file.
@@ -596,7 +596,7 @@ namespace ts {
let sourceFile: SourceFile;
let parseDiagnostics: DiagnosticWithLocation[];
let syntaxCursor: IncrementalParser.SyntaxCursor;
let syntaxCursor: IncrementalParser.SyntaxCursor | undefined;
let currentToken: SyntaxKind;
let sourceText: string;
@@ -683,7 +683,7 @@ namespace ts {
// attached to the EOF token.
let parseErrorBeforeNextFinishedNode = false;
export function parseSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, syntaxCursor: IncrementalParser.SyntaxCursor, setParentNodes?: boolean, scriptKind?: ScriptKind): SourceFile {
export function parseSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, syntaxCursor: IncrementalParser.SyntaxCursor | undefined, setParentNodes = false, scriptKind?: ScriptKind): SourceFile {
scriptKind = ensureScriptKind(fileName, scriptKind);
if (scriptKind === ScriptKind.JSON) {
const result = parseJsonText(fileName, sourceText, languageVersion, syntaxCursor, setParentNodes);
@@ -702,7 +702,7 @@ namespace ts {
return result;
}
export function parseIsolatedEntityName(content: string, languageVersion: ScriptTarget): EntityName {
export function parseIsolatedEntityName(content: string, languageVersion: ScriptTarget): EntityName | undefined {
// Choice of `isDeclarationFile` should be arbitrary
initializeState(content, languageVersion, /*syntaxCursor*/ undefined, ScriptKind.JS);
// Prime the scanner.
@@ -775,7 +775,7 @@ namespace ts {
return scriptKind === ScriptKind.TSX || scriptKind === ScriptKind.JSX || scriptKind === ScriptKind.JS || scriptKind === ScriptKind.JSON ? LanguageVariant.JSX : LanguageVariant.Standard;
}
function initializeState(_sourceText: string, languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor, scriptKind: ScriptKind) {
function initializeState(_sourceText: string, languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor | undefined, scriptKind: ScriptKind) {
NodeConstructor = objectAllocator.getNodeConstructor();
TokenConstructor = objectAllocator.getTokenConstructor();
IdentifierConstructor = objectAllocator.getIdentifierConstructor();
@@ -817,11 +817,11 @@ namespace ts {
scanner.setOnError(undefined);
// Clear any data. We don't want to accidentally hold onto it for too long.
parseDiagnostics = undefined;
sourceFile = undefined;
identifiers = undefined;
parseDiagnostics = undefined!;
sourceFile = undefined!;
identifiers = undefined!;
syntaxCursor = undefined;
sourceText = undefined;
sourceText = undefined!;
}
function parseSourceFileWorker(fileName: string, languageVersion: ScriptTarget, setParentNodes: boolean, scriptKind: ScriptKind): SourceFile {
@@ -865,7 +865,7 @@ namespace ts {
const comments = getJSDocCommentRanges(node, sourceFile.text);
if (comments) {
for (const comment of comments) {
node.jsDoc = append(node.jsDoc, JSDocParser.parseJSDocComment(node, comment.pos, comment.end - comment.pos));
node.jsDoc = append<JSDoc>(node.jsDoc, JSDocParser.parseJSDocComment(node, comment.pos, comment.end - comment.pos));
}
}
@@ -893,7 +893,7 @@ namespace ts {
parent = n;
forEachChild(n, visitNode);
if (hasJSDocNodes(n)) {
for (const jsDoc of n.jsDoc) {
for (const jsDoc of n.jsDoc!) {
jsDoc.parent = n;
parent = jsDoc;
forEachChild(jsDoc, visitNode);
@@ -1205,7 +1205,7 @@ namespace ts {
}
function parseOptionalToken<TKind extends SyntaxKind>(t: TKind): Token<TKind>;
function parseOptionalToken(t: SyntaxKind): Node {
function parseOptionalToken(t: SyntaxKind): Node | undefined {
if (token() === t) {
return parseTokenNode();
}
@@ -1250,7 +1250,7 @@ namespace ts {
function createNode(kind: SyntaxKind, pos?: number): Node {
nodeCount++;
const p = pos >= 0 ? pos : scanner.getStartPos();
const p = pos! >= 0 ? pos! : scanner.getStartPos();
return isNodeKind(kind) || kind === SyntaxKind.Unknown ? new NodeConstructor(kind, p, p) :
kind === SyntaxKind.Identifier ? new IdentifierConstructor(kind, p, p) :
new TokenConstructor(kind, p, p);
@@ -1527,7 +1527,7 @@ namespace ts {
return true;
}
Debug.fail("Non-exhaustive case in 'isListElement'.");
return Debug.fail("Non-exhaustive case in 'isListElement'.");
}
function isValidHeritageClauseObjectLiteral() {
@@ -1629,6 +1629,8 @@ namespace ts {
return token() === SyntaxKind.GreaterThanToken || token() === SyntaxKind.SlashToken;
case ParsingContext.JsxChildren:
return token() === SyntaxKind.LessThanToken && lookAhead(nextTokenIsSlash);
default:
return false;
}
}
@@ -1703,7 +1705,7 @@ namespace ts {
return parseElement();
}
function currentNode(parsingContext: ParsingContext): Node {
function currentNode(parsingContext: ParsingContext): Node | undefined {
// If there is an outstanding parse error that we've encountered, but not attached to
// some node, then we cannot get a node from the old source tree. This is because we
// want to mark the next node we encounter as being unusable.
@@ -2019,6 +2021,7 @@ namespace ts {
case ParsingContext.ImportOrExportSpecifiers: return Diagnostics.Identifier_expected;
case ParsingContext.JsxAttributes: return Diagnostics.Identifier_expected;
case ParsingContext.JsxChildren: return Diagnostics.Identifier_expected;
default: return undefined!; // TODO: GH#18217 `default: Debug.assertNever(context);`
}
}
@@ -2173,7 +2176,7 @@ namespace ts {
do {
list.push(parseTemplateSpan());
}
while (lastOrUndefined(list).literal.kind === SyntaxKind.TemplateMiddle);
while (last(list).literal.kind === SyntaxKind.TemplateMiddle);
template.templateSpans = createNodeArray(list, listPos);
@@ -2396,7 +2399,7 @@ namespace ts {
}
}
function parseParameterType(): TypeNode {
function parseParameterType(): TypeNode | undefined {
if (parseOptional(SyntaxKind.ColonToken)) {
return parseType();
}
@@ -2456,7 +2459,7 @@ namespace ts {
if (!(flags & SignatureFlags.JSDoc)) {
signature.typeParameters = parseTypeParameters();
}
signature.parameters = parseParameterList(flags);
signature.parameters = parseParameterList(flags)!; // TODO: GH#18217
if (shouldParseReturnType(returnToken, !!(flags & SignatureFlags.Type))) {
signature.type = parseTypeOrTypePredicate();
return signature.type !== undefined;
@@ -2638,7 +2641,7 @@ namespace ts {
if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) {
return true;
}
let idToken: boolean;
let idToken = false;
// Eat up all modifiers, but hold on to the last one in case it is actually an identifier
while (isModifierKind(token())) {
idToken = true;
@@ -2742,7 +2745,7 @@ namespace ts {
const node = <MappedTypeNode>createNode(SyntaxKind.MappedType);
parseExpected(SyntaxKind.OpenBraceToken);
if (token() === SyntaxKind.ReadonlyKeyword || token() === SyntaxKind.PlusToken || token() === SyntaxKind.MinusToken) {
node.readonlyToken = parseTokenNode();
node.readonlyToken = parseTokenNode<ReadonlyToken | PlusToken | MinusToken>();
if (node.readonlyToken.kind !== SyntaxKind.ReadonlyKeyword) {
parseExpectedToken(SyntaxKind.ReadonlyKeyword);
}
@@ -2751,7 +2754,7 @@ namespace ts {
node.typeParameter = parseMappedTypeParameter();
parseExpected(SyntaxKind.CloseBracketToken);
if (token() === SyntaxKind.QuestionToken || token() === SyntaxKind.PlusToken || token() === SyntaxKind.MinusToken) {
node.questionToken = parseTokenNode();
node.questionToken = parseTokenNode<QuestionToken | PlusToken | MinusToken>();
if (node.questionToken.kind !== SyntaxKind.QuestionToken) {
parseExpectedToken(SyntaxKind.QuestionToken);
}
@@ -2773,13 +2776,13 @@ namespace ts {
parseExpected(SyntaxKind.OpenParenToken);
node.type = parseType();
if (!node.type) {
return undefined;
return undefined!; // TODO: GH#18217
}
parseExpected(SyntaxKind.CloseParenToken);
return finishNode(node);
}
function parseFunctionOrConstructorType(kind: SyntaxKind): FunctionOrConstructorTypeNode {
function parseFunctionOrConstructorType(kind: SyntaxKind): FunctionOrConstructorTypeNode | undefined {
const node = <FunctionOrConstructorTypeNode>createNodeWithJSDoc(kind);
if (kind === SyntaxKind.ConstructorType) {
parseExpected(SyntaxKind.NewKeyword);
@@ -2800,7 +2803,7 @@ namespace ts {
function parseLiteralTypeNode(negative?: boolean): LiteralTypeNode {
const node = createNode(SyntaxKind.LiteralType) as LiteralTypeNode;
let unaryMinusExpression: PrefixUnaryExpression;
let unaryMinusExpression!: PrefixUnaryExpression;
if (negative) {
unaryMinusExpression = createNode(SyntaxKind.PrefixUnaryExpression) as PrefixUnaryExpression;
unaryMinusExpression.operator = SyntaxKind.MinusToken;
@@ -3129,10 +3132,10 @@ namespace ts {
function parseTypeWorker(noConditionalTypes?: boolean): TypeNode {
if (isStartOfFunctionType()) {
return parseFunctionOrConstructorType(SyntaxKind.FunctionType);
return parseFunctionOrConstructorType(SyntaxKind.FunctionType)!; // TODO: GH#18217
}
if (token() === SyntaxKind.NewKeyword) {
return parseFunctionOrConstructorType(SyntaxKind.ConstructorType);
return parseFunctionOrConstructorType(SyntaxKind.ConstructorType)!;
}
const type = parseUnionTypeOrHigher();
if (!noConditionalTypes && !scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind.ExtendsKeyword)) {
@@ -3149,7 +3152,7 @@ namespace ts {
return type;
}
function parseTypeAnnotation(): TypeNode {
function parseTypeAnnotation(): TypeNode | undefined {
return parseOptional(SyntaxKind.ColonToken) ? parseType() : undefined;
}
@@ -3373,7 +3376,7 @@ namespace ts {
}
}
function parseSimpleArrowFunctionExpression(identifier: Identifier, asyncModifier?: NodeArray<Modifier>): ArrowFunction {
function parseSimpleArrowFunctionExpression(identifier: Identifier, asyncModifier?: NodeArray<Modifier> | undefined): ArrowFunction {
Debug.assert(token() === SyntaxKind.EqualsGreaterThanToken, "parseSimpleArrowFunctionExpression should only have been called if we had a =>");
let node: ArrowFunction;
@@ -3572,7 +3575,7 @@ namespace ts {
}
}
function parsePossibleParenthesizedArrowFunctionExpressionHead(): ArrowFunction {
function parsePossibleParenthesizedArrowFunctionExpressionHead(): ArrowFunction | undefined {
return parseParenthesizedArrowFunctionExpressionHead(/*allowAmbiguity*/ false);
}
@@ -3609,7 +3612,7 @@ namespace ts {
return Tristate.False;
}
function parseParenthesizedArrowFunctionExpressionHead(allowAmbiguity: boolean): ArrowFunction {
function parseParenthesizedArrowFunctionExpressionHead(allowAmbiguity: boolean): ArrowFunction | undefined {
const node = <ArrowFunction>createNodeWithJSDoc(SyntaxKind.ArrowFunction);
node.modifiers = parseModifiersForArrowFunction();
const isAsync = hasModifier(node, ModifierFlags.Async) ? SignatureFlags.Await : SignatureFlags.None;
@@ -4208,7 +4211,7 @@ namespace ts {
badNode.end = invalidElement.end;
badNode.left = result;
badNode.right = invalidElement;
badNode.operatorToken = createMissingNode(SyntaxKind.CommaToken, /*reportAtCurrentPosition*/ false, /*diagnosticMessage*/ undefined);
badNode.operatorToken = createMissingNode(SyntaxKind.CommaToken, /*reportAtCurrentPosition*/ false, /*diagnosticMessage*/ undefined!); // TODO: GH#18217
badNode.operatorToken.pos = badNode.operatorToken.end = badNode.right.pos;
return <JsxElement><Node>badNode;
}
@@ -4902,7 +4905,7 @@ namespace ts {
const awaitToken = parseOptionalToken(SyntaxKind.AwaitKeyword);
parseExpected(SyntaxKind.OpenParenToken);
let initializer: VariableDeclarationList | Expression;
let initializer!: VariableDeclarationList | Expression;
if (token() !== SyntaxKind.SemicolonToken) {
if (token() === SyntaxKind.VarKeyword || token() === SyntaxKind.LetKeyword || token() === SyntaxKind.ConstKeyword) {
initializer = parseVariableDeclarationList(/*inForStatementInitializer*/ true);
@@ -5345,7 +5348,7 @@ namespace ts {
node.decorators = parseDecorators();
node.modifiers = parseModifiers();
if (some(node.modifiers, isDeclareModifier)) {
for (const m of node.modifiers) {
for (const m of node.modifiers!) {
m.flags |= NodeFlags.Ambient;
}
return doInsideOfContext(NodeFlags.Ambient, () => parseDeclarationWorker(node));
@@ -5398,6 +5401,7 @@ namespace ts {
missing.modifiers = node.modifiers;
return finishNode(missing);
}
return undefined!; // TODO: GH#18217
}
}
@@ -5406,7 +5410,7 @@ namespace ts {
return !scanner.hasPrecedingLineBreak() && (isIdentifier() || token() === SyntaxKind.StringLiteral);
}
function parseFunctionBlockOrSemicolon(flags: SignatureFlags, diagnosticMessage?: DiagnosticMessage): Block {
function parseFunctionBlockOrSemicolon(flags: SignatureFlags, diagnosticMessage?: DiagnosticMessage): Block | undefined {
if (token() !== SyntaxKind.OpenBraceToken && canParseSemicolon()) {
parseSemicolon();
return;
@@ -5484,7 +5488,7 @@ namespace ts {
node.name = parseIdentifierOrPattern();
if (allowExclamation && node.name.kind === SyntaxKind.Identifier &&
token() === SyntaxKind.ExclamationToken && !scanner.hasPrecedingLineBreak()) {
node.exclamationToken = parseTokenNode();
node.exclamationToken = parseTokenNode<Token<SyntaxKind.ExclamationToken>>();
}
node.type = parseTypeAnnotation();
if (!isInOrOfKeyword(token())) {
@@ -5580,7 +5584,7 @@ namespace ts {
function parsePropertyDeclaration(node: PropertyDeclaration): PropertyDeclaration {
node.kind = SyntaxKind.PropertyDeclaration;
if (!node.questionToken && token() === SyntaxKind.ExclamationToken && !scanner.hasPrecedingLineBreak()) {
node.exclamationToken = parseTokenNode();
node.exclamationToken = parseTokenNode<Token<SyntaxKind.ExclamationToken>>();
}
node.type = parseTypeAnnotation();
@@ -5622,7 +5626,7 @@ namespace ts {
}
function isClassMemberStart(): boolean {
let idToken: SyntaxKind;
let idToken: SyntaxKind | undefined;
if (token() === SyntaxKind.AtToken) {
return true;
@@ -5714,7 +5718,7 @@ namespace ts {
* In such situations, 'permitInvalidConstAsModifier' should be set to true.
*/
function parseModifiers(permitInvalidConstAsModifier?: boolean): NodeArray<Modifier> | undefined {
let list: Modifier[];
let list: Modifier[] | undefined;
const listPos = getNodePos();
while (true) {
const modifierStart = scanner.getStartPos();
@@ -5739,8 +5743,8 @@ namespace ts {
return list && createNodeArray(list, listPos);
}
function parseModifiersForArrowFunction(): NodeArray<Modifier> {
let modifiers: NodeArray<Modifier>;
function parseModifiersForArrowFunction(): NodeArray<Modifier> | undefined {
let modifiers: NodeArray<Modifier> | undefined;
if (token() === SyntaxKind.AsyncKeyword) {
const modifierStart = scanner.getStartPos();
const modifierKind = token();
@@ -5796,7 +5800,7 @@ namespace ts {
}
// 'isClassMemberStart' should have hinted not to attempt parsing.
Debug.fail("Should not have attempted to parse class member declaration.");
return Debug.fail("Should not have attempted to parse class member declaration.");
}
function parseClassExpression(): ClassExpression {
@@ -5853,17 +5857,14 @@ namespace ts {
return undefined;
}
function parseHeritageClause(): HeritageClause | undefined {
function parseHeritageClause(): HeritageClause {
const tok = token();
if (tok === SyntaxKind.ExtendsKeyword || tok === SyntaxKind.ImplementsKeyword) {
const node = <HeritageClause>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 = <HeritageClause>createNode(SyntaxKind.HeritageClause);
node.token = tok as SyntaxKind.ExtendsKeyword | SyntaxKind.ImplementsKeyword;
nextToken();
node.types = parseDelimitedList(ParsingContext.HeritageClauseElement, parseExpressionWithTypeArguments);
return finishNode(node);
}
function parseExpressionWithTypeArguments(): ExpressionWithTypeArguments {
@@ -6022,7 +6023,7 @@ namespace ts {
parseExpected(SyntaxKind.ImportKeyword);
const afterImportPos = scanner.getStartPos();
let identifier: Identifier;
let identifier: Identifier | undefined;
if (isIdentifier()) {
identifier = parseIdentifier();
if (token() !== SyntaxKind.CommaToken && token() !== SyntaxKind.FromKeyword) {
@@ -6056,7 +6057,7 @@ namespace ts {
return finishNode(node);
}
function parseImportClause(identifier: Identifier, fullStart: number) {
function parseImportClause(identifier: Identifier | undefined, fullStart: number) {
// ImportClause:
// ImportedDefaultBinding
// NameSpaceImport
@@ -6233,7 +6234,7 @@ namespace ts {
undefined;
}
function walkTreeForExternalModuleIndicators(node: Node): Node {
function walkTreeForExternalModuleIndicators(node: Node): Node | undefined {
return isImportMeta(node) ? node : forEachChild(node, walkTreeForExternalModuleIndicators);
}
@@ -6275,7 +6276,7 @@ namespace ts {
}
export namespace JSDocParser {
export function parseJSDocTypeExpressionForTests(content: string, start: number, length: number): { jsDocTypeExpression: JSDocTypeExpression, diagnostics: Diagnostic[] } | undefined {
export function parseJSDocTypeExpressionForTests(content: string, start: number | undefined, length: number | undefined): { jsDocTypeExpression: JSDocTypeExpression, diagnostics: Diagnostic[] } | undefined {
initializeState(content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS);
sourceFile = createSourceFile("file.js", ScriptTarget.Latest, ScriptKind.JS, /*isDeclarationFile*/ false);
scanner.setText(content, start, length);
@@ -6301,7 +6302,7 @@ namespace ts {
return finishNode(result);
}
export function parseIsolatedJSDocComment(content: string, start: number, length: number): { jsDoc: JSDoc, diagnostics: Diagnostic[] } | undefined {
export function parseIsolatedJSDocComment(content: string, start: number | undefined, length: number | undefined): { jsDoc: JSDoc, diagnostics: Diagnostic[] } | undefined {
initializeState(content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS);
sourceFile = <SourceFile>{ languageVariant: LanguageVariant.Standard, text: content }; // tslint:disable-line no-object-literal-type-assertion
const jsDoc = parseJSDocCommentWorker(start, length);
@@ -6311,7 +6312,7 @@ namespace ts {
return jsDoc ? { jsDoc, diagnostics } : undefined;
}
export function parseJSDocComment(parent: HasJSDoc, start: number, length: number): JSDoc {
export function parseJSDocComment(parent: HasJSDoc, start: number, length: number): JSDoc | undefined {
const saveToken = currentToken;
const saveParseDiagnosticsLength = parseDiagnostics.length;
const saveParseErrorBeforeNextFinishedNode = parseErrorBeforeNextFinishedNode;
@@ -6346,9 +6347,8 @@ namespace ts {
CallbackParameter = 1 << 2,
}
export function parseJSDocCommentWorker(start: number, length: number): JSDoc {
export function parseJSDocCommentWorker(start = 0, length: number | undefined): JSDoc | undefined {
const content = sourceText;
start = start || 0;
const end = length === undefined ? content.length : start + length;
length = end - start;
@@ -6360,7 +6360,7 @@ namespace ts {
let tagsPos: number;
let tagsEnd: number;
const comments: string[] = [];
let result: JSDoc;
let result: JSDoc | undefined;
// Check for /** (JSDoc opening part)
if (!isJSDocLikeText(content, start)) {
@@ -6518,7 +6518,7 @@ namespace ts {
return;
}
let tag: JSDocTag;
let tag: JSDocTag | undefined;
if (tagName) {
switch (tagName.escapedText) {
case "augments":
@@ -6638,7 +6638,7 @@ namespace ts {
return finishNode(result);
}
function addTag(tag: JSDocTag): void {
function addTag(tag: JSDocTag | undefined): void {
if (!tag) {
return;
}
@@ -6722,13 +6722,13 @@ namespace ts {
return finishNode(result);
}
function parseNestedTypeLiteral(typeExpression: JSDocTypeExpression, name: EntityName, target: PropertyLikeParse) {
function parseNestedTypeLiteral(typeExpression: JSDocTypeExpression | undefined, name: EntityName, target: PropertyLikeParse) {
if (typeExpression && isObjectOrObjectArrayTypeReference(typeExpression.type)) {
const typeLiteralExpression = <JSDocTypeExpression>createNode(SyntaxKind.JSDocTypeExpression, scanner.getTokenPos());
let child: JSDocPropertyLikeTag | JSDocTypeTag | false;
let jsdocTypeLiteral: JSDocTypeLiteral;
const start = scanner.getStartPos();
let children: JSDocPropertyLikeTag[];
let children: JSDocPropertyLikeTag[] | undefined;
while (child = tryParse(() => parseChildParameterOrPropertyTag(target, name))) {
if (child.kind === SyntaxKind.JSDocParameterTag || child.kind === SyntaxKind.JSDocPropertyTag) {
children = append(children, child);
@@ -6795,7 +6795,7 @@ namespace ts {
while (parseOptional(SyntaxKind.DotToken)) {
const prop: PropertyAccessEntityNameExpression = createNode(SyntaxKind.PropertyAccessExpression, node.pos) as PropertyAccessEntityNameExpression;
prop.expression = node;
prop.name = parseJSDocIdentifierName();
prop.name = parseJSDocIdentifierName()!; // TODO: GH#18217
node = finishNode(prop);
}
return node;
@@ -6821,11 +6821,11 @@ namespace ts {
typedefTag.comment = parseTagComments(indent);
typedefTag.typeExpression = typeExpression;
let end: number;
let end: number | undefined;
if (!typeExpression || isObjectOrObjectArrayTypeReference(typeExpression.type)) {
let child: JSDocTypeTag | JSDocPropertyTag | false;
let jsdocTypeLiteral: JSDocTypeLiteral;
let childTypeTag: JSDocTypeTag;
let jsdocTypeLiteral: JSDocTypeLiteral | undefined;
let childTypeTag: JSDocTypeTag | undefined;
const start = scanner.getStartPos();
while (child = tryParse(() => parseChildPropertyTag())) {
if (!jsdocTypeLiteral) {
@@ -6949,7 +6949,7 @@ namespace ts {
const child = tryParseChildTag(target);
if (child && child.kind === SyntaxKind.JSDocParameterTag &&
target !== PropertyLikeParse.CallbackParameter &&
(ts.isIdentifier(child.name) || !escapedTextsEqual(name, child.name.left))) {
(ts.isIdentifier(child.name) || !escapedTextsEqual(name!, child.name.left))) { // TODO: GH#18217
return false;
}
return child;
@@ -7219,7 +7219,7 @@ namespace ts {
forEachChild(node, visitNode, visitArray);
if (hasJSDocNodes(node)) {
for (const jsDocComment of node.jsDoc) {
for (const jsDocComment of node.jsDoc!) {
visitNode(<IncrementalNode><Node>jsDocComment);
}
}
@@ -7331,7 +7331,7 @@ namespace ts {
pos = child.end;
};
if (hasJSDocNodes(node)) {
for (const jsDocComment of node.jsDoc) {
for (const jsDocComment of node.jsDoc!) {
visitNode(jsDocComment);
}
}
@@ -7374,7 +7374,7 @@ namespace ts {
adjustIntersectingElement(child, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta);
forEachChild(child, visitNode, visitArray);
if (hasJSDocNodes(child)) {
for (const jsDocComment of child.jsDoc) {
for (const jsDocComment of child.jsDoc!) {
visitNode(<IncrementalNode><Node>jsDocComment);
}
}
@@ -7450,7 +7450,7 @@ namespace ts {
function findNearestNodeStartingBeforeOrAtPosition(sourceFile: SourceFile, position: number): Node {
let bestResult: Node = sourceFile;
let lastNodeEntirelyBeforePosition: Node;
let lastNodeEntirelyBeforePosition: Node | undefined;
forEachChild(sourceFile, visit);
@@ -7551,10 +7551,10 @@ namespace ts {
}
interface IncrementalElement extends TextRange {
parent?: Node;
parent: Node;
intersectsChange: boolean;
length?: number;
_children: Node[];
_children: Node[] | undefined;
}
export interface IncrementalNode extends Node, IncrementalElement {
@@ -7620,9 +7620,9 @@ namespace ts {
// return it, we can easily return its next sibling in the list.
function findHighestListElementThatStartsAtPosition(position: number) {
// Clear out any cached state about the last node we found.
currentArray = undefined;
currentArray = undefined!;
currentArrayIndex = InvalidPosition.Value;
current = undefined;
current = undefined!;
// Recurse into the source file to find the highest node at this position.
forEachChild(sourceFile, visitNode, visitArray);
@@ -7720,17 +7720,17 @@ namespace ts {
context.pragmas = createMap() as PragmaMap;
for (const pragma of pragmas) {
if (context.pragmas.has(pragma.name)) {
const currentValue = context.pragmas.get(pragma.name);
if (context.pragmas.has(pragma!.name)) { // TODO: GH#18217
const currentValue = context.pragmas.get(pragma!.name);
if (currentValue instanceof Array) {
currentValue.push(pragma.args);
currentValue.push(pragma!.args);
}
else {
context.pragmas.set(pragma.name, [currentValue, pragma.args]);
context.pragmas.set(pragma!.name, [currentValue, pragma!.args]);
}
continue;
}
context.pragmas.set(pragma.name, pragma.args);
context.pragmas.set(pragma!.name, pragma!.args);
}
}
@@ -7744,7 +7744,7 @@ namespace ts {
context.typeReferenceDirectives = [];
context.amdDependencies = [];
context.hasNoDefaultLib = false;
context.pragmas.forEach((entryOrList, key) => {
context.pragmas!.forEach((entryOrList, key) => { // TODO: GH#18217
// TODO: The below should be strongly type-guarded and not need casts/explicit annotations, since entryOrList is related to
// key and key is constrained to a union; but it's not (see GH#21483 for at least partial fix) :(
switch (key) {
@@ -7752,17 +7752,18 @@ namespace ts {
const referencedFiles = context.referencedFiles;
const typeReferenceDirectives = context.typeReferenceDirectives;
forEach(toArray(entryOrList), (arg: PragmaPsuedoMap["reference"]) => {
if (arg.arguments["no-default-lib"]) {
// TODO: GH#18217
if (arg!.arguments["no-default-lib"]) {
context.hasNoDefaultLib = true;
}
else if (arg.arguments.types) {
typeReferenceDirectives.push({ pos: arg.arguments.types.pos, end: arg.arguments.types.end, fileName: arg.arguments.types.value });
else if (arg!.arguments.types) {
typeReferenceDirectives.push({ pos: arg!.arguments.types!.pos, end: arg!.arguments.types!.end, fileName: arg!.arguments.types!.value });
}
else if (arg.arguments.path) {
referencedFiles.push({ pos: arg.arguments.path.pos, end: arg.arguments.path.end, fileName: arg.arguments.path.value });
else if (arg!.arguments.path) {
referencedFiles.push({ pos: arg!.arguments.path!.pos, end: arg!.arguments.path!.end, fileName: arg!.arguments.path!.value });
}
else {
reportDiagnostic(arg.range.pos, arg.range.end - arg.range.pos, Diagnostics.Invalid_reference_directive_syntax);
reportDiagnostic(arg!.range.pos, arg!.range.end - arg!.range.pos, Diagnostics.Invalid_reference_directive_syntax);
}
});
break;
@@ -7770,8 +7771,7 @@ namespace ts {
case "amd-dependency": {
context.amdDependencies = map(
toArray(entryOrList),
({ arguments: { name, path } }: PragmaPsuedoMap["amd-dependency"]) => ({ name, path })
);
(x: PragmaPsuedoMap["amd-dependency"]) => ({ name: x!.arguments.name!, path: x!.arguments.path })); // TODO: GH#18217
break;
}
case "amd-module": {
@@ -7779,13 +7779,13 @@ namespace ts {
for (const entry of entryOrList) {
if (context.moduleName) {
// TODO: It's probably fine to issue this diagnostic on all instances of the pragma
reportDiagnostic(entry.range.pos, entry.range.end - entry.range.pos, Diagnostics.An_AMD_module_cannot_have_multiple_name_assignments);
reportDiagnostic(entry!.range.pos, entry!.range.end - entry!.range.pos, Diagnostics.An_AMD_module_cannot_have_multiple_name_assignments);
}
context.moduleName = (entry as PragmaPsuedoMap["amd-module"]).arguments.name;
context.moduleName = (entry as PragmaPsuedoMap["amd-module"])!.arguments.name;
}
}
else {
context.moduleName = (entryOrList as PragmaPsuedoMap["amd-module"]).arguments.name;
context.moduleName = (entryOrList as PragmaPsuedoMap["amd-module"])!.arguments.name;
}
break;
}
@@ -7793,11 +7793,11 @@ namespace ts {
case "ts-check": {
// _last_ of either nocheck or check in a file is the "winner"
forEach(toArray(entryOrList), entry => {
if (!context.checkJsDirective || entry.range.pos > context.checkJsDirective.pos) {
if (!context.checkJsDirective || entry!.range.pos > context.checkJsDirective.pos) { // TODO: GH#18217
context.checkJsDirective = {
enabled: key === "ts-check",
end: entry.range.end,
pos: entry.range.pos
end: entry!.range.end,
pos: entry!.range.pos
};
}
});
@@ -7810,9 +7810,9 @@ namespace ts {
}
const namedArgRegExCache = createMap<RegExp>();
function getNamedArgRegEx(name: string) {
function getNamedArgRegEx(name: string): RegExp {
if (namedArgRegExCache.has(name)) {
return namedArgRegExCache.get(name);
return namedArgRegExCache.get(name)!;
}
const result = new RegExp(`(\\s${name}\\s*=\\s*)('|")(.+?)\\2`, "im");
namedArgRegExCache.set(name, result);
@@ -7826,7 +7826,7 @@ namespace ts {
if (tripleSlash) {
const name = tripleSlash[1].toLowerCase() as keyof PragmaPsuedoMap; // Technically unsafe cast, but we do it so the below check to make it safe typechecks
const pragma = commentPragmas[name] as PragmaDefinition;
if (!pragma || !(pragma.kind & PragmaKindFlags.TripleSlashXML)) {
if (!pragma || !(pragma.kind! & PragmaKindFlags.TripleSlashXML)) {
return;
}
if (pragma.args) {
@@ -7866,7 +7866,7 @@ namespace ts {
if (range.kind === SyntaxKind.MultiLineCommentTrivia) {
const multiLinePragmaRegEx = /\s*@(\S+)\s*(.*)\s*$/gim; // Defined inline since it uses the "g" flag, which keeps a persistent index (for iterating)
let multiLineMatch: RegExpExecArray;
let multiLineMatch: RegExpExecArray | null;
while (multiLineMatch = multiLinePragmaRegEx.exec(text)) {
addPragmaForMatch(pragmas, range, PragmaKindFlags.MultiLine, multiLineMatch);
}
@@ -7877,7 +7877,7 @@ namespace ts {
if (!match) return;
const name = match[1].toLowerCase() as keyof PragmaPsuedoMap; // Technically unsafe cast, but we do it so they below check to make it safe typechecks
const pragma = commentPragmas[name] as PragmaDefinition;
if (!pragma || !(pragma.kind & kind)) {
if (!pragma || !(pragma.kind! & kind)) {
return;
}
const args = match[2]; // Split on spaces and match up positionally with definition
+1 -1
View File
@@ -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*/
Regular → Executable
+92 -91
View File
@@ -16,7 +16,7 @@ namespace ts {
/* @internal */
export function computeCommonSourceDirectoryOfFilenames(fileNames: string[], currentDirectory: string, getCanonicalFileName: GetCanonicalFileName): string {
let commonPathComponents: string[];
let commonPathComponents: string[] | undefined;
const failed = forEach(fileNames, sourceFile => {
// Each file contributes into common source file path
const sourcePathComponents = getNormalizedPathComponents(sourceFile, currentDirectory);
@@ -75,8 +75,8 @@ namespace ts {
return sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
}
function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile {
let text: string;
function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile | undefined {
let text: string | undefined;
try {
performance.mark("beforeIORead");
text = sys.readFile(fileName, options.charset);
@@ -119,8 +119,8 @@ namespace ts {
outputFingerprints = createMap<OutputFingerprint>();
}
const hash = sys.createHash(data);
const mtimeBefore = sys.getModifiedTime(fileName);
const hash = sys.createHash!(data); // TODO: GH#18217
const mtimeBefore = sys.getModifiedTime!(fileName); // TODO: GH#18217
if (mtimeBefore) {
const fingerprint = outputFingerprints.get(fileName);
@@ -135,7 +135,7 @@ namespace ts {
sys.writeFile(fileName, data, writeByteOrderMark);
const mtimeAfter = sys.getModifiedTime(fileName);
const mtimeAfter = sys.getModifiedTime!(fileName); // TODO: GH#18217
outputFingerprints.set(fileName, {
hash,
@@ -171,7 +171,7 @@ namespace ts {
}
const newLine = getNewLineCharacter(options);
const realpath = sys.realpath && ((path: string) => sys.realpath(path));
const realpath = sys.realpath && ((path: string) => sys.realpath!(path));
return {
getSourceFile,
@@ -228,7 +228,7 @@ namespace ts {
const errorMessage = `${diagnosticCategoryName(diagnostic)} TS${diagnostic.code}: ${flattenDiagnosticMessageText(diagnostic.messageText, host.getNewLine())}${host.getNewLine()}`;
if (diagnostic.file) {
const { line, character } = getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start);
const { line, character } = getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start!); // TODO: GH#18217
const fileName = diagnostic.file.fileName;
const relativeFileName = convertToRelativePath(fileName, host.getCurrentDirectory(), fileName => host.getCanonicalFileName(fileName));
return `${relativeFileName}(${line + 1},${character + 1}): ` + errorMessage;
@@ -276,8 +276,8 @@ namespace ts {
let context = "";
if (diagnostic.file) {
const { start, length, file } = diagnostic;
const { line: firstLine, character: firstLineChar } = getLineAndCharacterOfPosition(file, start);
const { line: lastLine, character: lastLineChar } = getLineAndCharacterOfPosition(file, start + length);
const { line: firstLine, character: firstLineChar } = getLineAndCharacterOfPosition(file, start!); // TODO: GH#18217
const { line: lastLine, character: lastLineChar } = getLineAndCharacterOfPosition(file, start! + length!);
const lastLineInFile = getLineAndCharacterOfPosition(file, file.text.length).line;
const relativeFileName = host ? convertToRelativePath(file.fileName, host.getCurrentDirectory(), fileName => host.getCanonicalFileName(fileName)) : file.fileName;
@@ -349,7 +349,7 @@ namespace ts {
return output + host.getNewLine();
}
export function flattenDiagnosticMessageText(messageText: string | DiagnosticMessageChain, newLine: string): string {
export function flattenDiagnosticMessageText(messageText: string | DiagnosticMessageChain | undefined, newLine: string): string {
if (isString(messageText)) {
return messageText;
}
@@ -384,7 +384,7 @@ namespace ts {
for (const name of names) {
let result: T;
if (cache.has(name)) {
result = cache.get(name);
result = cache.get(name)!;
}
else {
cache.set(name, result = loader(name, containingFile));
@@ -407,7 +407,7 @@ namespace ts {
program: Program | undefined,
rootFileNames: string[],
newOptions: CompilerOptions,
getSourceVersion: (path: Path) => string,
getSourceVersion: (path: Path) => string | undefined,
fileExists: (fileName: string) => boolean,
hasInvalidatedResolution: HasInvalidatedResolution,
hasChangedAutomaticTypeDirectiveNames: boolean,
@@ -461,7 +461,7 @@ namespace ts {
/**
* Determined if source file needs to be re-created even if its text hasn't changed
*/
function shouldProgramCreateNewSourceFiles(program: Program, newOptions: CompilerOptions) {
function shouldProgramCreateNewSourceFiles(program: Program | undefined, newOptions: CompilerOptions) {
// If any of these options change, we can't reuse old source file even if version match
// The change in options like these could result in change in syntax tree change
const oldOptions = program && program.getCompilerOptions();
@@ -505,9 +505,9 @@ namespace ts {
export function createProgram(createProgramOptions: CreateProgramOptions): Program;
export function createProgram(rootNames: ReadonlyArray<string>, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): Program;
export function createProgram(rootNamesOrOptions: ReadonlyArray<string> | CreateProgramOptions, _options?: CompilerOptions, _host?: CompilerHost, _oldProgram?: Program, _configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): Program {
const createProgramOptions = isArray(rootNamesOrOptions) ? createCreateProgramOptions(rootNamesOrOptions, _options, _host, _oldProgram, _configFileParsingDiagnostics) : rootNamesOrOptions;
const createProgramOptions = isArray(rootNamesOrOptions) ? createCreateProgramOptions(rootNamesOrOptions, _options!, _host, _oldProgram, _configFileParsingDiagnostics) : rootNamesOrOptions; // TODO: GH#18217
const { rootNames, options, configFileParsingDiagnostics, projectReferences } = createProgramOptions;
let { host, oldProgram } = createProgramOptions;
let { oldProgram } = createProgramOptions;
let program: Program;
let files: SourceFile[] = [];
@@ -542,7 +542,7 @@ namespace ts {
performance.mark("beforeProgram");
host = host || createCompilerHost(options);
const host = createProgramOptions.host || createCompilerHost(options);
const configParsingHost = parseConfigHostFromCompilerHost(host);
let skipDefaultLib = options.noLib;
@@ -554,14 +554,14 @@ namespace ts {
// Map storing if there is emit blocking diagnostics for given input
const hasEmitBlockingDiagnostics = createMap<boolean>();
let _compilerOptionsObjectLiteralSyntax: ObjectLiteralExpression;
let _referencesArrayLiteralSyntax: ArrayLiteralExpression;
let _compilerOptionsObjectLiteralSyntax: ObjectLiteralExpression | null | undefined;
let _referencesArrayLiteralSyntax: ArrayLiteralExpression | null | undefined;
let moduleResolutionCache: ModuleResolutionCache;
let moduleResolutionCache: ModuleResolutionCache | undefined;
let resolveModuleNamesWorker: (moduleNames: string[], containingFile: string, reusedNames?: string[]) => ResolvedModuleFull[];
const hasInvalidatedResolution = host.hasInvalidatedResolution || returnFalse;
if (host.resolveModuleNames) {
resolveModuleNamesWorker = (moduleNames, containingFile, reusedNames) => host.resolveModuleNames(Debug.assertEachDefined(moduleNames), containingFile, reusedNames).map(resolved => {
resolveModuleNamesWorker = (moduleNames, containingFile, reusedNames) => host.resolveModuleNames!(Debug.assertEachDefined(moduleNames), containingFile, reusedNames).map(resolved => {
// An older host may have omitted extension, in which case we should infer it from the file extension of resolvedFileName.
if (!resolved || (resolved as ResolvedModuleFull).extension !== undefined) {
return resolved as ResolvedModuleFull;
@@ -573,17 +573,17 @@ namespace ts {
}
else {
moduleResolutionCache = createModuleResolutionCache(currentDirectory, x => host.getCanonicalFileName(x));
const loader = (moduleName: string, containingFile: string) => resolveModuleName(moduleName, containingFile, options, host, moduleResolutionCache).resolvedModule;
resolveModuleNamesWorker = (moduleNames, containingFile) => loadWithLocalCache(Debug.assertEachDefined(moduleNames), containingFile, loader);
const loader = (moduleName: string, containingFile: string) => resolveModuleName(moduleName, containingFile, options, host, moduleResolutionCache).resolvedModule!; // TODO: GH#18217
resolveModuleNamesWorker = (moduleNames, containingFile) => loadWithLocalCache<ResolvedModuleFull>(Debug.assertEachDefined(moduleNames), containingFile, loader);
}
let resolveTypeReferenceDirectiveNamesWorker: (typeDirectiveNames: string[], containingFile: string) => ResolvedTypeReferenceDirective[];
if (host.resolveTypeReferenceDirectives) {
resolveTypeReferenceDirectiveNamesWorker = (typeDirectiveNames, containingFile) => host.resolveTypeReferenceDirectives(Debug.assertEachDefined(typeDirectiveNames), containingFile);
resolveTypeReferenceDirectiveNamesWorker = (typeDirectiveNames, containingFile) => host.resolveTypeReferenceDirectives!(Debug.assertEachDefined(typeDirectiveNames), containingFile);
}
else {
const loader = (typesRef: string, containingFile: string) => resolveTypeReferenceDirective(typesRef, containingFile, options, host).resolvedTypeReferenceDirective;
resolveTypeReferenceDirectiveNamesWorker = (typeReferenceDirectiveNames, containingFile) => loadWithLocalCache(Debug.assertEachDefined(typeReferenceDirectiveNames), containingFile, loader);
const loader = (typesRef: string, containingFile: string) => resolveTypeReferenceDirective(typesRef, containingFile, options, host).resolvedTypeReferenceDirective!; // TODO: GH#18217
resolveTypeReferenceDirectiveNamesWorker = (typeReferenceDirectiveNames, containingFile) => loadWithLocalCache<ResolvedTypeReferenceDirective>(Debug.assertEachDefined(typeReferenceDirectiveNames), containingFile, loader);
}
// Map from a stringified PackageId to the source file with that id.
@@ -595,7 +595,7 @@ namespace ts {
let redirectTargetsSet = createMap<true>();
const filesByName = createMap<SourceFile | undefined>();
let missingFilePaths: ReadonlyArray<Path>;
let missingFilePaths: ReadonlyArray<Path> | undefined;
// stores 'filename -> file association' ignoring case
// used to track cases when two file names differ only in casing
const filesByNameIgnoreCase = host.useCaseSensitiveFileNames() ? createMap<SourceFile>() : undefined;
@@ -606,7 +606,7 @@ namespace ts {
if (projectReferences) {
for (const ref of projectReferences) {
const parsedRef = parseProjectReferenceConfigFile(ref);
resolvedProjectReferences.push(parsedRef);
resolvedProjectReferences!.push(parsedRef);
if (parsedRef) {
if (parsedRef.commandLine.options.outFile) {
const dtsOutfile = changeExtension(parsedRef.commandLine.options.outFile, ".d.ts");
@@ -677,7 +677,7 @@ namespace ts {
getSourceFile,
getSourceFileByPath,
getSourceFiles: () => files,
getMissingFilePaths: () => missingFilePaths,
getMissingFilePaths: () => missingFilePaths!, // TODO: GH#18217
getCompilerOptions: () => options,
getSyntacticDiagnostics,
getOptionsDiagnostics,
@@ -714,7 +714,7 @@ namespace ts {
return program;
function getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string): ResolvedModuleWithFailedLookupLocations {
function getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string): ResolvedModuleWithFailedLookupLocations | undefined {
return moduleResolutionCache && resolveModuleNameFromCache(moduleName, containingFile, moduleResolutionCache);
}
@@ -731,7 +731,7 @@ namespace ts {
}
else if (options.composite) {
// Project compilations never infer their root from the input source paths
commonSourceDirectory = getDirectoryPath(normalizeSlashes(options.configFilePath));
commonSourceDirectory = getDirectoryPath(normalizeSlashes(options.configFilePath!)); // TODO: GH#18217
checkSourceFilesBelongToPath(emittedFiles, commonSourceDirectory);
}
else {
@@ -755,7 +755,7 @@ namespace ts {
classifiableNames = createUnderscoreEscapedMap<true>();
for (const sourceFile of files) {
copyEntries(sourceFile.classifiableNames, classifiableNames);
copyEntries(sourceFile.classifiableNames!, classifiableNames);
}
}
@@ -766,7 +766,7 @@ namespace ts {
program: Program | undefined;
oldSourceFile: SourceFile | undefined;
/** The collection of paths modified *since* the old program. */
modifiedFilePaths: Path[];
modifiedFilePaths: Path[] | undefined;
}
function resolveModuleNamesReusingOldState(moduleNames: string[], containingFile: string, file: SourceFile, oldProgramState: OldProgramState) {
@@ -788,7 +788,7 @@ namespace ts {
// it is safe to reuse resolutions from the earlier call.
const result: ResolvedModuleFull[] = [];
for (const moduleName of moduleNames) {
const resolvedModule = file.resolvedModules.get(moduleName);
const resolvedModule = file.resolvedModules.get(moduleName)!;
result.push(resolvedModule);
}
return result;
@@ -799,7 +799,7 @@ namespace ts {
// With this information, we can infer some module resolutions without performing resolution.
/** An ordered list of module names for which we cannot recover the resolution. */
let unknownModuleNames: string[];
let unknownModuleNames: string[] | undefined;
/**
* The indexing of elements in this list matches that of `moduleNames`.
*
@@ -809,8 +809,8 @@ namespace ts {
* Needs to be reset to undefined before returning,
* * ResolvedModuleFull instance: can be reused.
*/
let result: ResolvedModuleFull[];
let reusedNames: string[];
let result: ResolvedModuleFull[] | undefined;
let reusedNames: string[] | undefined;
/** A transient placeholder used to mark predicted resolution in the result list. */
const predictedToResolveToAmbientModuleMarker: ResolvedModuleFull = <any>{};
@@ -818,7 +818,7 @@ namespace ts {
const moduleName = moduleNames[i];
// If the source file is unchanged and doesnt have invalidated resolution, reuse the module resolutions
if (file === oldSourceFile && !hasInvalidatedResolution(oldSourceFile.path)) {
const oldResolvedModule = oldSourceFile && oldSourceFile.resolvedModules.get(moduleName);
const oldResolvedModule = oldSourceFile && oldSourceFile.resolvedModules!.get(moduleName);
if (oldResolvedModule) {
if (isTraceEnabled(options, host)) {
trace(host, Diagnostics.Reusing_resolution_of_module_0_to_file_1_from_old_program, moduleName, containingFile);
@@ -869,7 +869,7 @@ namespace ts {
// `result[i]` is either a `ResolvedModuleFull` or a marker.
// If it is the former, we can leave it as is.
if (result[i] === predictedToResolveToAmbientModuleMarker) {
result[i] = undefined;
result[i] = undefined!; // TODO: GH#18217
}
}
else {
@@ -884,7 +884,7 @@ namespace ts {
// If we change our policy of rechecking failed lookups on each program create,
// we should adjust the value returned here.
function moduleNameResolvesToAmbientModuleInNonModifiedFile(moduleName: string, oldProgramState: OldProgramState): boolean {
const resolutionToFile = getResolvedModule(oldProgramState.oldSourceFile, moduleName);
const resolutionToFile = getResolvedModule(oldProgramState.oldSourceFile!, moduleName); // TODO: GH#18217
const resolvedFile = resolutionToFile && oldProgramState.program && oldProgramState.program.getSourceFile(resolutionToFile.resolvedFileName);
if (resolutionToFile && resolvedFile && !resolvedFile.externalModuleIndicator) {
// In the old program, we resolved to an ambient module that was in the same
@@ -927,7 +927,7 @@ namespace ts {
return oldProgram.structureIsReused = StructureIsReused.Not;
}
Debug.assert(!(oldProgram.structureIsReused & (StructureIsReused.Completely | StructureIsReused.SafeModules)));
Debug.assert(!(oldProgram.structureIsReused! & (StructureIsReused.Completely | StructureIsReused.SafeModules)));
// there is an old program, check if we can reuse its structure
const oldRootNames = oldProgram.getRootFileNames();
@@ -987,8 +987,8 @@ namespace ts {
for (const oldSourceFile of oldSourceFiles) {
let newSourceFile = host.getSourceFileByPath
? host.getSourceFileByPath(oldSourceFile.fileName, oldSourceFile.path, options.target, /*onError*/ undefined, shouldCreateNewSourceFile)
: host.getSourceFile(oldSourceFile.fileName, options.target, /*onError*/ undefined, shouldCreateNewSourceFile);
? host.getSourceFileByPath(oldSourceFile.fileName, oldSourceFile.path, options.target!, /*onError*/ undefined, shouldCreateNewSourceFile)
: host.getSourceFile(oldSourceFile.fileName, options.target!, /*onError*/ undefined, shouldCreateNewSourceFile); // TODO: GH#18217
if (!newSourceFile) {
return oldProgram.structureIsReused = StructureIsReused.Not;
@@ -1134,7 +1134,7 @@ namespace ts {
for (let i = 0; i < newSourceFiles.length; i++) {
filesByName.set(filePaths[i], newSourceFiles[i]);
// Set the file as found during node modules search if it was found that way in old progra,
if (oldProgram.isSourceFileFromExternalLibrary(oldProgram.getSourceFileByPath(filePaths[i]))) {
if (oldProgram.isSourceFileFromExternalLibrary(oldProgram.getSourceFileByPath(filePaths[i])!)) {
sourceFilesFoundSearchingNodeModules.set(filePaths[i], true);
}
}
@@ -1185,7 +1185,7 @@ namespace ts {
const nodes: InputFiles[] = [];
for (let i = 0; i < projectReferences.length; i++) {
const ref = projectReferences[i];
const resolvedRefOpts = resolvedProjectReferences[i].commandLine;
const resolvedRefOpts = resolvedProjectReferences![i]!.commandLine;
if (ref.prepend && resolvedRefOpts && resolvedRefOpts.options) {
// Upstream project didn't have outFile set -- skip (error will have been issued earlier)
if (!resolvedRefOpts.options.outFile) continue;
@@ -1201,7 +1201,7 @@ namespace ts {
}
function isSourceFileFromExternalLibrary(file: SourceFile): boolean {
return sourceFilesFoundSearchingNodeModules.get(file.path);
return !!sourceFilesFoundSearchingNodeModules.get(file.path);
}
function isSourceFileDefaultLibrary(file: SourceFile): boolean {
@@ -1220,7 +1220,7 @@ namespace ts {
return equalityComparer(file.fileName, getDefaultLibraryFileName());
}
else {
return forEach(options.lib, libFileName => equalityComparer(file.fileName, combinePaths(defaultLibraryPath, libFileName)));
return some(options.lib, libFileName => equalityComparer(file.fileName, combinePaths(defaultLibraryPath, libFileName)));
}
}
@@ -1229,7 +1229,7 @@ namespace ts {
}
function dropDiagnosticsProducingTypeChecker() {
diagnosticsProducingTypeChecker = undefined;
diagnosticsProducingTypeChecker = undefined!;
}
function getTypeChecker() {
@@ -1244,7 +1244,7 @@ namespace ts {
return hasEmitBlockingDiagnostics.has(toPath(emitFileName));
}
function emitWorker(program: Program, sourceFile: SourceFile, writeFileCallback: WriteFileCallback, cancellationToken: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult {
function emitWorker(program: Program, sourceFile: SourceFile | undefined, writeFileCallback: WriteFileCallback | undefined, cancellationToken: CancellationToken | undefined, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult {
let declarationDiagnostics: ReadonlyArray<Diagnostic> = [];
if (!emitOnlyDtsFiles) {
@@ -1294,7 +1294,7 @@ namespace ts {
const emitResult = emitFiles(
emitResolver,
getEmitHost(writeFileCallback),
sourceFile,
sourceFile!, // TODO: GH#18217
emitOnlyDtsFiles,
transformers,
customTransformers && customTransformers.afterDeclarations
@@ -1374,8 +1374,8 @@ namespace ts {
// cancel when the user has made a change anyways. And, in that case, we (the
// program instance) will get thrown away anyways. So trying to keep one of
// these type checkers alive doesn't serve much purpose.
noDiagnosticsTypeChecker = undefined;
diagnosticsProducingTypeChecker = undefined;
noDiagnosticsTypeChecker = undefined!;
diagnosticsProducingTypeChecker = undefined!;
}
throw e;
@@ -1386,7 +1386,7 @@ namespace ts {
return getAndCacheDiagnostics(sourceFile, cancellationToken, cachedSemanticDiagnosticsForFile, getSemanticDiagnosticsForFileNoCache);
}
function getSemanticDiagnosticsForFileNoCache(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] {
function getSemanticDiagnosticsForFileNoCache(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] | undefined {
return runWithCancellationToken(() => {
// If skipLibCheck is enabled, skip reporting errors if file is a declaration file.
// If skipDefaultLibCheck is enabled, skip reporting errors if file contains a
@@ -1429,7 +1429,7 @@ namespace ts {
const { file, start } = diagnostic;
if (file) {
const lineStarts = getLineStarts(file);
let { line } = computeLineAndCharacterOfPosition(lineStarts, start);
let { line } = computeLineAndCharacterOfPosition(lineStarts, start!); // TODO: GH#18217
while (line > 0) {
const previousLineText = file.text.slice(lineStarts[line - 1], lineStarts[line]);
const result = ignoreDiagnosticCommentRegEx.exec(previousLineText);
@@ -1646,7 +1646,7 @@ namespace ts {
sourceFile: SourceFile | undefined,
cancellationToken: CancellationToken,
cache: DiagnosticCache<T>,
getDiagnostics: (sourceFile: SourceFile, cancellationToken: CancellationToken) => T[],
getDiagnostics: (sourceFile: SourceFile, cancellationToken: CancellationToken) => T[] | undefined,
): ReadonlyArray<T> {
const cachedResult = sourceFile
@@ -1656,7 +1656,7 @@ namespace ts {
if (cachedResult) {
return cachedResult;
}
const result = getDiagnostics(sourceFile, cancellationToken) || emptyArray;
const result = getDiagnostics(sourceFile!, cancellationToken) || emptyArray; // TODO: GH#18217
if (sourceFile) {
if (!cache.perFile) {
cache.perFile = createMap<T[]>();
@@ -1715,8 +1715,8 @@ namespace ts {
// file.imports may not be undefined if there exists dynamic import
let imports: StringLiteralLike[] | undefined;
let moduleAugmentations: (StringLiteral | Identifier)[];
let ambientModules: string[];
let moduleAugmentations: (StringLiteral | Identifier)[] | undefined;
let ambientModules: string[] | undefined;
// If we are importing helpers, we need to add a synthetic reference to resolve the
// helpers library.
@@ -1867,7 +1867,7 @@ namespace ts {
/** This has side effects through `findSourceFile`. */
function processSourceFile(fileName: string, isDefaultLib: boolean, packageId: PackageId | undefined, refFile?: SourceFile, refPos?: number, refEnd?: number): void {
getSourceFileFromReferenceWorker(fileName,
fileName => findSourceFile(fileName, toPath(fileName), isDefaultLib, refFile, refPos, refEnd, packageId),
fileName => findSourceFile(fileName, toPath(fileName), isDefaultLib, refFile!, refPos!, refEnd!, packageId), // TODO: GH#18217
(diagnostic, ...args) => {
fileProcessingDiagnostics.add(refFile !== undefined && refEnd !== undefined && refPos !== undefined
? createFileDiagnostic(refFile, refPos, refEnd - refPos, diagnostic, ...args)
@@ -1893,12 +1893,12 @@ namespace ts {
redirect.redirectInfo = { redirectTarget, unredirected };
Object.defineProperties(redirect, {
id: {
get(this: SourceFile) { return this.redirectInfo.redirectTarget.id; },
set(this: SourceFile, value: SourceFile["id"]) { this.redirectInfo.redirectTarget.id = value; },
get(this: SourceFile) { return this.redirectInfo!.redirectTarget.id; },
set(this: SourceFile, value: SourceFile["id"]) { this.redirectInfo!.redirectTarget.id = value; },
},
symbol: {
get(this: SourceFile) { return this.redirectInfo.redirectTarget.symbol; },
set(this: SourceFile, value: SourceFile["symbol"]) { this.redirectInfo.redirectTarget.symbol = value; },
get(this: SourceFile) { return this.redirectInfo!.redirectTarget.symbol; },
set(this: SourceFile, value: SourceFile["symbol"]) { this.redirectInfo!.redirectTarget.symbol = value; },
},
});
return redirect;
@@ -1953,7 +1953,7 @@ namespace ts {
}
// We haven't looked for this file, do so now and cache result
const file = host.getSourceFile(fileName, options.target, hostErrorMessage => {
const file = host.getSourceFile(fileName, options.target!, hostErrorMessage => { // TODO: GH#18217
if (refFile !== undefined && refPos !== undefined && refEnd !== undefined) {
fileProcessingDiagnostics.add(createFileDiagnostic(refFile, refPos, refEnd - refPos,
Diagnostics.Cannot_read_file_0_Colon_1, fileName, hostErrorMessage));
@@ -1969,7 +1969,7 @@ namespace ts {
if (fileFromPackageId) {
// Some other SourceFile already exists with this package name and version.
// Instead of creating a duplicate, just redirect to the existing one.
const dupFile = createRedirectSourceFile(fileFromPackageId, file, fileName, path);
const dupFile = createRedirectSourceFile(fileFromPackageId, file!, fileName, path); // TODO: GH#18217
redirectTargetsSet.set(fileFromPackageId.path, true);
filesByName.set(path, dupFile);
sourceFileToPackageName.set(path, packageId.name);
@@ -1995,12 +1995,12 @@ namespace ts {
if (host.useCaseSensitiveFileNames()) {
const pathLowerCase = path.toLowerCase();
// for case-sensitive file systems check if we've already seen some file with similar filename ignoring case
const existingFile = filesByNameIgnoreCase.get(pathLowerCase);
const existingFile = filesByNameIgnoreCase!.get(pathLowerCase);
if (existingFile) {
reportFileNamesDifferOnlyInCasingError(fileName, existingFile.fileName, refFile, refPos, refEnd);
}
else {
filesByNameIgnoreCase.set(pathLowerCase, file);
filesByNameIgnoreCase!.set(pathLowerCase, file);
}
}
@@ -2080,7 +2080,7 @@ namespace ts {
if (resolvedTypeReferenceDirective) {
if (resolvedTypeReferenceDirective.primary) {
// resolved from the primary path
processSourceFile(resolvedTypeReferenceDirective.resolvedFileName, /*isDefaultLib*/ false, resolvedTypeReferenceDirective.packageId, refFile, refPos, refEnd);
processSourceFile(resolvedTypeReferenceDirective.resolvedFileName!, /*isDefaultLib*/ false, resolvedTypeReferenceDirective.packageId, refFile, refPos, refEnd); // TODO: GH#18217
}
else {
// If we already resolved to this file, it must have been a secondary reference. Check file contents
@@ -2088,9 +2088,9 @@ namespace ts {
if (previousResolution) {
// Don't bother reading the file again if it's the same file.
if (resolvedTypeReferenceDirective.resolvedFileName !== previousResolution.resolvedFileName) {
const otherFileText = host.readFile(resolvedTypeReferenceDirective.resolvedFileName);
if (otherFileText !== getSourceFile(previousResolution.resolvedFileName).text) {
fileProcessingDiagnostics.add(createDiagnostic(refFile, refPos, refEnd,
const otherFileText = host.readFile(resolvedTypeReferenceDirective.resolvedFileName!);
if (otherFileText !== getSourceFile(previousResolution.resolvedFileName!)!.text) {
fileProcessingDiagnostics.add(createDiagnostic(refFile!, refPos!, refEnd!, // TODO: GH#18217
Diagnostics.Conflicting_definitions_for_0_found_at_1_and_2_Consider_installing_a_specific_version_of_this_library_to_resolve_the_conflict,
typeReferenceDirective,
resolvedTypeReferenceDirective.resolvedFileName,
@@ -2103,12 +2103,12 @@ namespace ts {
}
else {
// First resolution of this library
processSourceFile(resolvedTypeReferenceDirective.resolvedFileName, /*isDefaultLib*/ false, resolvedTypeReferenceDirective.packageId, refFile, refPos, refEnd);
processSourceFile(resolvedTypeReferenceDirective.resolvedFileName!, /*isDefaultLib*/ false, resolvedTypeReferenceDirective.packageId, refFile, refPos, refEnd);
}
}
}
else {
fileProcessingDiagnostics.add(createDiagnostic(refFile, refPos, refEnd, Diagnostics.Cannot_find_type_definition_file_for_0, typeReferenceDirective));
fileProcessingDiagnostics.add(createDiagnostic(refFile!, refPos!, refEnd!, Diagnostics.Cannot_find_type_definition_file_for_0, typeReferenceDirective)); // TODO: GH#18217
}
if (saveResolution) {
@@ -2221,7 +2221,7 @@ namespace ts {
function parseProjectReferenceConfigFile(ref: ProjectReference): { commandLine: ParsedCommandLine, sourceFile: SourceFile } | undefined {
// The actual filename (i.e. add "/tsconfig.json" if necessary)
const refPath = resolveProjectReferencePath(host, ref);
const refPath = resolveProjectReferencePath(host, ref)!; // TODO: GH#18217
// An absolute path pointing to the containing directory of the config file
const basePath = getNormalizedAbsolutePath(getDirectoryPath(refPath), host.getCurrentDirectory());
const sourceFile = host.getSourceFile(refPath, ScriptTarget.JSON) as JsonSourceFile;
@@ -2234,14 +2234,14 @@ namespace ts {
}
function addProjectReferenceRedirects(referencedProject: ParsedCommandLine, target: Map<string>) {
const rootDir = normalizePath(referencedProject.options.rootDir || getDirectoryPath(referencedProject.options.configFilePath));
const rootDir = normalizePath(referencedProject.options.rootDir || getDirectoryPath(referencedProject.options.configFilePath!)); // TODO: GH#18217
target.set(rootDir, getDeclarationOutputDirectory(referencedProject));
}
function getDeclarationOutputDirectory(proj: ParsedCommandLine) {
return proj.options.declarationDir ||
proj.options.outDir ||
getDirectoryPath(proj.options.configFilePath);
getDirectoryPath(proj.options.configFilePath!); // TODO: GH#18217
}
function verifyCompilerOptions() {
@@ -2289,7 +2289,7 @@ namespace ts {
if (projectReferences) {
for (let i = 0; i < projectReferences.length; i++) {
const ref = projectReferences[i];
const resolvedRefOpts = resolvedProjectReferences[i] && resolvedProjectReferences[i].commandLine.options;
const resolvedRefOpts = resolvedProjectReferences![i] && resolvedProjectReferences![i]!.commandLine.options;
if (resolvedRefOpts === undefined) {
createDiagnosticForReference(i, Diagnostics.File_0_does_not_exist, ref.path);
continue;
@@ -2409,7 +2409,7 @@ namespace ts {
}
else if (firstNonAmbientExternalModuleSourceFile && languageVersion < ScriptTarget.ES2015 && options.module === ModuleKind.None) {
// We cannot use createDiagnosticFromNode because nodes do not have parents yet
const span = getErrorSpanForNode(firstNonAmbientExternalModuleSourceFile, firstNonAmbientExternalModuleSourceFile.externalModuleIndicator);
const span = getErrorSpanForNode(firstNonAmbientExternalModuleSourceFile, firstNonAmbientExternalModuleSourceFile.externalModuleIndicator!);
programDiagnostics.add(createFileDiagnostic(firstNonAmbientExternalModuleSourceFile, span.start, span.length, Diagnostics.Cannot_use_imports_exports_or_module_augmentations_when_module_is_none));
}
@@ -2419,7 +2419,7 @@ namespace ts {
createDiagnosticForOptionName(Diagnostics.Only_amd_and_system_modules_are_supported_alongside_0, options.out ? "out" : "outFile", "module");
}
else if (options.module === undefined && firstNonAmbientExternalModuleSourceFile) {
const span = getErrorSpanForNode(firstNonAmbientExternalModuleSourceFile, firstNonAmbientExternalModuleSourceFile.externalModuleIndicator);
const span = getErrorSpanForNode(firstNonAmbientExternalModuleSourceFile, firstNonAmbientExternalModuleSourceFile.externalModuleIndicator!);
programDiagnostics.add(createFileDiagnostic(firstNonAmbientExternalModuleSourceFile, span.start, span.length, Diagnostics.Cannot_compile_modules_using_option_0_unless_the_module_flag_is_amd_or_system, options.out ? "out" : "outFile"));
}
}
@@ -2493,12 +2493,12 @@ namespace ts {
}
// Verify that all the emit files are unique and don't overwrite input files
function verifyEmitFilePath(emitFileName: string, emitFilesSeen: Map<true>) {
function verifyEmitFilePath(emitFileName: string | undefined, emitFilesSeen: Map<true>) {
if (emitFileName) {
const emitFilePath = toPath(emitFileName);
// Report error if the output overwrites input file
if (filesByName.has(emitFilePath)) {
let chain: DiagnosticMessageChain;
let chain: DiagnosticMessageChain | undefined;
if (!options.configFilePath) {
// The program is from either an inferred project or an external project
chain = chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Adding_a_tsconfig_json_file_will_help_organize_projects_that_contain_both_TypeScript_and_JavaScript_files_Learn_more_at_https_Colon_Slash_Slashaka_ms_Slashtsconfig);
@@ -2526,9 +2526,9 @@ namespace ts {
for (const pathProp of pathsSyntax) {
if (isObjectLiteralExpression(pathProp.initializer)) {
for (const keyProps of getPropertyAssignment(pathProp.initializer, key)) {
if (isArrayLiteralExpression(keyProps.initializer) &&
keyProps.initializer.elements.length > valueIndex) {
programDiagnostics.add(createDiagnosticForNodeInSourceFile(options.configFile, keyProps.initializer.elements[valueIndex], message, arg0, arg1, arg2));
const initializer = keyProps.initializer;
if (isArrayLiteralExpression(initializer) && initializer.elements.length > valueIndex) {
programDiagnostics.add(createDiagnosticForNodeInSourceFile(options.configFile!, initializer.elements[valueIndex], message, arg0, arg1, arg2));
needCompilerDiagnostic = false;
}
}
@@ -2586,7 +2586,7 @@ namespace ts {
programDiagnostics.add(createCompilerDiagnostic(message, arg0, arg1));
}
function createDiagnosticForOption(onKey: boolean, option1: string, option2: string, message: DiagnosticMessage, arg0: string | number, arg1?: string | number, arg2?: string | number) {
function createDiagnosticForOption(onKey: boolean, option1: string, option2: string | undefined, message: DiagnosticMessage, arg0: string | number, arg1?: string | number, arg2?: string | number) {
const compilerOptionsObjectLiteralSyntax = getCompilerOptionsObjectLiteralSyntax();
const needCompilerDiagnostic = !compilerOptionsObjectLiteralSyntax ||
!createOptionDiagnosticInObjectLiteralSyntax(compilerOptionsObjectLiteralSyntax, onKey, option1, option2, message, arg0, arg1, arg2);
@@ -2600,7 +2600,7 @@ namespace ts {
if (_referencesArrayLiteralSyntax === undefined) {
_referencesArrayLiteralSyntax = null; // tslint:disable-line:no-null-keyword
if (options.configFile) {
const jsonObjectLiteral = getTsConfigObjectLiteralExpression(options.configFile);
const jsonObjectLiteral = getTsConfigObjectLiteralExpression(options.configFile)!; // TODO: GH#18217
for (const prop of getPropertyAssignment(jsonObjectLiteral, "references")) {
if (isArrayLiteralExpression(prop.initializer)) {
_referencesArrayLiteralSyntax = prop.initializer;
@@ -2628,20 +2628,21 @@ namespace ts {
return _compilerOptionsObjectLiteralSyntax;
}
function createOptionDiagnosticInObjectLiteralSyntax(objectLiteral: ObjectLiteralExpression, onKey: boolean, key1: string, key2: string, message: DiagnosticMessage, arg0: string | number, arg1?: string | number, arg2?: string | number): boolean {
function createOptionDiagnosticInObjectLiteralSyntax(objectLiteral: ObjectLiteralExpression, onKey: boolean, key1: string, key2: string | undefined, message: DiagnosticMessage, arg0: string | number, arg1?: string | number, arg2?: string | number): boolean {
const props = getPropertyAssignment(objectLiteral, key1, key2);
for (const prop of props) {
programDiagnostics.add(createDiagnosticForNodeInSourceFile(options.configFile, onKey ? prop.name : prop.initializer, message, arg0, arg1, arg2));
programDiagnostics.add(createDiagnosticForNodeInSourceFile(options.configFile!, onKey ? prop.name : prop.initializer, message, arg0, arg1, arg2));
}
return !!props.length;
}
function createOptionDiagnosticInArrayLiteralSyntax(arrayLiteral: ArrayLiteralExpression, index: number, message: DiagnosticMessage, arg0: string | number, arg1?: string | number, arg2?: string | number): boolean {
function createOptionDiagnosticInArrayLiteralSyntax(arrayLiteral: ArrayLiteralExpression, index: number, message: DiagnosticMessage, arg0: string | number | undefined, arg1?: string | number, arg2?: string | number): boolean {
if (arrayLiteral.elements.length <= index) {
// Out-of-bounds
return false;
}
programDiagnostics.add(createDiagnosticForNodeInSourceFile(options.configFile, arrayLiteral.elements[index], message, arg0, arg1, arg2));
programDiagnostics.add(createDiagnosticForNodeInSourceFile(options.configFile!, arrayLiteral.elements[index], message, arg0, arg1, arg2));
return false; // TODO: GH#18217 This function always returns `false`!`
}
function blockEmittingOfFile(emitFileName: string, diag: Diagnostic) {
@@ -2649,7 +2650,7 @@ namespace ts {
programDiagnostics.add(diag);
}
function isEmittedFile(file: string) {
function isEmittedFile(file: string): boolean {
if (options.noEmit) {
return false;
}
+22 -22
View File
@@ -3,10 +3,10 @@ namespace ts {
/** This is the cache of module/typedirectives resolution that can be retained across program */
export interface ResolutionCache {
startRecordingFilesWithChangedResolutions(): void;
finishRecordingFilesWithChangedResolutions(): Path[];
finishRecordingFilesWithChangedResolutions(): Path[] | undefined;
resolveModuleNames(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined): ResolvedModuleFull[];
getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string): ResolvedModuleWithFailedLookupLocations;
getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string): ResolvedModuleWithFailedLookupLocations | undefined;
resolveTypeReferenceDirectives(typeDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[];
invalidateResolutionOfFile(filePath: Path): void;
@@ -76,13 +76,13 @@ namespace ts {
type GetResolutionWithResolvedFileName<T extends ResolutionWithFailedLookupLocations = ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName = ResolutionWithResolvedFileName> =
(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<true> | undefined;
let filesWithInvalidatedNonRelativeUnresolvedImports: Map<ReadonlyArray<string>> | undefined;
let allFilesHaveInvalidatedResolution = false;
const getCurrentDirectory = memoize(() => resolutionHost.getCurrentDirectory());
const getCurrentDirectory = memoize(() => resolutionHost.getCurrentDirectory!()); // TODO: GH#18217
const cachedDirectoryStructureHost = resolutionHost.getCachedDirectoryStructureHost();
// The resolvedModuleNames and resolvedTypeReferenceDirectives are the cache of resolutions per file.
@@ -112,7 +112,7 @@ namespace ts {
const directoryWatchesOfFailedLookups = createMap<DirectoryWatchesOfFailedLookup>();
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<FileWatcher>();
@@ -144,7 +144,7 @@ namespace ts {
return resolution.resolvedTypeReferenceDirective;
}
function isInDirectoryPath(dir: Path, file: Path) {
function isInDirectoryPath(dir: Path | undefined, file: Path) {
if (dir === undefined || file.length <= dir.length) {
return false;
}
@@ -173,14 +173,14 @@ namespace ts {
return collected;
}
function isFileWithInvalidatedNonRelativeUnresolvedImports(path: Path) {
function isFileWithInvalidatedNonRelativeUnresolvedImports(path: Path): boolean {
if (!filesWithInvalidatedNonRelativeUnresolvedImports) {
return false;
}
// Invalidated if file has unresolved imports
const value = filesWithInvalidatedNonRelativeUnresolvedImports.get(path);
return value && !!value.length;
return !!value && !!value.length;
}
function createHasInvalidatedResolution(forceAllFilesAsInvalidated?: boolean): HasInvalidatedResolution {
@@ -191,7 +191,7 @@ namespace ts {
}
const collected = filesWithInvalidatedResolutions;
filesWithInvalidatedResolutions = undefined;
return path => (collected && collected.has(path)) ||
return path => (!!collected && collected.has(path)) ||
isFileWithInvalidatedNonRelativeUnresolvedImports(path);
}
@@ -247,7 +247,7 @@ namespace ts {
logChanges: boolean): R[] {
const path = resolutionHost.toPath(containingFile);
const resolutionsInFile = cache.get(path) || cache.set(path, createMap()).get(path);
const resolutionsInFile = cache.get(path) || cache.set(path, createMap()).get(path)!;
const dirPath = getDirectoryPath(path);
let perDirectoryResolution = perDirectoryCache.get(dirPath);
if (!perDirectoryResolution) {
@@ -289,7 +289,7 @@ namespace ts {
}
Debug.assert(resolution !== undefined && !resolution.isInvalidated);
seenNamesInFile.set(name, true);
resolvedModules.push(getResolutionWithResolvedFileName(resolution));
resolvedModules.push(getResolutionWithResolvedFileName(resolution)!); // TODO: GH#18217
}
// Stop watching and remove the unused name
@@ -302,7 +302,7 @@ namespace ts {
return resolvedModules;
function resolutionIsEqualTo(oldResolution: T, newResolution: T): boolean {
function resolutionIsEqualTo(oldResolution: T | undefined, newResolution: T | undefined): boolean {
if (oldResolution === newResolution) {
return true;
}
@@ -381,7 +381,7 @@ namespace ts {
function getDirectoryToWatchFailedLookupLocation(failedLookupLocation: string, failedLookupLocationPath: Path): DirectoryOfFailedLookupWatch {
if (isInDirectoryPath(rootPath, failedLookupLocationPath)) {
return { dir: rootDir, dirPath: rootPath };
return { dir: rootDir!, dirPath: rootPath }; // TODO: GH#18217
}
return getDirectoryToWatchFromFailedLookupLocationDirectory(
@@ -457,7 +457,7 @@ namespace ts {
}
if (setAtRoot) {
setDirectoryWatcher(rootDir, rootPath);
setDirectoryWatcher(rootDir!, rootPath); // TODO: GH#18217
}
}
@@ -519,14 +519,14 @@ namespace ts {
}
function removeDirectoryWatcher(dirPath: string, subDirectory?: Path) {
const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath);
const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath)!;
if (subDirectory) {
const existing = dirWatcher.subDirectoryMap.get(subDirectory);
const existing = dirWatcher.subDirectoryMap!.get(subDirectory)!;
if (existing === 1) {
dirWatcher.subDirectoryMap.delete(subDirectory);
dirWatcher.subDirectoryMap!.delete(subDirectory);
}
else {
dirWatcher.subDirectoryMap.set(subDirectory, existing - 1);
dirWatcher.subDirectoryMap!.set(subDirectory, existing - 1);
}
}
// Do not close the watcher yet since it might be needed by other failed lookup locations.
@@ -589,10 +589,10 @@ namespace ts {
seen.set(dirPath, seenInDir);
}
resolutions.forEach((resolution, name) => {
if (seenInDir.has(name)) {
if (seenInDir!.has(name)) {
return;
}
seenInDir.set(name, true);
seenInDir!.set(name, true);
if (!resolution.isInvalidated && isInvalidatedResolution(resolution, getResolutionWithResolvedFileName)) {
// Mark the file as needing re-evaluation of module resolution instead of using it blindly.
resolution.isInvalidated = true;
@@ -626,7 +626,7 @@ namespace ts {
// Resolution is invalidated if the resulting file name is same as the deleted file path
(resolution, getResolutionWithResolvedFileName) => {
const result = getResolutionWithResolvedFileName(resolution);
return result && resolutionHost.toPath(result.resolvedFileName) === filePath;
return !!result && resolutionHost.toPath(result.resolvedFileName!) === filePath; // TODO: GH#18217
}
);
}
@@ -689,7 +689,7 @@ namespace ts {
return rootPath;
}
const { dirPath, ignore } = getDirectoryToWatchFromFailedLookupLocationDirectory(typeRoot, typeRootPath);
return !ignore && directoryWatchesOfFailedLookups.has(dirPath) && dirPath;
return !ignore && directoryWatchesOfFailedLookups.has(dirPath) ? dirPath : undefined;
}
function createTypeRootsWatch(typeRootPath: Path, typeRoot: string): FileWatcher {
+27 -24
View File
@@ -37,8 +37,8 @@ namespace ts {
getText(): string;
// Sets the text for the scanner to scan. An optional subrange starting point and length
// can be provided to have the scanner only scan a portion of the text.
setText(text: string, start?: number, length?: number): void;
setOnError(onError: ErrorCallback): void;
setText(text: string | undefined, start?: number, length?: number): void;
setOnError(onError: ErrorCallback | undefined): void;
setScriptTarget(scriptTarget: ScriptTarget): void;
setLanguageVariant(variant: LanguageVariant): void;
setTextPos(textPos: number): void;
@@ -266,14 +266,14 @@ namespace ts {
return false;
}
/* @internal */ export function isUnicodeIdentifierStart(code: number, languageVersion: ScriptTarget) {
return languageVersion >= ScriptTarget.ES5 ?
/* @internal */ export function isUnicodeIdentifierStart(code: number, languageVersion: ScriptTarget | undefined) {
return languageVersion! >= ScriptTarget.ES5 ?
lookupInUnicodeMap(code, unicodeES5IdentifierStart) :
lookupInUnicodeMap(code, unicodeES3IdentifierStart);
}
function isUnicodeIdentifierPart(code: number, languageVersion: ScriptTarget) {
return languageVersion >= ScriptTarget.ES5 ?
function isUnicodeIdentifierPart(code: number, languageVersion: ScriptTarget | undefined) {
return languageVersion! >= ScriptTarget.ES5 ?
lookupInUnicodeMap(code, unicodeES5IdentifierPart) :
lookupInUnicodeMap(code, unicodeES3IdentifierPart);
}
@@ -601,7 +601,7 @@ namespace ts {
}
function scanShebangTrivia(text: string, pos: number) {
const shebang = shebangTriviaRegex.exec(text)[0];
const shebang = shebangTriviaRegex.exec(text)![0];
pos = pos + shebang.length;
return pos;
}
@@ -626,11 +626,11 @@ namespace ts {
* @returns If "reduce" is true, the accumulated value. If "reduce" is false, the first truthy
* return value of the callback.
*/
function iterateCommentRanges<T, U>(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<T, U>(reduce: boolean, text: string, pos: number, trailing: boolean, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T, memo: U | undefined) => U, state: T, initial?: U): U | undefined {
let pendingPos!: number;
let pendingEnd!: number;
let pendingKind!: CommentKind;
let pendingHasTrailingNewLine!: boolean;
let hasPendingCommentRange = false;
let collecting = trailing || pos === 0;
let accumulator = initial;
@@ -769,20 +769,20 @@ namespace ts {
}
}
export function isIdentifierStart(ch: number, languageVersion: ScriptTarget): boolean {
export function isIdentifierStart(ch: number, languageVersion: ScriptTarget | undefined): boolean {
return ch >= CharacterCodes.A && ch <= CharacterCodes.Z || ch >= CharacterCodes.a && ch <= CharacterCodes.z ||
ch === CharacterCodes.$ || ch === CharacterCodes._ ||
ch > CharacterCodes.maxAsciiCharacter && isUnicodeIdentifierStart(ch, languageVersion);
}
export function isIdentifierPart(ch: number, languageVersion: ScriptTarget): boolean {
export function isIdentifierPart(ch: number, languageVersion: ScriptTarget | undefined): boolean {
return ch >= CharacterCodes.A && ch <= CharacterCodes.Z || ch >= CharacterCodes.a && ch <= CharacterCodes.z ||
ch >= CharacterCodes._0 && ch <= CharacterCodes._9 || ch === CharacterCodes.$ || ch === CharacterCodes._ ||
ch > CharacterCodes.maxAsciiCharacter && isUnicodeIdentifierPart(ch, languageVersion);
}
/* @internal */
export function isIdentifierText(name: string, languageVersion: ScriptTarget): boolean {
export function isIdentifierText(name: string, languageVersion: ScriptTarget | undefined): boolean {
if (!isIdentifierStart(name.charCodeAt(0), languageVersion)) {
return false;
}
@@ -800,13 +800,16 @@ namespace ts {
export function createScanner(languageVersion: ScriptTarget,
skipTrivia: boolean,
languageVariant = LanguageVariant.Standard,
text?: string,
textInitial?: string,
onError?: ErrorCallback,
start?: number,
length?: number): Scanner {
let text = textInitial!;
// Current position (end position of text of current token)
let pos: number;
// end of text
let end: number;
@@ -817,7 +820,7 @@ namespace ts {
let tokenPos: number;
let token: SyntaxKind;
let tokenValue: string;
let tokenValue!: string;
let tokenFlags: TokenFlags;
setText(text, start, length);
@@ -907,8 +910,8 @@ namespace ts {
function scanNumber(): string {
const start = pos;
const mainFragment = scanNumberFragment();
let decimalFragment: string;
let scientificFragment: string;
let decimalFragment: string | undefined;
let scientificFragment: string | undefined;
if (text.charCodeAt(pos) === CharacterCodes.dot) {
pos++;
decimalFragment = scanNumberFragment();
@@ -1285,7 +1288,7 @@ namespace ts {
if (len >= 2 && len <= 11) {
const ch = tokenValue.charCodeAt(0);
if (ch >= CharacterCodes.a && ch <= CharacterCodes.z) {
token = textToToken.get(tokenValue);
token = textToToken.get(tokenValue)!;
if (token !== undefined) {
return token;
}
@@ -2045,13 +2048,13 @@ namespace ts {
return text;
}
function setText(newText: string, start: number, length: number) {
function setText(newText: string | undefined, start: number | undefined, length: number | undefined) {
text = newText || "";
end = length === undefined ? text.length : start + length;
end = length === undefined ? text.length : start! + length;
setTextPos(start || 0);
}
function setOnError(errorCallback: ErrorCallback) {
function setOnError(errorCallback: ErrorCallback | undefined) {
onError = errorCallback;
}
@@ -2069,7 +2072,7 @@ namespace ts {
startPos = textPos;
tokenPos = textPos;
token = SyntaxKind.Unknown;
tokenValue = undefined;
tokenValue = undefined!;
tokenFlags = 0;
}
}
+27 -27
View File
@@ -8,7 +8,7 @@ namespace ts {
* @param sourceMapFilePath The path to the output source map file.
* @param sourceFileOrBundle The input source file or bundle for the program.
*/
initialize(filePath: string, sourceMapFilePath: string, sourceFileOrBundle: SourceFile | Bundle, sourceMapOutput?: SourceMapData[]): void;
initialize(filePath: string, sourceMapFilePath: string | undefined, sourceFileOrBundle: SourceFile | Bundle, sourceMapOutput?: SourceMapData[]): void;
/**
* Reset the SourceMapWriter to an empty state.
@@ -90,13 +90,13 @@ namespace ts {
let sourceMapSourceIndex: number;
// Last recorded and encoded spans
let lastRecordedSourceMapSpan: SourceMapSpan;
let lastEncodedSourceMapSpan: SourceMapSpan;
let lastEncodedNameIndex: number;
let lastRecordedSourceMapSpan: SourceMapSpan | undefined;
let lastEncodedSourceMapSpan: SourceMapSpan | undefined;
let lastEncodedNameIndex: number | undefined;
// Source map data
let sourceMapData: SourceMapData;
let sourceMapDataList: SourceMapData[];
let sourceMapDataList: SourceMapData[] | undefined;
let disabled: boolean = !(compilerOptions.sourceMap || compilerOptions.inlineSourceMap);
return {
@@ -134,8 +134,8 @@ namespace ts {
}
sourceMapDataList = outputSourceMapDataList;
currentSource = undefined;
currentSourceText = undefined;
currentSource = undefined!;
currentSourceText = undefined!;
// Current source map file and its index in the sources list
sourceMapSourceIndex = -1;
@@ -148,7 +148,7 @@ namespace ts {
// Initialize source map data
sourceMapData = {
sourceMapFilePath,
jsSourceMappingURL: !compilerOptions.inlineSourceMap ? getBaseFileName(normalizeSlashes(sourceMapFilePath)) : undefined,
jsSourceMappingURL: !compilerOptions.inlineSourceMap ? getBaseFileName(normalizeSlashes(sourceMapFilePath)) : undefined!, // TODO: GH#18217
sourceMapFile: getBaseFileName(normalizeSlashes(filePath)),
sourceMapSourceRoot: compilerOptions.sourceRoot || "",
sourceMapSources: [],
@@ -206,14 +206,14 @@ namespace ts {
sourceMapDataList.push(sourceMapData);
}
currentSource = undefined;
sourceMapDir = undefined;
sourceMapSourceIndex = undefined;
currentSource = undefined!;
sourceMapDir = undefined!;
sourceMapSourceIndex = undefined!;
lastRecordedSourceMapSpan = undefined;
lastEncodedSourceMapSpan = undefined;
lastEncodedSourceMapSpan = undefined!;
lastEncodedNameIndex = undefined;
sourceMapData = undefined;
sourceMapDataList = undefined;
sourceMapData = undefined!;
sourceMapDataList = undefined!;
}
// Encoding for sourcemap span
@@ -222,9 +222,9 @@ namespace ts {
return;
}
let prevEncodedEmittedColumn = lastEncodedSourceMapSpan.emittedColumn;
let prevEncodedEmittedColumn = lastEncodedSourceMapSpan!.emittedColumn;
// Line/Comma delimiters
if (lastEncodedSourceMapSpan.emittedLine === lastRecordedSourceMapSpan.emittedLine) {
if (lastEncodedSourceMapSpan!.emittedLine === lastRecordedSourceMapSpan.emittedLine) {
// Emit comma to separate the entry
if (sourceMapData.sourceMapMappings) {
sourceMapData.sourceMapMappings += ",";
@@ -232,7 +232,7 @@ namespace ts {
}
else {
// Emit line delimiters
for (let encodedLine = lastEncodedSourceMapSpan.emittedLine; encodedLine < lastRecordedSourceMapSpan.emittedLine; encodedLine++) {
for (let encodedLine = lastEncodedSourceMapSpan!.emittedLine; encodedLine < lastRecordedSourceMapSpan.emittedLine; encodedLine++) {
sourceMapData.sourceMapMappings += ";";
}
prevEncodedEmittedColumn = 1;
@@ -242,18 +242,18 @@ namespace ts {
sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.emittedColumn - prevEncodedEmittedColumn);
// 2. Relative sourceIndex
sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceIndex - lastEncodedSourceMapSpan.sourceIndex);
sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceIndex - lastEncodedSourceMapSpan!.sourceIndex);
// 3. Relative sourceLine 0 based
sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceLine - lastEncodedSourceMapSpan.sourceLine);
sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceLine - lastEncodedSourceMapSpan!.sourceLine);
// 4. Relative sourceColumn 0 based
sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceColumn - lastEncodedSourceMapSpan.sourceColumn);
sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceColumn - lastEncodedSourceMapSpan!.sourceColumn);
// 5. Relative namePosition 0 based
if (lastRecordedSourceMapSpan.nameIndex >= 0) {
if (lastRecordedSourceMapSpan.nameIndex! >= 0) {
Debug.assert(false, "We do not support name index right now, Make sure to update updateLastEncodedAndRecordedSpans when we start using this");
sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.nameIndex - lastEncodedNameIndex);
sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.nameIndex! - lastEncodedNameIndex!);
lastEncodedNameIndex = lastRecordedSourceMapSpan.nameIndex;
}
@@ -334,7 +334,7 @@ namespace ts {
if (node) {
const emitNode = node.emitNode;
const emitFlags = emitNode && emitNode.flags;
const emitFlags = emitNode && emitNode.flags || EmitFlags.None;
const range = emitNode && emitNode.sourceMapRange;
const { pos, end } = range || node;
let source = range && range.source;
@@ -386,7 +386,7 @@ namespace ts {
}
const emitNode = node && node.emitNode;
const emitFlags = emitNode && emitNode.flags;
const emitFlags = emitNode && emitNode.flags || EmitFlags.None;
const range = emitNode && emitNode.tokenSourceMapRanges && emitNode.tokenSourceMapRanges[token];
tokenPos = skipSourceTrivia(range ? range.pos : tokenPos);
@@ -437,7 +437,7 @@ namespace ts {
sourceMapData.inputSourceFileNames.push(currentSource.fileName);
if (compilerOptions.inlineSources) {
sourceMapData.sourceMapSourcesContent.push(currentSource.text);
sourceMapData.sourceMapSourcesContent!.push(currentSource.text);
}
}
}
@@ -447,7 +447,7 @@ namespace ts {
*/
function getText() {
if (disabled) {
return;
return undefined!; // TODO: GH#18217
}
encodeLastRecordedSourceMapSpan();
@@ -468,7 +468,7 @@ namespace ts {
*/
function getSourceMappingURL() {
if (disabled) {
return;
return undefined!; // TODO: GH#18217
}
if (compilerOptions.inlineSourceMap) {
+8 -7
View File
@@ -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;
}
}
}
+26 -22
View File
@@ -50,11 +50,11 @@ namespace ts {
/* @internal */
export function watchFileUsingPriorityPollingInterval(host: System, fileName: string, callback: FileWatcherCallback, watchPriority: PollingInterval): FileWatcher {
return host.watchFile(fileName, callback, pollingInterval(watchPriority));
return host.watchFile!(fileName, callback, pollingInterval(watchPriority));
}
/* @internal */
export type HostWatchFile = (fileName: string, callback: FileWatcherCallback, pollingInterval: PollingInterval) => FileWatcher;
export type HostWatchFile = (fileName: string, callback: FileWatcherCallback, pollingInterval: PollingInterval | undefined) => FileWatcher;
/* @internal */
export type HostWatchDirectory = (fileName: string, callback: DirectoryWatcherCallback, recursive?: boolean) => FileWatcher;
@@ -119,7 +119,7 @@ namespace ts {
return false;
function setLevel(level: keyof Levels) {
levels[level] = customLevels[level] || levels[level];
levels[level] = customLevels![level] || levels[level];
}
}
@@ -171,7 +171,7 @@ namespace ts {
}
function createPollingIntervalQueue(pollingInterval: PollingInterval): PollingIntervalQueue {
const queue = [] as PollingIntervalQueue;
const queue = [] as WatchedFile[] as PollingIntervalQueue;
queue.pollingInterval = pollingInterval;
queue.pollIndex = 0;
queue.pollScheduled = false;
@@ -203,7 +203,7 @@ namespace ts {
}
}
function pollQueue(queue: WatchedFile[], pollingInterval: PollingInterval, pollIndex: number, chunkSize: number) {
function pollQueue(queue: (WatchedFile | undefined)[], pollingInterval: PollingInterval, pollIndex: number, chunkSize: number) {
// Max visit would be all elements of the queue
let needsVisit = queue.length;
let definedValueCopyToIndex = pollIndex;
@@ -300,11 +300,11 @@ namespace ts {
}
function scheduleNextPoll(pollingInterval: PollingInterval) {
pollingIntervalQueue(pollingInterval).pollScheduled = host.setTimeout(pollingInterval === PollingInterval.Low ? pollLowPollingIntervalQueue : pollPollingIntervalQueue, pollingInterval, pollingIntervalQueue(pollingInterval));
pollingIntervalQueue(pollingInterval).pollScheduled = host.setTimeout!(pollingInterval === PollingInterval.Low ? pollLowPollingIntervalQueue : pollPollingIntervalQueue, pollingInterval, pollingIntervalQueue(pollingInterval));
}
function getModifiedTime(fileName: string) {
return host.getModifiedTime(fileName) || missingFileModifiedTime;
return host.getModifiedTime!(fileName) || missingFileModifiedTime;
}
}
@@ -369,7 +369,7 @@ namespace ts {
close: () => {
watcher.close();
result.childWatches.forEach(closeFileWatcher);
result = undefined;
result = undefined!;
},
dirName,
childWatches: emptyArray
@@ -423,6 +423,7 @@ namespace ts {
}
}
// TODO: GH#18217 Methods on System are often used as if they are certainly defined
export interface System {
args: string[];
newLine: string;
@@ -480,7 +481,7 @@ namespace ts {
declare const global: any;
declare const __filename: string;
export function getNodeMajorVersion() {
export function getNodeMajorVersion(): number | undefined {
if (typeof process === "undefined") {
return undefined;
}
@@ -517,6 +518,7 @@ namespace ts {
getEnvironmentVariable?(name: string): string;
};
// TODO: this is used as if it's certainly defined in many places.
export let sys: System = (() => {
// NodeJS detects "\uFEFF" at the start of the string and *replaces* it with the actual
// byte order mark from the specified encoding. Using any other byte order mark does
@@ -528,7 +530,7 @@ namespace ts {
const _path = require("path");
const _os = require("os");
// crypto can be absent on reduced node installations
let _crypto: typeof import("crypto");
let _crypto: typeof import("crypto") | undefined;
try {
_crypto = require("crypto");
}
@@ -542,7 +544,7 @@ namespace ts {
} = require("buffer").Buffer;
const nodeVersion = getNodeMajorVersion();
const isNode4OrLater = nodeVersion >= 4;
const isNode4OrLater = nodeVersion! >= 4;
const platform: string = _os.platform();
const useCaseSensitiveFileNames = isFileSystemCaseSensitive();
@@ -632,12 +634,12 @@ namespace ts {
}
},
base64decode: Buffer.from ? input => {
return Buffer.from(input, "base64").toString("utf8");
return Buffer.from!(input, "base64").toString("utf8");
} : input => {
return new Buffer(input, "base64").toString("utf8");
},
base64encode: Buffer.from ? input => {
return Buffer.from(input).toString("base64");
return Buffer.from!(input).toString("base64");
} : input => {
return new Buffer(input).toString("base64");
}
@@ -712,6 +714,7 @@ namespace ts {
return watchDirectoryRecursively(directoryName, callback);
}
watchDirectory(directoryName, callback);
return undefined!; // TODO: GH#18217
};
}
@@ -748,7 +751,7 @@ namespace ts {
(_eventName: string, relativeFileName) => {
// When files are deleted from disk, the triggered "rename" event would have a relativefileName of "undefined"
const fileName = !isString(relativeFileName)
? undefined
? undefined! // TODO: GH#18217
: getNormalizedAbsolutePath(relativeFileName, dirName);
// Some applications save a working file via rename operations
const callbacks = fileWatcherCallbacks.get(toCanonicalName(fileName));
@@ -838,7 +841,7 @@ namespace ts {
close: () => {
// Close the watcher (either existing file system entry watcher or missing file system entry watcher)
watcher.close();
watcher = undefined;
watcher = undefined!;
}
};
@@ -970,7 +973,7 @@ namespace ts {
data = byteOrderMarkIndicator + data;
}
let fd: number;
let fd: number | undefined;
try {
fd = _fs.openSync(fileName, "w");
@@ -1028,6 +1031,7 @@ namespace ts {
switch (entryKind) {
case FileSystemEntryKind.File: return stat.isFile();
case FileSystemEntryKind.Directory: return stat.isDirectory();
default: return false;
}
}
catch (e) {
@@ -1075,13 +1079,13 @@ namespace ts {
}
function createMD5HashUsingNativeCrypto(data: string): string {
const hash = _crypto.createHash("md5");
const hash = _crypto!.createHash("md5");
hash.update(data);
return hash.digest("hex");
}
function createSHA256Hash(data: string): string {
const hash = _crypto.createHash("sha256");
const hash = _crypto!.createHash("sha256");
hash.update(data);
return hash.digest("hex");
}
@@ -1134,7 +1138,7 @@ namespace ts {
}
}
let sys: System;
let sys: System | undefined;
if (typeof ChakraHost !== "undefined") {
sys = getChakraSystem();
}
@@ -1148,13 +1152,13 @@ namespace ts {
const originalWriteFile = sys.writeFile;
sys.writeFile = (path, data, writeBom) => {
const directoryPath = getDirectoryPath(normalizeSlashes(path));
if (directoryPath && !sys.directoryExists(directoryPath)) {
recursiveCreateDirectory(directoryPath, sys);
if (directoryPath && !sys!.directoryExists(directoryPath)) {
recursiveCreateDirectory(directoryPath, sys!);
}
originalWriteFile.call(sys, path, data, writeBom);
};
}
return sys;
return sys!;
})();
if (sys && sys.getEnvironmentVariable) {
+14 -14
View File
@@ -78,7 +78,7 @@ namespace ts {
* @param transforms An array of `TransformerFactory` callbacks.
* @param allowDtsFiles A value indicating whether to allow the transformation of .d.ts files.
*/
export function transformNodes<T extends Node>(resolver: EmitResolver, host: EmitHost, options: CompilerOptions, nodes: ReadonlyArray<T>, transformers: ReadonlyArray<TransformerFactory<T>>, allowDtsFiles: boolean): TransformationResult<T> {
export function transformNodes<T extends Node>(resolver: EmitResolver | undefined, host: EmitHost | undefined, options: CompilerOptions, nodes: ReadonlyArray<T>, transformers: ReadonlyArray<TransformerFactory<T>>, allowDtsFiles: boolean): TransformationResult<T> {
const enabledSyntaxKindFeatures = new Array<SyntaxKindFeatureFlags>(SyntaxKind.Count);
let lexicalEnvironmentVariableDeclarations: VariableDeclaration[];
let lexicalEnvironmentFunctionDeclarations: FunctionDeclaration[];
@@ -86,7 +86,7 @@ namespace ts {
let lexicalEnvironmentFunctionDeclarationsStack: FunctionDeclaration[][] = [];
let lexicalEnvironmentStackOffset = 0;
let lexicalEnvironmentSuspended = false;
let emitHelpers: EmitHelper[];
let emitHelpers: EmitHelper[] | undefined;
let onSubstituteNode: TransformationContext["onSubstituteNode"] = (_, node) => node;
let onEmitNode: TransformationContext["onEmitNode"] = (hint, node, callback) => callback(hint, node);
let state = TransformationState.Uninitialized;
@@ -96,8 +96,8 @@ namespace ts {
// initialization.
const context: TransformationContext = {
getCompilerOptions: () => options,
getEmitResolver: () => resolver,
getEmitHost: () => host,
getEmitResolver: () => resolver!, // TODO: GH#18217
getEmitHost: () => host!, // TODO: GH#18217
startLexicalEnvironment,
suspendLexicalEnvironment,
resumeLexicalEnvironment,
@@ -270,8 +270,8 @@ namespace ts {
lexicalEnvironmentVariableDeclarationsStack[lexicalEnvironmentStackOffset] = lexicalEnvironmentVariableDeclarations;
lexicalEnvironmentFunctionDeclarationsStack[lexicalEnvironmentStackOffset] = lexicalEnvironmentFunctionDeclarations;
lexicalEnvironmentStackOffset++;
lexicalEnvironmentVariableDeclarations = undefined;
lexicalEnvironmentFunctionDeclarations = undefined;
lexicalEnvironmentVariableDeclarations = undefined!;
lexicalEnvironmentFunctionDeclarations = undefined!;
}
/** Suspends the current lexical environment, usually after visiting a parameter list. */
@@ -294,12 +294,12 @@ namespace ts {
* Ends a lexical environment. The previous set of hoisted declarations are restored and
* any hoisted declarations added in this environment are returned.
*/
function endLexicalEnvironment(): Statement[] {
function endLexicalEnvironment(): Statement[] | undefined {
Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization.");
Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed.");
Debug.assert(!lexicalEnvironmentSuspended, "Lexical environment is suspended.");
let statements: Statement[];
let statements: Statement[] | undefined;
if (lexicalEnvironmentVariableDeclarations || lexicalEnvironmentFunctionDeclarations) {
if (lexicalEnvironmentFunctionDeclarations) {
statements = [...lexicalEnvironmentFunctionDeclarations];
@@ -354,12 +354,12 @@ namespace ts {
}
// Release references to external entries for GC purposes.
lexicalEnvironmentVariableDeclarations = undefined;
lexicalEnvironmentVariableDeclarationsStack = undefined;
lexicalEnvironmentFunctionDeclarations = undefined;
lexicalEnvironmentFunctionDeclarationsStack = undefined;
onSubstituteNode = undefined;
onEmitNode = undefined;
lexicalEnvironmentVariableDeclarations = undefined!;
lexicalEnvironmentVariableDeclarationsStack = undefined!;
lexicalEnvironmentFunctionDeclarations = undefined!;
lexicalEnvironmentFunctionDeclarationsStack = undefined!;
onSubstituteNode = undefined!;
onEmitNode = undefined!;
emitHelpers = undefined;
// Prevent further use of the transformation result.
+31 -30
View File
@@ -1,6 +1,6 @@
/*@internal*/
namespace ts {
export function getDeclarationDiagnostics(host: EmitHost, resolver: EmitResolver, file: SourceFile | undefined): DiagnosticWithLocation[] {
export function getDeclarationDiagnostics(host: EmitHost, resolver: EmitResolver, file: SourceFile | undefined): DiagnosticWithLocation[] | undefined {
if (file && isSourceFileJavaScript(file)) {
return []; // No declaration diagnostics for js for now
}
@@ -32,8 +32,8 @@ namespace ts {
let needsScopeFixMarker = false;
let resultHasScopeMarker = false;
let enclosingDeclaration: Node;
let necessaryTypeRefernces: Map<true>;
let lateMarkedStatements: LateVisibilityPaintedStatement[];
let necessaryTypeRefernces: Map<true> | undefined;
let lateMarkedStatements: LateVisibilityPaintedStatement[] | undefined;
let lateStatementReplacementMap: Map<VisitResult<LateVisibilityPaintedStatement>>;
let suppressNewDiagnosticContexts: boolean;
@@ -56,7 +56,7 @@ namespace ts {
const { noResolve, stripInternal } = options;
return transformRoot;
function recordTypeReferenceDirectivesIfNecessary(typeReferenceDirectives: string[]): void {
function recordTypeReferenceDirectivesIfNecessary(typeReferenceDirectives: string[] | undefined): void {
if (!typeReferenceDirectives) {
return;
}
@@ -151,7 +151,7 @@ namespace ts {
let hasNoDefaultLib = false;
const bundle = createBundle(map(node.sourceFiles,
sourceFile => {
if (sourceFile.isDeclarationFile || isSourceFileJavaScript(sourceFile)) return; // Omit declaration files from bundle results, too
if (sourceFile.isDeclarationFile || isSourceFileJavaScript(sourceFile)) return undefined!; // Omit declaration files from bundle results, too // TODO: GH#18217
hasNoDefaultLib = hasNoDefaultLib || sourceFile.hasNoDefaultLib;
currentSourceFile = sourceFile;
enclosingDeclaration = sourceFile;
@@ -186,7 +186,7 @@ namespace ts {
bundle.syntheticFileReferences = [];
bundle.syntheticTypeReferences = getFileReferencesForUsedTypeReferences();
bundle.hasNoDefaultLib = hasNoDefaultLib;
const outputFilePath = getDirectoryPath(normalizeSlashes(getOutputPathsFor(node, host, /*forceDtsPaths*/ true).declarationFilePath));
const outputFilePath = getDirectoryPath(normalizeSlashes(getOutputPathsFor(node, host, /*forceDtsPaths*/ true).declarationFilePath!));
const referenceVisitor = mapReferencesIntoArray(bundle.syntheticFileReferences as FileReference[], outputFilePath);
refs.forEach(referenceVisitor);
return bundle;
@@ -207,7 +207,7 @@ namespace ts {
necessaryTypeRefernces = undefined;
refs = collectReferences(currentSourceFile, createMap());
const references: FileReference[] = [];
const outputFilePath = getDirectoryPath(normalizeSlashes(getOutputPathsFor(node, host, /*forceDtsPaths*/ true).declarationFilePath));
const outputFilePath = getDirectoryPath(normalizeSlashes(getOutputPathsFor(node, host, /*forceDtsPaths*/ true).declarationFilePath!));
const referenceVisitor = mapReferencesIntoArray(references, outputFilePath);
const statements = visitNodes(node.statements, visitDeclarationStatements);
let combinedStatements = setTextRange(createNodeArray(transformAndReplaceLatePaintedStatements(statements)), node.statements);
@@ -304,7 +304,7 @@ namespace ts {
}
function ensureParameter(p: ParameterDeclaration, modifierMask?: ModifierFlags): ParameterDeclaration {
let oldDiag: typeof getSymbolAccessibilityDiagnostic;
let oldDiag: typeof getSymbolAccessibilityDiagnostic | undefined;
if (!suppressNewDiagnosticContexts) {
oldDiag = getSymbolAccessibilityDiagnostic;
getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(p);
@@ -320,7 +320,7 @@ namespace ts {
ensureNoInitializer(p)
);
if (!suppressNewDiagnosticContexts) {
getSymbolAccessibilityDiagnostic = oldDiag;
getSymbolAccessibilityDiagnostic = oldDiag!;
}
return newParam;
}
@@ -350,7 +350,7 @@ namespace ts {
| PropertyDeclaration
| PropertySignature;
function ensureType(node: HasInferredType, type: TypeNode, ignorePrivate?: boolean): TypeNode {
function ensureType(node: HasInferredType, type: TypeNode | undefined, ignorePrivate?: boolean): TypeNode | undefined {
if (!ignorePrivate && hasModifier(node, ModifierFlags.Private)) {
// Private nodes emit no types (except private parameter properties, whose parameter types are actually visible)
return;
@@ -427,7 +427,7 @@ namespace ts {
}
if (isBindingPattern(elem.name)) {
// If any child binding pattern element has been marked visible (usually by collect linked aliases), then this is visible
return forEach(elem.name.elements, getBindingNameVisible);
return some(elem.name.elements, getBindingNameVisible);
}
else {
return resolver.isDeclarationVisible(elem);
@@ -436,16 +436,16 @@ namespace ts {
function updateParamsList(node: Node, params: NodeArray<ParameterDeclaration>, modifierMask?: ModifierFlags) {
if (hasModifier(node, ModifierFlags.Private)) {
return undefined;
return undefined!; // TODO: GH#18217
}
const newParams = map(params, p => ensureParameter(p, modifierMask));
if (!newParams) {
return undefined;
return undefined!; // TODO: GH#18217
}
return createNodeArray(newParams, params.hasTrailingComma);
}
function ensureTypeParams(node: Node, params: NodeArray<TypeParameterDeclaration>) {
function ensureTypeParams(node: Node, params: NodeArray<TypeParameterDeclaration> | undefined) {
return hasModifier(node, ModifierFlags.Private) ? undefined : visitNodes(params, visitDeclarationSubtree);
}
@@ -473,8 +473,8 @@ namespace ts {
return setCommentRange(updated, getCommentRange(original));
}
function rewriteModuleSpecifier<T extends Node>(parent: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration | ImportTypeNode, input: T): T | StringLiteral {
if (!input) return;
function rewriteModuleSpecifier<T extends Node>(parent: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration | ImportTypeNode, input: T | undefined): T | StringLiteral {
if (!input) return undefined!; // TODO: GH#18217
resultHasExternalModuleIndicator = resultHasExternalModuleIndicator || (parent.kind !== SyntaxKind.ModuleDeclaration && parent.kind !== SyntaxKind.ImportType);
if (input.kind === SyntaxKind.StringLiteral && isBundledEmit) {
const newName = getExternalModuleNameFromDeclaration(context.getEmitHost(), resolver, parent);
@@ -571,7 +571,7 @@ namespace ts {
// be recorded. So while checking D's visibility we mark C as visible, then we must check C which in turn marks B, completing the chain of
// dependent imports and allowing a valid declaration file output. Today, this dependent alias marking only happens for internal import aliases.
while (length(lateMarkedStatements)) {
const i = lateMarkedStatements.shift();
const i = lateMarkedStatements!.shift()!;
if (!isLateVisibilityPaintedStatement(i)) {
return Debug.fail(`Late replaced statement was found which is not handled by the declaration transformer!: ${(ts as any).SyntaxKind ? (ts as any).SyntaxKind[(i as any).kind] : (i as any).kind}`);
}
@@ -687,7 +687,8 @@ namespace ts {
const ctor = createSignatureDeclaration(
SyntaxKind.Constructor,
isPrivate ? undefined : ensureTypeParams(input, input.typeParameters),
isPrivate ? undefined : updateParamsList(input, input.parameters, ModifierFlags.None),
// TODO: GH#18217
isPrivate ? undefined! : updateParamsList(input, input.parameters, ModifierFlags.None),
/*type*/ undefined
);
ctor.modifiers = createNodeArray(ensureModifiers(input));
@@ -807,7 +808,7 @@ namespace ts {
return cleanup(visitEachChild(input, visitDeclarationSubtree, context));
function cleanup<T extends Node>(returnValue: T | undefined): T {
function cleanup<T extends Node>(returnValue: T | undefined): T | undefined {
if (returnValue && canProdiceDiagnostic && hasDynamicName(input as Declaration)) {
checkName(input as DeclarationDiagnosticProducing);
}
@@ -961,7 +962,7 @@ namespace ts {
needsDeclare = false;
visitNode(inner, visitDeclarationStatements);
// eagerly transform nested namespaces (the nesting doesn't need any elision or painting done)
const id = "" + getOriginalNodeId(inner);
const id = "" + getOriginalNodeId(inner!); // TODO: GH#18217
const body = lateStatementReplacementMap.get(id);
lateStatementReplacementMap.delete(id);
return cleanup(updateModuleDeclaration(
@@ -977,7 +978,7 @@ namespace ts {
const modifiers = createNodeArray(ensureModifiers(input, isPrivate));
const typeParameters = ensureTypeParams(input, input.typeParameters);
const ctor = getFirstConstructorWithBody(input);
let parameterProperties: PropertyDeclaration[];
let parameterProperties: PropertyDeclaration[] | undefined;
if (ctor) {
const oldDiag = getSymbolAccessibilityDiagnostic;
parameterProperties = compact(flatMap(ctor.parameters, param => {
@@ -998,7 +999,7 @@ namespace ts {
}
function walkBindingPattern(pattern: BindingPattern) {
let elems: PropertyDeclaration[];
let elems: PropertyDeclaration[] | undefined;
for (const elem of pattern.elements) {
if (isOmittedExpression(elem)) continue;
if (isBindingPattern(elem.name)) {
@@ -1025,7 +1026,7 @@ namespace ts {
if (extendsClause && !isEntityNameExpression(extendsClause.expression) && extendsClause.expression.kind !== SyntaxKind.NullKeyword) {
// We must add a temporary declaration for the extends clause expression
const newId = createOptimisticUniqueName(`${unescapeLeadingUnderscores(input.name.escapedText)}_base`);
const newId = createOptimisticUniqueName(`${unescapeLeadingUnderscores(input.name!.escapedText)}_base`); // TODO: GH#18217
getSymbolAccessibilityDiagnostic = () => ({
diagnosticMessage: Diagnostics.extends_clause_of_exported_class_0_has_or_is_using_private_name_1,
errorNode: extendsClause,
@@ -1051,7 +1052,7 @@ namespace ts {
typeParameters,
heritageClauses,
members
))];
))!]; // TODO: GH#18217
}
else {
const heritageClauses = transformHeritageClauses(input.heritageClauses);
@@ -1081,7 +1082,7 @@ namespace ts {
// Anything left unhandled is an error, so this should be unreachable
return Debug.assertNever(input, `Unhandled top-level node in declaration emit: ${(ts as any).SyntaxKind[(input as any).kind]}`);
function cleanup<T extends Node>(node: T | undefined): T {
function cleanup<T extends Node>(node: T | undefined): T | undefined {
if (isEnclosingDeclaration(input)) {
enclosingDeclaration = previousEnclosingDeclaration;
}
@@ -1125,7 +1126,7 @@ namespace ts {
}
function checkName(node: DeclarationDiagnosticProducing) {
let oldDiag: typeof getSymbolAccessibilityDiagnostic;
let oldDiag: typeof getSymbolAccessibilityDiagnostic | undefined;
if (!suppressNewDiagnosticContexts) {
oldDiag = getSymbolAccessibilityDiagnostic;
getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNodeName(node);
@@ -1136,7 +1137,7 @@ namespace ts {
const entityName = decl.name.expression;
checkEntityNameVisibility(entityName, enclosingDeclaration);
if (!suppressNewDiagnosticContexts) {
getSymbolAccessibilityDiagnostic = oldDiag;
getSymbolAccessibilityDiagnostic = oldDiag!;
}
errorNameNode = undefined;
}
@@ -1156,7 +1157,7 @@ namespace ts {
return false;
}
function ensureModifiers(node: Node, privateDeclaration?: boolean): ReadonlyArray<Modifier> {
function ensureModifiers(node: Node, privateDeclaration?: boolean): ReadonlyArray<Modifier> | undefined {
const currentFlags = getModifierFlags(node);
const newFlags = ensureModifierFlags(node, privateDeclaration);
if (currentFlags === newFlags) {
@@ -1211,7 +1212,7 @@ namespace ts {
return prop;
}
function transformHeritageClauses(nodes: NodeArray<HeritageClause>) {
function transformHeritageClauses(nodes: NodeArray<HeritageClause> | undefined) {
return createNodeArray(filter(map(nodes, clause => updateHeritageClause(clause, visitNodes(createNodeArray(filter(clause.types, t => {
return isEntityNameExpression(t.expression) || (clause.token === SyntaxKind.ExtendsKeyword && t.expression.kind === SyntaxKind.NullKeyword);
})), visitDeclarationSubtree))), clause => clause.types && !!clause.types.length));
@@ -1238,7 +1239,7 @@ namespace ts {
return flags;
}
function getTypeAnnotationFromAccessor(accessor: AccessorDeclaration): TypeNode {
function getTypeAnnotationFromAccessor(accessor: AccessorDeclaration): TypeNode | undefined {
if (accessor) {
return accessor.kind === SyntaxKind.GetAccessor
? accessor.type // Getter - return type
@@ -90,7 +90,7 @@ namespace ts {
}
}
function getMethodNameVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic {
function getMethodNameVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic | undefined {
const diagnosticMessage = getMethodNameVisibilityDiagnosticMessage(symbolAccessibilityResult);
return diagnosticMessage !== undefined ? {
diagnosticMessage,
@@ -122,7 +122,7 @@ namespace ts {
}
}
export function createGetSymbolAccessibilityDiagnosticForNode(node: DeclarationDiagnosticProducing) {
export function createGetSymbolAccessibilityDiagnosticForNode(node: DeclarationDiagnosticProducing): (symbolAccessibilityResult: SymbolAccessibilityResult) => SymbolAccessibilityDiagnostic | undefined {
if (isVariableDeclaration(node) || isPropertyDeclaration(node) || isPropertySignature(node) || isBindingElement(node) || isConstructorDeclaration(node)) {
return getVariableDeclarationTypeVisibilityError;
}
@@ -151,7 +151,7 @@ namespace ts {
return getTypeAliasDeclarationVisibilityError;
}
else {
Debug.assertNever(node, `Attempted to set a declaration diagnostic context for unhandled node kind: ${(ts as any).SyntaxKind[(node as any).kind]}`);
return Debug.assertNever(node, `Attempted to set a declaration diagnostic context for unhandled node kind: ${(ts as any).SyntaxKind[(node as any).kind]}`);
}
function getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult: SymbolAccessibilityResult) {
@@ -190,7 +190,7 @@ namespace ts {
}
}
function getVariableDeclarationTypeVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic {
function getVariableDeclarationTypeVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic | undefined {
const diagnosticMessage = getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult);
return diagnosticMessage !== undefined ? {
diagnosticMessage,
@@ -233,7 +233,7 @@ namespace ts {
}
return {
diagnosticMessage,
errorNode: (node as NamedDeclaration).name,
errorNode: (node as NamedDeclaration).name!,
typeName: (node as NamedDeclaration).name
};
}
@@ -295,7 +295,7 @@ namespace ts {
break;
default:
Debug.fail("This is unknown kind for signature: " + node.kind);
return Debug.fail("This is unknown kind for signature: " + node.kind);
}
return {
@@ -304,7 +304,7 @@ namespace ts {
};
}
function getParameterDeclarationTypeVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic {
function getParameterDeclarationTypeVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic | undefined {
const diagnosticMessage: DiagnosticMessage = getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult);
return diagnosticMessage !== undefined ? {
diagnosticMessage,
@@ -373,7 +373,7 @@ namespace ts {
Diagnostics.Parameter_0_of_exported_function_has_or_is_using_private_name_1;
default:
Debug.fail(`Unknown parent for parameter: ${(ts as any).SyntaxKind[node.parent.kind]}`);
return Debug.fail(`Unknown parent for parameter: ${(ts as any).SyntaxKind[node.parent.kind]}`);
}
}
@@ -419,7 +419,7 @@ namespace ts {
break;
default:
Debug.fail("This is unknown parent for type parameter: " + node.parent.kind);
return Debug.fail("This is unknown parent for type parameter: " + node.parent.kind);
}
return {
+23 -23
View File
@@ -6,7 +6,7 @@ namespace ts {
downlevelIteration: boolean;
hoistTempVariables: boolean;
emitExpression: (value: Expression) => void;
emitBindingOrAssignment: (target: BindingOrAssignmentElementTarget, value: Expression, location: TextRange, original: Node) => void;
emitBindingOrAssignment: (target: BindingOrAssignmentElementTarget, value: Expression, location: TextRange, original: Node | undefined) => void;
createArrayBindingOrAssignmentPattern: (elements: BindingOrAssignmentElement[]) => ArrayBindingOrAssignmentPattern;
createObjectBindingOrAssignmentPattern: (elements: BindingOrAssignmentElement[]) => ObjectBindingOrAssignmentPattern;
createArrayBindingOrAssignmentElement: (node: Identifier) => BindingOrAssignmentElement;
@@ -37,7 +37,7 @@ namespace ts {
needsValue?: boolean,
createAssignmentCallback?: (name: Identifier, value: Expression, location?: TextRange) => Expression): Expression {
let location: TextRange = node;
let value: Expression;
let value: Expression | undefined;
if (isDestructuringAssignment(node)) {
value = node.right;
while (isEmptyArrayLiteral(node.left) || isEmptyObjectLiteral(node.left)) {
@@ -51,11 +51,11 @@ namespace ts {
}
}
let expressions: Expression[];
let expressions: Expression[] | undefined;
const flattenContext: FlattenContext = {
context,
level,
downlevelIteration: context.getCompilerOptions().downlevelIteration,
downlevelIteration: !!context.getCompilerOptions().downlevelIteration,
hoistTempVariables: true,
emitExpression,
emitBindingOrAssignment,
@@ -103,7 +103,7 @@ namespace ts {
expressions.push(value);
}
return aggregateTransformFlags(inlineExpressions(expressions)) || createOmittedExpression();
return aggregateTransformFlags(inlineExpressions(expressions!)) || createOmittedExpression();
function emitExpression(expression: Expression) {
// NOTE: this completely disables source maps, but aligns with the behavior of
@@ -127,7 +127,7 @@ namespace ts {
}
function bindingOrAssignmentElementAssignsToName(element: BindingOrAssignmentElement, escapedName: __String): boolean {
const target = getTargetOfBindingOrAssignmentElement(element);
const target = getTargetOfBindingOrAssignmentElement(element)!; // TODO: GH#18217
if (isBindingOrAssignmentPattern(target)) {
return bindingOrAssignmentPatternAssignsToName(target, escapedName);
}
@@ -164,15 +164,15 @@ namespace ts {
context: TransformationContext,
level: FlattenLevel,
rval?: Expression,
hoistTempVariables?: boolean,
hoistTempVariables = false,
skipInitializer?: boolean): VariableDeclaration[] {
let pendingExpressions: Expression[];
let pendingExpressions: Expression[] | undefined;
const pendingDeclarations: { pendingExpressions?: Expression[], name: BindingName, value: Expression, location?: TextRange, original?: Node; }[] = [];
const declarations: VariableDeclaration[] = [];
const flattenContext: FlattenContext = {
context,
level,
downlevelIteration: context.getCompilerOptions().downlevelIteration,
downlevelIteration: !!context.getCompilerOptions().downlevelIteration,
hoistTempVariables,
emitExpression,
emitBindingOrAssignment,
@@ -202,7 +202,7 @@ namespace ts {
}
else {
context.hoistVariableDeclaration(temp);
const pendingDeclaration = lastOrUndefined(pendingDeclarations);
const pendingDeclaration = last(pendingDeclarations);
pendingDeclaration.pendingExpressions = append(
pendingDeclaration.pendingExpressions,
createAssignment(temp, pendingDeclaration.value)
@@ -231,7 +231,7 @@ namespace ts {
pendingExpressions = append(pendingExpressions, value);
}
function emitBindingOrAssignment(target: BindingOrAssignmentElementTarget, value: Expression, location: TextRange, original: Node) {
function emitBindingOrAssignment(target: BindingOrAssignmentElementTarget, value: Expression, location: TextRange | undefined, original: Node | undefined) {
Debug.assertNode(target, isBindingName);
if (pendingExpressions) {
value = inlineExpressions(append(pendingExpressions, value));
@@ -268,15 +268,15 @@ namespace ts {
value = createVoidZero();
}
}
const bindingTarget = getTargetOfBindingOrAssignmentElement(element);
const bindingTarget = getTargetOfBindingOrAssignmentElement(element)!; // TODO: GH#18217
if (isObjectBindingOrAssignmentPattern(bindingTarget)) {
flattenObjectBindingOrAssignmentPattern(flattenContext, element, bindingTarget, value, location);
flattenObjectBindingOrAssignmentPattern(flattenContext, element, bindingTarget, value!, location);
}
else if (isArrayBindingOrAssignmentPattern(bindingTarget)) {
flattenArrayBindingOrAssignmentPattern(flattenContext, element, bindingTarget, value, location);
flattenArrayBindingOrAssignmentPattern(flattenContext, element, bindingTarget, value!, location);
}
else {
flattenContext.emitBindingOrAssignment(bindingTarget, value, location, /*original*/ element);
flattenContext.emitBindingOrAssignment(bindingTarget, value!, location, /*original*/ element); // TODO: GH#18217
}
}
@@ -300,15 +300,15 @@ namespace ts {
const reuseIdentifierExpressions = !isDeclarationBindingElement(parent) || numElements !== 0;
value = ensureIdentifier(flattenContext, value, reuseIdentifierExpressions, location);
}
let bindingElements: BindingOrAssignmentElement[];
let computedTempVariables: Expression[];
let bindingElements: BindingOrAssignmentElement[] | undefined;
let computedTempVariables: Expression[] | undefined;
for (let i = 0; i < numElements; i++) {
const element = elements[i];
if (!getRestIndicatorOfBindingOrAssignmentElement(element)) {
const propertyName = getPropertyNameOfBindingOrAssignmentElement(element);
const propertyName = getPropertyNameOfBindingOrAssignmentElement(element)!;
if (flattenContext.level >= FlattenLevel.ObjectRest
&& !(element.transformFlags & (TransformFlags.ContainsRest | TransformFlags.ContainsObjectRest))
&& !(getTargetOfBindingOrAssignmentElement(element).transformFlags & (TransformFlags.ContainsRest | TransformFlags.ContainsObjectRest))
&& !(getTargetOfBindingOrAssignmentElement(element)!.transformFlags & (TransformFlags.ContainsRest | TransformFlags.ContainsObjectRest))
&& !isComputedPropertyName(propertyName)) {
bindingElements = append(bindingElements, element);
}
@@ -319,7 +319,7 @@ namespace ts {
}
const rhsValue = createDestructuringPropertyAccess(flattenContext, value, propertyName);
if (isComputedPropertyName(propertyName)) {
computedTempVariables = append(computedTempVariables, (rhsValue as ElementAccessExpression).argumentExpression);
computedTempVariables = append<Expression>(computedTempVariables, (rhsValue as ElementAccessExpression).argumentExpression);
}
flattenBindingOrAssignmentElement(flattenContext, element, rhsValue, /*location*/ element);
}
@@ -329,7 +329,7 @@ namespace ts {
flattenContext.emitBindingOrAssignment(flattenContext.createObjectBindingOrAssignmentPattern(bindingElements), value, location, pattern);
bindingElements = undefined;
}
const rhsValue = createRestCall(flattenContext.context, value, elements, computedTempVariables, pattern);
const rhsValue = createRestCall(flattenContext.context, value, elements, computedTempVariables!, pattern); // TODO: GH#18217
flattenBindingOrAssignmentElement(flattenContext, element, rhsValue, element);
}
}
@@ -377,8 +377,8 @@ namespace ts {
const reuseIdentifierExpressions = !isDeclarationBindingElement(parent) || numElements !== 0;
value = ensureIdentifier(flattenContext, value, reuseIdentifierExpressions, location);
}
let bindingElements: BindingOrAssignmentElement[];
let restContainingElements: [Identifier, BindingOrAssignmentElement][];
let bindingElements: BindingOrAssignmentElement[] | undefined;
let restContainingElements: [Identifier, BindingOrAssignmentElement][] | undefined;
for (let i = 0; i < numElements; i++) {
const element = elements[i];
if (flattenContext.level >= FlattenLevel.ObjectRest) {
+108 -110
View File
@@ -159,7 +159,7 @@ namespace ts {
ReplaceWithReturn,
}
type LoopConverter = (node: IterationStatement, outermostLabeledStatement: LabeledStatement, convertedLoopBodyStatements: Statement[]) => Statement;
type LoopConverter = (node: IterationStatement, outermostLabeledStatement: LabeledStatement | undefined, convertedLoopBodyStatements: Statement[] | undefined) => Statement;
// Facts we track as we traverse the tree
const enum HierarchyFacts {
@@ -286,7 +286,7 @@ namespace ts {
/**
* Used to track if we are emitting body of the converted loop
*/
let convertedLoopState: ConvertedLoopState;
let convertedLoopState: ConvertedLoopState | undefined;
/**
* Keeps track of whether substitutions have been enabled for specific cases.
@@ -308,9 +308,9 @@ namespace ts {
const visited = visitSourceFile(node);
addEmitHelpers(visited, context.readEmitHelpers());
currentSourceFile = undefined;
currentText = undefined;
taggedTemplateStringDeclarations = undefined;
currentSourceFile = undefined!;
currentText = undefined!;
taggedTemplateStringDeclarations = undefined!;
hierarchyFacts = HierarchyFacts.None;
return visited;
}
@@ -338,7 +338,7 @@ namespace ts {
}
function isReturnVoidStatementInConstructorWithCapturedSuper(node: Node): boolean {
return hierarchyFacts & HierarchyFacts.ConstructorWithCapturedSuper
return (hierarchyFacts & HierarchyFacts.ConstructorWithCapturedSuper) !== 0
&& node.kind === SyntaxKind.ReturnStatement
&& !(<ReturnStatement>node).expression;
}
@@ -520,7 +520,7 @@ namespace ts {
const ancestorFacts = enterSubtree(HierarchyFacts.SourceFileExcludes, HierarchyFacts.SourceFileIncludes);
const statements: Statement[] = [];
startLexicalEnvironment();
let statementOffset = addStandardPrologue(statements, node.statements, /*ensureUseStrict*/ false);
let statementOffset: number | undefined = addStandardPrologue(statements, node.statements, /*ensureUseStrict*/ false);
addCaptureThisForNodeIfNeeded(statements, node);
statementOffset = addCustomPrologue(statements, node.statements, statementOffset, visitor);
addRange(statements, visitNodes(node.statements, visitor, isStatement, statementOffset));
@@ -541,7 +541,7 @@ namespace ts {
if (convertedLoopState !== undefined) {
const savedAllowedNonLabeledJumps = convertedLoopState.allowedNonLabeledJumps;
// for switch statement allow only non-labeled break
convertedLoopState.allowedNonLabeledJumps |= Jump.Break;
convertedLoopState.allowedNonLabeledJumps! |= Jump.Break;
const result = visitEachChild(node, visitor, context);
convertedLoopState.allowedNonLabeledJumps = savedAllowedNonLabeledJumps;
return result;
@@ -562,7 +562,7 @@ namespace ts {
function visitReturnStatement(node: ReturnStatement): Statement {
if (convertedLoopState) {
convertedLoopState.nonLocalJumps |= Jump.Return;
convertedLoopState.nonLocalJumps! |= Jump.Return;
if (isReturnVoidStatementInConstructorWithCapturedSuper(node)) {
node = returnCapturedThis(node);
}
@@ -619,45 +619,46 @@ namespace ts {
const jump = node.kind === SyntaxKind.BreakStatement ? Jump.Break : Jump.Continue;
const canUseBreakOrContinue =
(node.label && convertedLoopState.labels && convertedLoopState.labels.get(idText(node.label))) ||
(!node.label && (convertedLoopState.allowedNonLabeledJumps & jump));
(!node.label && (convertedLoopState.allowedNonLabeledJumps! & jump));
if (!canUseBreakOrContinue) {
let labelMarker: string;
if (!node.label) {
const label = node.label;
if (!label) {
if (node.kind === SyntaxKind.BreakStatement) {
convertedLoopState.nonLocalJumps |= Jump.Break;
convertedLoopState.nonLocalJumps! |= Jump.Break;
labelMarker = "break";
}
else {
convertedLoopState.nonLocalJumps |= Jump.Continue;
convertedLoopState.nonLocalJumps! |= Jump.Continue;
// note: return value is emitted only to simplify debugging, call to converted loop body does not do any dispatching on it.
labelMarker = "continue";
}
}
else {
if (node.kind === SyntaxKind.BreakStatement) {
labelMarker = `break-${node.label.escapedText}`;
setLabeledJump(convertedLoopState, /*isBreak*/ true, idText(node.label), labelMarker);
labelMarker = `break-${label.escapedText}`;
setLabeledJump(convertedLoopState, /*isBreak*/ true, idText(label), labelMarker);
}
else {
labelMarker = `continue-${node.label.escapedText}`;
setLabeledJump(convertedLoopState, /*isBreak*/ false, idText(node.label), labelMarker);
labelMarker = `continue-${label.escapedText}`;
setLabeledJump(convertedLoopState, /*isBreak*/ false, idText(label), labelMarker);
}
}
let returnExpression: Expression = createLiteral(labelMarker);
if (convertedLoopState.loopOutParameters.length) {
const outParams = convertedLoopState.loopOutParameters;
let expr: Expression;
if (convertedLoopState.loopOutParameters!.length) {
const outParams = convertedLoopState.loopOutParameters!;
let expr: Expression | undefined;
for (let i = 0; i < outParams.length; i++) {
const copyExpr = copyOutParameter(outParams[i], CopyDirection.ToOutParameter);
if (i === 0) {
expr = copyExpr;
}
else {
expr = createBinary(expr, SyntaxKind.CommaToken, copyExpr);
expr = createBinary(expr!, SyntaxKind.CommaToken, copyExpr);
}
}
returnExpression = createBinary(expr, SyntaxKind.CommaToken, returnExpression);
returnExpression = createBinary(expr!, SyntaxKind.CommaToken, returnExpression);
}
return createReturn(returnExpression);
}
@@ -814,7 +815,7 @@ namespace ts {
* @param node A ClassExpression or ClassDeclaration node.
* @param extendsClauseElement The expression for the class `extends` clause.
*/
function transformClassBody(node: ClassExpression | ClassDeclaration, extendsClauseElement: ExpressionWithTypeArguments): Block {
function transformClassBody(node: ClassExpression | ClassDeclaration, extendsClauseElement: ExpressionWithTypeArguments | undefined): Block {
const statements: Statement[] = [];
startLexicalEnvironment();
addExtendsHelperIfNeeded(statements, node, extendsClauseElement);
@@ -850,7 +851,7 @@ namespace ts {
* @param node The ClassExpression or ClassDeclaration node.
* @param extendsClauseElement The expression for the class `extends` clause.
*/
function addExtendsHelperIfNeeded(statements: Statement[], node: ClassExpression | ClassDeclaration, extendsClauseElement: ExpressionWithTypeArguments): void {
function addExtendsHelperIfNeeded(statements: Statement[], node: ClassExpression | ClassDeclaration, extendsClauseElement: ExpressionWithTypeArguments | undefined): void {
if (extendsClauseElement) {
statements.push(
setTextRange(
@@ -870,7 +871,7 @@ namespace ts {
* @param node The ClassExpression or ClassDeclaration node.
* @param extendsClauseElement The expression for the class `extends` clause.
*/
function addConstructor(statements: Statement[], node: ClassExpression | ClassDeclaration, extendsClauseElement: ExpressionWithTypeArguments): void {
function addConstructor(statements: Statement[], node: ClassExpression | ClassDeclaration, extendsClauseElement: ExpressionWithTypeArguments | undefined): void {
const savedConvertedLoopState = convertedLoopState;
convertedLoopState = undefined;
const ancestorFacts = enterSubtree(HierarchyFacts.ConstructorExcludes, HierarchyFacts.ConstructorIncludes);
@@ -904,13 +905,13 @@ namespace ts {
* @param hasSynthesizedSuper A value indicating whether the constructor starts with a
* synthesized `super` call.
*/
function transformConstructorParameters(constructor: ConstructorDeclaration, hasSynthesizedSuper: boolean) {
function transformConstructorParameters(constructor: ConstructorDeclaration | undefined, hasSynthesizedSuper: boolean) {
// If the TypeScript transformer needed to synthesize a constructor for property
// initializers, it would have also added a synthetic `...args` parameter and
// `super` call.
// If this is the case, we do not include the synthetic `...args` parameter and
// will instead use the `arguments` object in ES5/3.
return visitParameterList(constructor && !hasSynthesizedSuper && constructor.parameters, visitor, context)
return visitParameterList(constructor && !hasSynthesizedSuper ? constructor.parameters : undefined, visitor, context)
|| <ParameterDeclaration[]>[];
}
@@ -923,7 +924,7 @@ namespace ts {
* @param hasSynthesizedSuper A value indicating whether the constructor starts with a
* synthesized `super` call.
*/
function transformConstructorBody(constructor: ConstructorDeclaration | undefined, node: ClassDeclaration | ClassExpression, extendsClauseElement: ExpressionWithTypeArguments, hasSynthesizedSuper: boolean) {
function transformConstructorBody(constructor: ConstructorDeclaration | undefined, node: ClassDeclaration | ClassExpression, extendsClauseElement: ExpressionWithTypeArguments | undefined, hasSynthesizedSuper: boolean) {
const statements: Statement[] = [];
resumeLexicalEnvironment();
@@ -935,7 +936,7 @@ namespace ts {
statementOffset = 0;
}
else if (constructor) {
statementOffset = addStandardPrologue(statements, constructor.body.statements, /*ensureUseStrict*/ false);
statementOffset = addStandardPrologue(statements, constructor.body!.statements, /*ensureUseStrict*/ false);
}
if (constructor) {
@@ -943,7 +944,7 @@ namespace ts {
addRestParameterIfNeeded(statements, constructor, hasSynthesizedSuper);
if (!hasSynthesizedSuper) {
// If no super call has been synthesized, emit custom prologue directives.
statementOffset = addCustomPrologue(statements, constructor.body.statements, statementOffset, visitor);
statementOffset = addCustomPrologue(statements, constructor.body!.statements, statementOffset, visitor);
}
Debug.assert(statementOffset >= 0, "statementOffset not initialized correctly!");
@@ -951,7 +952,7 @@ namespace ts {
// determine whether the class is known syntactically to be a derived class (e.g. a
// class that extends a value that is not syntactically known to be `null`).
const isDerivedClass = extendsClauseElement && skipOuterExpressions(extendsClauseElement.expression).kind !== SyntaxKind.NullKeyword;
const isDerivedClass = !!extendsClauseElement && skipOuterExpressions(extendsClauseElement.expression).kind !== SyntaxKind.NullKeyword;
const superCaptureStatus = declareOrCaptureOrReturnThisForConstructorIfNeeded(statements, constructor, isDerivedClass, hasSynthesizedSuper, statementOffset);
// The last statement expression was replaced. Skip it.
@@ -964,14 +965,14 @@ namespace ts {
hierarchyFacts |= HierarchyFacts.ConstructorWithCapturedSuper;
}
addRange(statements, visitNodes(constructor.body.statements, visitor, isStatement, /*start*/ statementOffset));
addRange(statements, visitNodes(constructor.body!.statements, visitor, isStatement, /*start*/ statementOffset));
}
// Return `_this` unless we're sure enough that it would be pointless to add a return statement.
// If there's a constructor that we can tell returns in enough places, then we *do not* want to add a return.
if (isDerivedClass
&& superCaptureStatus !== SuperCaptureResult.ReplaceWithReturn
&& !(constructor && isSufficientlyCoveredByReturnStatements(constructor.body))) {
&& !(constructor && isSufficientlyCoveredByReturnStatements(constructor.body!))) {
statements.push(
createReturn(
createFileLevelUniqueName("_this")
@@ -990,7 +991,7 @@ namespace ts {
createNodeArray(
statements
),
/*location*/ constructor ? constructor.body.statements : node.members
/*location*/ constructor ? constructor.body!.statements : node.members
),
/*multiLine*/ true
);
@@ -1085,10 +1086,10 @@ namespace ts {
//
// return _super.call(...) || this;
//
let firstStatement: Statement;
let superCallExpression: Expression;
let firstStatement: Statement | undefined;
let superCallExpression: Expression | undefined;
const ctorStatements = ctor.body.statements;
const ctorStatements = ctor.body!.statements;
if (statementOffset < ctorStatements.length) {
firstStatement = ctorStatements[statementOffset];
@@ -1156,7 +1157,7 @@ namespace ts {
*
* @param node A ParameterDeclaration node.
*/
function visitParameter(node: ParameterDeclaration): ParameterDeclaration {
function visitParameter(node: ParameterDeclaration): ParameterDeclaration | undefined {
if (node.dotDotDotToken) {
// rest parameters are elided
return undefined;
@@ -1251,7 +1252,7 @@ namespace ts {
* @param name The name of the parameter.
* @param initializer The initializer for the parameter.
*/
function addDefaultValueAssignmentForBindingPattern(statements: Statement[], parameter: ParameterDeclaration, name: BindingPattern, initializer: Expression): void {
function addDefaultValueAssignmentForBindingPattern(statements: Statement[], parameter: ParameterDeclaration, name: BindingPattern, initializer: Expression | undefined): void {
const temp = getGeneratedNameForNode(parameter);
// In cases where a binding pattern is simply '[]' or '{}',
@@ -1339,7 +1340,7 @@ namespace ts {
* part of a constructor declaration with a
* synthesized call to `super`
*/
function shouldAddRestParameter(node: ParameterDeclaration, inConstructorWithSynthesizedSuper: boolean) {
function shouldAddRestParameter(node: ParameterDeclaration | undefined, inConstructorWithSynthesizedSuper: boolean) {
return node && node.dotDotDotToken && node.name.kind === SyntaxKind.Identifier && !inConstructorWithSynthesizedSuper;
}
@@ -1359,11 +1360,11 @@ namespace ts {
}
// `declarationName` is the name of the local declaration for the parameter.
const declarationName = getMutableClone(<Identifier>parameter.name);
const declarationName = getMutableClone(<Identifier>parameter!.name);
setEmitFlags(declarationName, EmitFlags.NoSourceMap);
// `expressionName` is the name of the parameter used in expressions.
const expressionName = getSynthesizedClone(<Identifier>parameter.name);
const expressionName = getSynthesizedClone(<Identifier>parameter!.name);
const restIndex = node.parameters.length - 1;
const temp = createLoopVariable();
@@ -1640,7 +1641,7 @@ namespace ts {
// arguments are both mapped contiguously to the accessor name.
const target = getMutableClone(receiver);
setEmitFlags(target, EmitFlags.NoComments | EmitFlags.NoTrailingSourceMap);
setSourceMapRange(target, firstAccessor.name);
setSourceMapRange(target, firstAccessor.name); // TODO: GH#18217
const propertyName = createExpressionForPropertyName(visitNode(firstAccessor.name, visitor, isPropertyName));
setEmitFlags(propertyName, EmitFlags.NoComments | EmitFlags.NoLeadingSourceMap);
@@ -1789,7 +1790,7 @@ namespace ts {
* @param location The source-map location for the new FunctionExpression.
* @param name The name of the new FunctionExpression.
*/
function transformFunctionLikeToExpression(node: FunctionLikeDeclaration, location: TextRange, name: Identifier, container: Node): FunctionExpression {
function transformFunctionLikeToExpression(node: FunctionLikeDeclaration, location: TextRange | undefined, name: Identifier | undefined, container: Node | undefined): FunctionExpression {
const savedConvertedLoopState = convertedLoopState;
convertedLoopState = undefined;
const ancestorFacts = container && isClassLike(container) && !hasModifier(node, ModifierFlags.Static)
@@ -1829,11 +1830,11 @@ namespace ts {
let multiLine = false; // indicates whether the block *must* be emitted as multiple lines
let singleLine = false; // indicates whether the block *may* be emitted as a single line
let statementsLocation: TextRange;
let closeBraceLocation: TextRange;
let closeBraceLocation: TextRange | undefined;
const statements: Statement[] = [];
const body = node.body;
let statementOffset: number;
const body = node.body!;
let statementOffset: number | undefined;
resumeLexicalEnvironment();
if (isBlock(body)) {
@@ -1919,7 +1920,7 @@ namespace ts {
}
function visitFunctionBodyDownLevel(node: FunctionDeclaration | FunctionExpression | AccessorDeclaration) {
const updated = visitFunctionBody(node.body, functionBodyVisitor, context);
const updated = visitFunctionBody(node.body, functionBodyVisitor, context)!;
return updateBlock(
updated,
setTextRange(
@@ -2003,12 +2004,12 @@ namespace ts {
return visitEachChild(node, visitor, context);
}
function visitVariableStatement(node: VariableStatement): Statement {
function visitVariableStatement(node: VariableStatement): Statement | undefined {
const ancestorFacts = enterSubtree(HierarchyFacts.None, hasModifier(node, ModifierFlags.Export) ? HierarchyFacts.ExportedVariableStatement : HierarchyFacts.None);
let updated: Statement;
let updated: Statement | undefined;
if (convertedLoopState && (node.declarationList.flags & NodeFlags.BlockScoped) === 0) {
// we are inside a converted loop - hoist variable declarations
let assignments: Expression[];
let assignments: Expression[] | undefined;
for (const decl of node.declarationList.declarations) {
hoistVariableDeclarationDeclaredInConvertedLoop(convertedLoopState, decl);
if (decl.initializer) {
@@ -2066,13 +2067,12 @@ namespace ts {
setCommentRange(declarationList, node);
if (node.transformFlags & TransformFlags.ContainsBindingPattern
&& (isBindingPattern(node.declarations[0].name) || isBindingPattern(lastOrUndefined(node.declarations).name))) {
&& (isBindingPattern(node.declarations[0].name) || isBindingPattern(last(node.declarations).name))) {
// If the first or last declaration is a binding pattern, we need to modify
// the source map range for the declaration list.
const firstDeclaration = firstOrUndefined(declarations);
if (firstDeclaration) {
const lastDeclaration = lastOrUndefined(declarations);
setSourceMapRange(declarationList, createRange(firstDeclaration.pos, lastDeclaration.end));
setSourceMapRange(declarationList, createRange(firstDeclaration.pos, last(declarations).end));
}
}
@@ -2198,11 +2198,11 @@ namespace ts {
}
function recordLabel(node: LabeledStatement) {
convertedLoopState.labels.set(idText(node.label), true);
convertedLoopState!.labels!.set(idText(node.label), true);
}
function resetLabel(node: LabeledStatement) {
convertedLoopState.labels.set(idText(node.label), false);
convertedLoopState!.labels!.set(idText(node.label), false);
}
function visitLabeledStatement(node: LabeledStatement): VisitResult<Statement> {
@@ -2229,14 +2229,14 @@ namespace ts {
}
}
function visitIterationStatementWithFacts(excludeFacts: HierarchyFacts, includeFacts: HierarchyFacts, node: IterationStatement, outermostLabeledStatement: LabeledStatement, convert?: LoopConverter) {
function visitIterationStatementWithFacts(excludeFacts: HierarchyFacts, includeFacts: HierarchyFacts, node: IterationStatement, outermostLabeledStatement: LabeledStatement | undefined, convert?: LoopConverter) {
const ancestorFacts = enterSubtree(excludeFacts, includeFacts);
const updated = convertIterationStatementBodyIfNecessary(node, outermostLabeledStatement, convert);
exitSubtree(ancestorFacts, HierarchyFacts.None, HierarchyFacts.None);
return updated;
}
function visitDoOrWhileStatement(node: DoStatement | WhileStatement, outermostLabeledStatement: LabeledStatement) {
function visitDoOrWhileStatement(node: DoStatement | WhileStatement, outermostLabeledStatement: LabeledStatement | undefined) {
return visitIterationStatementWithFacts(
HierarchyFacts.DoOrWhileStatementExcludes,
HierarchyFacts.DoOrWhileStatementIncludes,
@@ -2244,7 +2244,7 @@ namespace ts {
outermostLabeledStatement);
}
function visitForStatement(node: ForStatement, outermostLabeledStatement: LabeledStatement) {
function visitForStatement(node: ForStatement, outermostLabeledStatement: LabeledStatement | undefined) {
return visitIterationStatementWithFacts(
HierarchyFacts.ForStatementExcludes,
HierarchyFacts.ForStatementIncludes,
@@ -2252,7 +2252,7 @@ namespace ts {
outermostLabeledStatement);
}
function visitForInStatement(node: ForInStatement, outermostLabeledStatement: LabeledStatement) {
function visitForInStatement(node: ForInStatement, outermostLabeledStatement: LabeledStatement | undefined) {
return visitIterationStatementWithFacts(
HierarchyFacts.ForInOrForOfStatementExcludes,
HierarchyFacts.ForInOrForOfStatementIncludes,
@@ -2260,7 +2260,7 @@ namespace ts {
outermostLabeledStatement);
}
function visitForOfStatement(node: ForOfStatement, outermostLabeledStatement: LabeledStatement): VisitResult<Statement> {
function visitForOfStatement(node: ForOfStatement, outermostLabeledStatement: LabeledStatement | undefined): VisitResult<Statement> {
return visitIterationStatementWithFacts(
HierarchyFacts.ForInOrForOfStatementExcludes,
HierarchyFacts.ForInOrForOfStatementIncludes,
@@ -2271,12 +2271,13 @@ namespace ts {
function convertForOfStatementHead(node: ForOfStatement, boundValue: Expression, convertedLoopBodyStatements: Statement[]) {
const statements: Statement[] = [];
if (isVariableDeclarationList(node.initializer)) {
const initializer = node.initializer;
if (isVariableDeclarationList(initializer)) {
if (node.initializer.flags & NodeFlags.BlockScoped) {
enableSubstitutionsForBlockScopedBindings();
}
const firstOriginalDeclaration = firstOrUndefined(node.initializer.declarations);
const firstOriginalDeclaration = firstOrUndefined(initializer.declarations);
if (firstOriginalDeclaration && isBindingPattern(firstOriginalDeclaration.name)) {
// This works whether the declaration is a var, let, or const.
// It will use rhsIterationValue _a[_i] as the initializer.
@@ -2293,9 +2294,7 @@ namespace ts {
// Adjust the source map range for the first declaration to align with the old
// emitter.
const firstDeclaration = declarations[0];
const lastDeclaration = lastOrUndefined(declarations);
setSourceMapRange(declarationList, createRange(firstDeclaration.pos, lastDeclaration.end));
setSourceMapRange(declarationList, createRange(declarations[0].pos, last(declarations).end));
statements.push(
createVariableStatement(
@@ -2320,12 +2319,12 @@ namespace ts {
boundValue
)
]),
moveRangePos(node.initializer, -1)
moveRangePos(initializer, -1)
),
node.initializer
initializer
)
),
moveRangeEnd(node.initializer, -1)
moveRangeEnd(initializer, -1)
)
);
}
@@ -2333,14 +2332,14 @@ namespace ts {
else {
// Initializer is an expression. Emit the expression in the body, so that it's
// evaluated on every iteration.
const assignment = createAssignment(node.initializer, boundValue);
const assignment = createAssignment(initializer, boundValue);
if (isDestructuringAssignment(assignment)) {
aggregateTransformFlags(assignment);
statements.push(createStatement(visitBinaryExpression(assignment, /*needsDestructuringValue*/ false)));
}
else {
assignment.end = node.initializer.end;
statements.push(setTextRange(createStatement(visitNode(assignment, visitor, isExpression)), moveRangeEnd(node.initializer, -1)));
assignment.end = initializer.end;
statements.push(setTextRange(createStatement(visitNode(assignment, visitor, isExpression)), moveRangeEnd(initializer, -1)));
}
}
@@ -2565,7 +2564,7 @@ namespace ts {
&& i < numInitialPropertiesWithoutYield) {
numInitialPropertiesWithoutYield = i;
}
if (property.name.kind === SyntaxKind.ComputedPropertyName) {
if (property.name!.kind === SyntaxKind.ComputedPropertyName) {
numInitialProperties = i;
break;
}
@@ -2625,7 +2624,7 @@ namespace ts {
function visit(node: Identifier | BindingPattern) {
if (node.kind === SyntaxKind.Identifier) {
state.hoistedLocalVariables.push(node);
state.hoistedLocalVariables!.push(node);
}
else {
for (const element of node.elements) {
@@ -2637,9 +2636,9 @@ namespace ts {
}
}
function convertIterationStatementBodyIfNecessary(node: IterationStatement, outermostLabeledStatement: LabeledStatement, convert?: LoopConverter): VisitResult<Statement> {
function convertIterationStatementBodyIfNecessary(node: IterationStatement, outermostLabeledStatement: LabeledStatement | undefined, convert?: LoopConverter): VisitResult<Statement> {
if (!shouldConvertIterationStatementBody(node)) {
let saveAllowedNonLabeledJumps: Jump;
let saveAllowedNonLabeledJumps: Jump | undefined;
if (convertedLoopState) {
// we get here if we are trying to emit normal loop loop inside converted loop
// set allowedNonLabeledJumps to Break | Continue to mark that break\continue inside the loop should be emitted as is
@@ -2658,7 +2657,7 @@ namespace ts {
}
const functionName = createUniqueName("_loop");
let loopInitializer: VariableDeclarationList;
let loopInitializer: VariableDeclarationList | undefined;
switch (node.kind) {
case SyntaxKind.ForStatement:
case SyntaxKind.ForInStatement:
@@ -2766,7 +2765,7 @@ namespace ts {
const statements: Statement[] = [convertedLoopVariable];
let extraVariableDeclarations: VariableDeclaration[];
let extraVariableDeclarations: VariableDeclaration[] | undefined;
// propagate state from the inner loop to the outer loop if necessary
if (currentState.argumentsName) {
// if alias for arguments is set
@@ -2851,7 +2850,7 @@ namespace ts {
else {
let clone = getMutableClone(node);
// clean statement part
clone.statement = undefined;
clone.statement = undefined!;
// visit childnodes to transform initializer/condition/incrementor parts
clone = visitEachChild(clone, visitor, context);
// set loop statement
@@ -2886,7 +2885,7 @@ namespace ts {
// simple loops are emitted as just 'loop()';
// NOTE: if loop uses only 'continue' it still will be emitted as simple loop
const isSimpleLoop =
!(state.nonLocalJumps & ~Jump.Continue) &&
!(state.nonLocalJumps! & ~Jump.Continue) &&
!state.labeledNonLocalBreaks &&
!state.labeledNonLocalContinues;
@@ -2899,7 +2898,7 @@ namespace ts {
: call;
if (isSimpleLoop) {
statements.push(createStatement(callResult));
copyOutParameters(state.loopOutParameters, CopyDirection.ToOriginal, statements);
copyOutParameters(state.loopOutParameters!, CopyDirection.ToOriginal, statements);
}
else {
const loopResultName = createUniqueName("state");
@@ -2910,12 +2909,12 @@ namespace ts {
)
);
statements.push(stateVariable);
copyOutParameters(state.loopOutParameters, CopyDirection.ToOriginal, statements);
copyOutParameters(state.loopOutParameters!, CopyDirection.ToOriginal, statements);
if (state.nonLocalJumps & Jump.Return) {
if (state.nonLocalJumps! & Jump.Return) {
let returnStatement: ReturnStatement;
if (outerConvertedLoopState) {
outerConvertedLoopState.nonLocalJumps |= Jump.Return;
outerConvertedLoopState.nonLocalJumps! |= Jump.Return;
returnStatement = createReturn(loopResultName);
}
else {
@@ -2933,7 +2932,7 @@ namespace ts {
);
}
if (state.nonLocalJumps & Jump.Break) {
if (state.nonLocalJumps! & Jump.Break) {
statements.push(
createIf(
createBinary(
@@ -2948,8 +2947,8 @@ namespace ts {
if (state.labeledNonLocalBreaks || state.labeledNonLocalContinues) {
const caseClauses: CaseClause[] = [];
processLabeledJumps(state.labeledNonLocalBreaks, /*isBreak*/ true, loopResultName, outerConvertedLoopState, caseClauses);
processLabeledJumps(state.labeledNonLocalContinues, /*isBreak*/ false, loopResultName, outerConvertedLoopState, caseClauses);
processLabeledJumps(state.labeledNonLocalBreaks!, /*isBreak*/ true, loopResultName, outerConvertedLoopState, caseClauses);
processLabeledJumps(state.labeledNonLocalContinues!, /*isBreak*/ false, loopResultName, outerConvertedLoopState, caseClauses);
statements.push(
createSwitch(
loopResultName,
@@ -2976,7 +2975,7 @@ namespace ts {
}
}
function processLabeledJumps(table: Map<string>, isBreak: boolean, loopResultName: Identifier, outerLoop: ConvertedLoopState, caseClauses: CaseClause[]): void {
function processLabeledJumps(table: Map<string>, isBreak: boolean, loopResultName: Identifier, outerLoop: ConvertedLoopState | undefined, caseClauses: CaseClause[]): void {
if (!table) {
return;
}
@@ -3034,21 +3033,21 @@ namespace ts {
case SyntaxKind.SetAccessor:
const accessors = getAllAccessorDeclarations(node.properties, property);
if (property === accessors.firstAccessor) {
expressions.push(transformAccessorsToExpression(receiver, accessors, node, node.multiLine));
expressions.push(transformAccessorsToExpression(receiver, accessors, node, !!node.multiLine));
}
break;
case SyntaxKind.MethodDeclaration:
expressions.push(transformObjectLiteralMethodDeclarationToExpression(property, receiver, node, node.multiLine));
expressions.push(transformObjectLiteralMethodDeclarationToExpression(property, receiver, node, node.multiLine!));
break;
case SyntaxKind.PropertyAssignment:
expressions.push(transformPropertyAssignmentToExpression(property, receiver, node.multiLine));
expressions.push(transformPropertyAssignmentToExpression(property, receiver, node.multiLine!));
break;
case SyntaxKind.ShorthandPropertyAssignment:
expressions.push(transformShorthandPropertyAssignmentToExpression(property, receiver, node.multiLine));
expressions.push(transformShorthandPropertyAssignmentToExpression(property, receiver, node.multiLine!));
break;
default:
@@ -3130,12 +3129,12 @@ namespace ts {
const ancestorFacts = enterSubtree(HierarchyFacts.BlockScopeExcludes, HierarchyFacts.BlockScopeIncludes);
let updated: CatchClause;
Debug.assert(!!node.variableDeclaration, "Catch clause variable should always be present when downleveling ES2015.");
if (isBindingPattern(node.variableDeclaration.name)) {
if (isBindingPattern(node.variableDeclaration!.name)) {
const temp = createTempVariable(/*recordTempVariable*/ undefined);
const newVariableDeclaration = createVariableDeclaration(temp);
setTextRange(newVariableDeclaration, node.variableDeclaration);
const vars = flattenDestructuringBinding(
node.variableDeclaration,
node.variableDeclaration!,
visitor,
context,
FlattenLevel.All,
@@ -3247,7 +3246,7 @@ namespace ts {
function visitArrayLiteralExpression(node: ArrayLiteralExpression): Expression {
if (node.transformFlags & TransformFlags.ES2015) {
// We are here because we contain a SpreadElementExpression.
return transformAndSpreadElements(node.elements, /*needsUniqueCopy*/ true, node.multiLine, /*hasTrailingComma*/ node.elements.hasTrailingComma);
return transformAndSpreadElements(node.elements, /*needsUniqueCopy*/ true, !!node.multiLine, /*hasTrailingComma*/ !!node.elements.hasTrailingComma);
}
return visitEachChild(node, visitor, context);
}
@@ -3312,16 +3311,16 @@ namespace ts {
// The class statements are the statements generated by visiting the first statement with initializer of the
// body (1), while all other statements are added to remainingStatements (2)
const isVariableStatementWithInitializer = (stmt: Statement) => isVariableStatement(stmt) && !!firstOrUndefined(stmt.declarationList.declarations).initializer;
const isVariableStatementWithInitializer = (stmt: Statement) => isVariableStatement(stmt) && !!first(stmt.declarationList.declarations).initializer;
const bodyStatements = visitNodes(body.statements, visitor, isStatement);
const classStatements = filter(bodyStatements, isVariableStatementWithInitializer);
const remainingStatements = filter(bodyStatements, stmt => !isVariableStatementWithInitializer(stmt));
const varStatement = cast(firstOrUndefined(classStatements), isVariableStatement);
const varStatement = cast(first(classStatements), isVariableStatement);
// We know there is only one variable declaration here as we verified this in an
// earlier call to isTypeScriptClassWrapper
const variable = varStatement.declarationList.declarations[0];
const initializer = skipOuterExpressions(variable.initializer);
const initializer = skipOuterExpressions(variable.initializer!);
// Under certain conditions, the 'ts' transformer may introduce a class alias, which
// we see as an assignment, for example:
@@ -3374,7 +3373,7 @@ namespace ts {
}
// Find the trailing 'return' statement (4)
while (!isReturnStatement(elementAt(funcStatements, classBodyEnd))) {
while (!isReturnStatement(elementAt(funcStatements, classBodyEnd)!)) {
classBodyEnd--;
}
@@ -3517,7 +3516,7 @@ namespace ts {
createFunctionApply(
visitNode(target, visitor, isExpression),
thisArg,
transformAndSpreadElements(createNodeArray([createVoidZero(), ...node.arguments]), /*needsUniqueCopy*/ false, /*multiLine*/ false, /*hasTrailingComma*/ false)
transformAndSpreadElements(createNodeArray([createVoidZero(), ...node.arguments!]), /*needsUniqueCopy*/ false, /*multiLine*/ false, /*hasTrailingComma*/ false)
),
/*typeArguments*/ undefined,
[]
@@ -3571,7 +3570,7 @@ namespace ts {
}
// Rewrite using the pattern <segment0>.concat(<segment1>, <segment2>, ...)
return createArrayConcat(segments.shift(), segments);
return createArrayConcat(segments.shift()!, segments);
}
}
@@ -3650,7 +3649,7 @@ namespace ts {
// Build up the template arguments and the raw and cooked strings for the template.
// We start out with 'undefined' for the first argument and revisit later
// to avoid walking over the template string twice and shifting all our arguments over after the fact.
const templateArguments: Expression[] = [undefined];
const templateArguments: Expression[] = [undefined!];
const cookedStrings: Expression[] = [];
const rawStrings: Expression[] = [];
const template = node.template;
@@ -3734,7 +3733,7 @@ namespace ts {
// ("abc" + 1) << (2 + "")
// rather than
// "abc" + (1 << 2) + ""
const expression = reduceLeft(expressions, createAdd);
const expression = reduceLeft(expressions, createAdd)!;
if (nodeIsSynthesized(expression)) {
expression.pos = node.pos;
expression.end = node.end;
@@ -3921,14 +3920,13 @@ namespace ts {
* @param node An original source tree node.
*/
function isNameOfDeclarationWithCollidingName(node: Identifier) {
const parent = node.parent;
switch (parent.kind) {
switch (node.parent.kind) {
case SyntaxKind.BindingElement:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.VariableDeclaration:
return (<NamedDeclaration>parent).name === node
&& resolver.isDeclarationWithCollidingName(<Declaration>parent);
return (<NamedDeclaration>node.parent).name === node
&& resolver.isDeclarationWithCollidingName(<Declaration>node.parent);
}
return false;
@@ -3968,7 +3966,7 @@ namespace ts {
}
function isPartOfClassBody(declaration: ClassLikeDeclaration, node: Identifier) {
let currentNode = getParseTreeNode(node);
let currentNode: Node | undefined = getParseTreeNode(node);
if (!currentNode || currentNode === declaration || currentNode.end <= declaration.pos || currentNode.pos >= declaration.end) {
// if the node has no correlation to a parse tree node, its definitely not
// part of the body.
@@ -4010,7 +4008,7 @@ namespace ts {
: createPropertyAccess(getInternalName(node), "prototype");
}
function hasSynthesizedDefaultSuperCall(constructor: ConstructorDeclaration, hasExtendsClause: boolean) {
function hasSynthesizedDefaultSuperCall(constructor: ConstructorDeclaration | undefined, hasExtendsClause: boolean) {
if (!constructor || !hasExtendsClause) {
return false;
}
@@ -4019,7 +4017,7 @@ namespace ts {
return false;
}
const statement = firstOrUndefined(constructor.body.statements);
const statement = firstOrUndefined(constructor.body!.statements);
if (!statement || !nodeIsSynthesized(statement) || statement.kind !== SyntaxKind.ExpressionStatement) {
return false;
}
+14 -13
View File
@@ -116,10 +116,10 @@ namespace ts {
function visitCatchClauseInAsyncBody(node: CatchClause) {
const catchClauseNames = createUnderscoreEscapedMap<true>();
recordDeclarationName(node.variableDeclaration, catchClauseNames);
recordDeclarationName(node.variableDeclaration!, catchClauseNames); // TODO: GH#18217
// names declared in a catch variable are block scoped
let catchClauseUnshadowedNames: UnderscoreEscapedMap<true>;
let catchClauseUnshadowedNames: UnderscoreEscapedMap<true> | undefined;
catchClauseNames.forEach((_, escapedName) => {
if (enclosingFunctionParameterNames.has(escapedName)) {
if (!catchClauseUnshadowedNames) {
@@ -153,7 +153,7 @@ namespace ts {
return updateForIn(
node,
isVariableDeclarationListWithCollidingName(node.initializer)
? visitVariableDeclarationListWithCollidingNames(node.initializer, /*hasReceiver*/ true)
? visitVariableDeclarationListWithCollidingNames(node.initializer, /*hasReceiver*/ true)!
: visitNode(node.initializer, visitor, isForInitializer),
visitNode(node.expression, visitor, isExpression),
visitNode(node.statement, asyncBodyVisitor, isStatement, liftToBlock)
@@ -165,7 +165,7 @@ namespace ts {
node,
visitNode(node.awaitModifier, visitor, isToken),
isVariableDeclarationListWithCollidingName(node.initializer)
? visitVariableDeclarationListWithCollidingNames(node.initializer, /*hasReceiver*/ true)
? visitVariableDeclarationListWithCollidingNames(node.initializer, /*hasReceiver*/ true)!
: visitNode(node.initializer, visitor, isForInitializer),
visitNode(node.expression, visitor, isExpression),
visitNode(node.statement, asyncBodyVisitor, isStatement, liftToBlock)
@@ -173,10 +173,11 @@ namespace ts {
}
function visitForStatementInAsyncBody(node: ForStatement) {
const initializer = node.initializer!; // TODO: GH#18217
return updateFor(
node,
isVariableDeclarationListWithCollidingName(node.initializer)
? visitVariableDeclarationListWithCollidingNames(node.initializer, /*hasReceiver*/ false)
isVariableDeclarationListWithCollidingName(initializer)
? visitVariableDeclarationListWithCollidingNames(initializer, /*hasReceiver*/ false)
: visitNode(node.initializer, visitor, isForInitializer),
visitNode(node.condition, visitor, isExpression),
visitNode(node.incrementor, visitor, isExpression),
@@ -312,10 +313,10 @@ namespace ts {
}
function isVariableDeclarationListWithCollidingName(node: ForInitializer): node is VariableDeclarationList {
return node
return !!node
&& isVariableDeclarationList(node)
&& !(node.flags & NodeFlags.BlockScoped)
&& forEach(node.declarations, collidesWithParameterName);
&& node.declarations.some(collidesWithParameterName);
}
function visitVariableDeclarationListWithCollidingNames(node: VariableDeclarationList, hasReceiver: boolean) {
@@ -353,7 +354,7 @@ namespace ts {
const converted = setSourceMapRange(
createAssignment(
convertToAssignmentElementTarget(node.name),
node.initializer
node.initializer!
),
node
);
@@ -437,7 +438,7 @@ namespace ts {
context,
hasLexicalArguments,
promiseConstructor,
transformAsyncFunctionBodyWorker(node.body)
transformAsyncFunctionBodyWorker(node.body!)
);
const declarations = endLexicalEnvironment();
@@ -463,7 +464,7 @@ namespace ts {
}
}
function getPromiseConstructor(type: TypeNode) {
function getPromiseConstructor(type: TypeNode | undefined) {
const typeName = type && getEntityNameFromTypeNode(type);
if (typeName && isEntityName(typeName)) {
const serializationKind = resolver.getTypeReferenceSerializationKind(typeName);
@@ -634,7 +635,7 @@ namespace ts {
};`
};
function createAwaiterHelper(context: TransformationContext, hasLexicalArguments: boolean, promiseConstructor: EntityName | Expression, body: Block) {
function createAwaiterHelper(context: TransformationContext, hasLexicalArguments: boolean, promiseConstructor: EntityName | Expression | undefined, body: Block) {
context.requestEmitHelper(awaiterHelper);
const generatorFunc = createFunctionExpression(
@@ -648,7 +649,7 @@ namespace ts {
);
// Mark this node as originally an async function
(generatorFunc.emitNode || (generatorFunc.emitNode = {})).flags |= EmitFlags.AsyncFunctionBody | EmitFlags.ReuseTempVariableScope;
(generatorFunc.emitNode || (generatorFunc.emitNode = {} as EmitNode)).flags |= EmitFlags.AsyncFunctionBody | EmitFlags.ReuseTempVariableScope;
return createCall(
getHelperName("__awaiter"),
+1 -1
View File
@@ -109,7 +109,7 @@ namespace ts {
*/
function trySubstituteReservedName(name: Identifier) {
const token = name.originalKeywordKind || (nodeIsSynthesized(name) ? stringToToken(idText(name)) : undefined);
if (token >= SyntaxKind.FirstReservedWord && token <= SyntaxKind.LastReservedWord) {
if (token !== undefined && token >= SyntaxKind.FirstReservedWord && token <= SyntaxKind.LastReservedWord) {
return setTextRange(createLiteral(name), name);
}
return undefined;
+14 -14
View File
@@ -294,7 +294,7 @@ namespace ts {
*
* @param node A ForOfStatement.
*/
function visitForOfStatement(node: ForOfStatement, outermostLabeledStatement: LabeledStatement): VisitResult<Statement> {
function visitForOfStatement(node: ForOfStatement, outermostLabeledStatement: LabeledStatement | undefined): VisitResult<Statement> {
if (node.initializer.transformFlags & TransformFlags.ContainsObjectRest) {
node = transformForOfStatementWithObjectRest(node);
}
@@ -309,8 +309,8 @@ namespace ts {
function transformForOfStatementWithObjectRest(node: ForOfStatement) {
const initializerWithoutParens = skipParentheses(node.initializer) as ForInitializer;
if (isVariableDeclarationList(initializerWithoutParens) || isAssignmentPattern(initializerWithoutParens)) {
let bodyLocation: TextRange;
let statementsLocation: TextRange;
let bodyLocation: TextRange | undefined;
let statementsLocation: TextRange | undefined;
const temp = createTempVariable(/*recordTempVariable*/ undefined);
const statements: Statement[] = [createForOfBindingStatement(initializerWithoutParens, temp)];
if (isBlock(node.statement)) {
@@ -351,8 +351,8 @@ namespace ts {
function convertForOfStatementHead(node: ForOfStatement, boundValue: Expression) {
const binding = createForOfBindingStatement(node.initializer, boundValue);
let bodyLocation: TextRange;
let statementsLocation: TextRange;
let bodyLocation: TextRange | undefined;
let statementsLocation: TextRange | undefined;
const statements: Statement[] = [visitNode(binding, visitor, isStatement)];
const statement = visitNode(node.statement, visitor, isStatement);
if (isBlock(statement)) {
@@ -382,7 +382,7 @@ namespace ts {
: createAwait(expression);
}
function transformForAwaitOfStatement(node: ForOfStatement, outermostLabeledStatement: LabeledStatement) {
function transformForAwaitOfStatement(node: ForOfStatement, outermostLabeledStatement: LabeledStatement | undefined) {
const expression = visitNode(node.expression, visitor, isExpression);
const iterator = isIdentifier(expression) ? getGeneratedNameForNode(expression) : createTempVariable(/*recordTempVariable*/ undefined);
const result = isIdentifier(expression) ? getGeneratedNameForNode(iterator) : createTempVariable(/*recordTempVariable*/ undefined);
@@ -562,7 +562,7 @@ namespace ts {
? undefined
: node.asteriskToken,
visitNode(node.name, visitor, isPropertyName),
visitNode(/*questionToken*/ undefined, visitor, isToken),
visitNode<Token<SyntaxKind.QuestionToken>>(/*questionToken*/ undefined, visitor, isToken),
/*typeParameters*/ undefined,
visitParameterList(node.parameters, visitor, context),
/*type*/ undefined,
@@ -640,7 +640,7 @@ namespace ts {
function transformAsyncGeneratorFunctionBody(node: MethodDeclaration | AccessorDeclaration | FunctionDeclaration | FunctionExpression): FunctionBody {
resumeLexicalEnvironment();
const statements: Statement[] = [];
const statementOffset = addPrologue(statements, node.body.statements, /*ensureUseStrict*/ false, visitor);
const statementOffset = addPrologue(statements, node.body!.statements, /*ensureUseStrict*/ false, visitor);
appendObjectRestAssignmentsIfNeeded(statements, node);
statements.push(
@@ -655,8 +655,8 @@ namespace ts {
/*parameters*/ [],
/*type*/ undefined,
updateBlock(
node.body,
visitLexicalEnvironment(node.body.statements, visitor, context, statementOffset)
node.body!,
visitLexicalEnvironment(node.body!.statements, visitor, context, statementOffset)
)
)
)
@@ -664,7 +664,7 @@ namespace ts {
);
prependRange(statements, endLexicalEnvironment());
const block = updateBlock(node.body, statements);
const block = updateBlock(node.body!, statements);
// Minor optimization, emit `_super` helper to capture `super` access in an arrow.
// This step isn't needed if we eventually transform this to ES5.
@@ -702,7 +702,7 @@ namespace ts {
return body;
}
function appendObjectRestAssignmentsIfNeeded(statements: Statement[], node: FunctionLikeDeclaration): Statement[] {
function appendObjectRestAssignmentsIfNeeded(statements: Statement[] | undefined, node: FunctionLikeDeclaration): Statement[] | undefined {
for (const parameter of node.parameters) {
if (parameter.transformFlags & TransformFlags.ContainsObjectRest) {
const temp = getGeneratedNameForNode(parameter);
@@ -889,7 +889,7 @@ namespace ts {
};
export function createAssignHelper(context: TransformationContext, attributesSegments: Expression[]) {
if (context.getCompilerOptions().target >= ScriptTarget.ES2015) {
if (context.getCompilerOptions().target! >= ScriptTarget.ES2015) {
return createCall(createPropertyAccess(createIdentifier("Object"), "assign"),
/*typeArguments*/ undefined,
attributesSegments);
@@ -936,7 +936,7 @@ namespace ts {
context.requestEmitHelper(asyncGeneratorHelper);
// Mark this node as originally an async function
(generatorFunc.emitNode || (generatorFunc.emitNode = {})).flags |= EmitFlags.AsyncFunctionBody;
(generatorFunc.emitNode || (generatorFunc.emitNode = {} as EmitNode)).flags |= EmitFlags.AsyncFunctionBody;
return createCall(
getHelperName("__asyncGenerator"),
+70 -68
View File
@@ -135,7 +135,7 @@ namespace ts {
Endfinally // Marks the end of a `finally` block
}
type OperationArguments = [Label] | [Label, Expression] | [Statement] | [Expression] | [Expression, Expression];
type OperationArguments = [Label] | [Label, Expression] | [Statement] | [Expression | undefined] | [Expression, Expression];
// whether a generated code block is opening or closing at the current operation for a FunctionBuilder
const enum BlockAction {
@@ -224,6 +224,7 @@ namespace ts {
case Instruction.Yield: return "yield";
case Instruction.YieldStar: return "yield*";
case Instruction.Endfinally: return "endfinally";
default: return undefined!; // TODO: GH#18217
}
}
@@ -251,18 +252,18 @@ namespace ts {
// All three arrays are correlated by their index. This approach is used over allocating
// objects to store the same information to avoid GC overhead.
//
let blocks: CodeBlock[]; // Information about the code block
let blockOffsets: number[]; // The operation offset at which a code block begins or ends
let blockActions: BlockAction[]; // Whether the code block is opened or closed
let blockStack: CodeBlock[]; // A stack of currently open code blocks
let blocks: CodeBlock[] | undefined; // Information about the code block
let blockOffsets: number[] | undefined; // The operation offset at which a code block begins or ends
let blockActions: BlockAction[] | undefined; // Whether the code block is opened or closed
let blockStack: CodeBlock[] | undefined; // A stack of currently open code blocks
// Labels are used to mark locations in the code that can be the target of a Break (jump)
// operation. These are translated into case clauses in a switch statement.
// The following two arrays are correlated by their index. This approach is used over
// allocating objects to store the same information to avoid GC overhead.
//
let labelOffsets: number[]; // The operation offset at which the label is defined.
let labelExpressions: LiteralExpression[][]; // The NumericLiteral nodes bound to each label.
let labelOffsets: number[] | undefined; // The operation offset at which the label is defined.
let labelExpressions: LiteralExpression[][] | undefined; // The NumericLiteral nodes bound to each label.
let nextLabelId = 1; // The next label id to use.
// Operations store information about generated code for the function body. This
@@ -270,9 +271,9 @@ namespace ts {
// The following three arrays are correlated by their index. This approach is used over
// allocating objects to store the same information to avoid GC overhead.
//
let operations: OpCode[]; // The operation to perform.
let operationArguments: OperationArguments[]; // The arguments to the operation.
let operationLocations: TextRange[]; // The source map location for the operation.
let operations: OpCode[] | undefined; // The operation to perform.
let operationArguments: (OperationArguments | undefined)[] | undefined; // The arguments to the operation.
let operationLocations: (TextRange | undefined)[] | undefined; // The source map location for the operation.
let state: Identifier; // The name of the state object used by the generator at runtime.
@@ -280,14 +281,14 @@ namespace ts {
//
let blockIndex = 0; // The index of the current block.
let labelNumber = 0; // The current label number.
let labelNumbers: number[][];
let labelNumbers: number[][] | undefined;
let lastOperationWasAbrupt: boolean; // Indicates whether the last operation was abrupt (break/continue).
let lastOperationWasCompletion: boolean; // Indicates whether the last operation was a completion (return/throw).
let clauses: CaseClause[]; // The case clauses generated for labels.
let statements: Statement[]; // The statements for the current label.
let exceptionBlockStack: ExceptionBlock[]; // A stack of containing exception blocks.
let currentExceptionBlock: ExceptionBlock; // The current exception block.
let withBlockStack: WithBlock[]; // A stack containing `with` blocks.
let clauses: CaseClause[] | undefined; // The case clauses generated for labels.
let statements: Statement[] | undefined; // The statements for the current label.
let exceptionBlockStack: ExceptionBlock[] | undefined; // A stack of containing exception blocks.
let currentExceptionBlock: ExceptionBlock | undefined; // The current exception block.
let withBlockStack: WithBlock[] | undefined; // A stack containing `with` blocks.
return chainBundle(transformSourceFile);
@@ -440,7 +441,7 @@ namespace ts {
*
* @param node The node to visit.
*/
function visitFunctionDeclaration(node: FunctionDeclaration): Statement {
function visitFunctionDeclaration(node: FunctionDeclaration): Statement | undefined {
// Currently, we only support generators that were originally async functions.
if (node.asteriskToken) {
node = setOriginalNode(
@@ -453,7 +454,7 @@ namespace ts {
/*typeParameters*/ undefined,
visitParameterList(node.parameters, visitor, context),
/*type*/ undefined,
transformGeneratorFunctionBody(node.body)
transformGeneratorFunctionBody(node.body!)
),
/*location*/ node
),
@@ -615,7 +616,7 @@ namespace ts {
*
* @param node The node to visit.
*/
function visitVariableStatement(node: VariableStatement): Statement {
function visitVariableStatement(node: VariableStatement): Statement | undefined {
if (node.transformFlags & TransformFlags.ContainsYield) {
transformAndEmitVariableDeclarationList(node.declarationList);
return undefined;
@@ -655,13 +656,14 @@ namespace ts {
* @param node The node to visit.
*/
function visitBinaryExpression(node: BinaryExpression): Expression {
switch (getExpressionAssociativity(node)) {
const assoc = getExpressionAssociativity(node);
switch (assoc) {
case Associativity.Left:
return visitLeftAssociativeBinaryExpression(node);
case Associativity.Right:
return visitRightAssociativeBinaryExpression(node);
default:
Debug.fail("Unknown associativity.");
return Debug.assertNever(assoc);
}
}
@@ -934,9 +936,9 @@ namespace ts {
// x = %sent%;
const resumeLabel = defineLabel();
const expression = visitNode(node.expression, visitor, isExpression);
const expression = visitNode(node.expression!, visitor, isExpression);
if (node.asteriskToken) {
const iterator = (getEmitFlags(node.expression) & EmitFlags.Iterator) === 0
const iterator = (getEmitFlags(node.expression!) & EmitFlags.Iterator) === 0
? createValuesHelper(context, expression, /*location*/ node)
: expression;
emitYieldStar(iterator, /*location*/ node);
@@ -978,7 +980,7 @@ namespace ts {
const numInitialElements = countInitialNodesWithoutYield(elements);
let temp: Identifier;
let temp: Identifier | undefined;
if (numInitialElements > 0) {
temp = declareLocal();
const initialElements = visitNodes(elements, visitor, isExpression, 0, numInitialElements);
@@ -1155,7 +1157,7 @@ namespace ts {
cacheExpression(visitNode(target, visitor, isExpression)),
thisArg,
visitElements(
node.arguments,
node.arguments!,
/*leadingElement*/ createVoidZero()
)
),
@@ -1246,7 +1248,7 @@ namespace ts {
emitStatement(visitNode(node, visitor, isStatement));
}
function transformAndEmitVariableDeclarationList(node: VariableDeclarationList): VariableDeclarationList {
function transformAndEmitVariableDeclarationList(node: VariableDeclarationList): VariableDeclarationList | undefined {
for (const variable of node.declarations) {
const name = getSynthesizedClone(<Identifier>variable.name);
setCommentRange(name, variable.name);
@@ -1260,7 +1262,7 @@ namespace ts {
while (variablesWritten < numVariables) {
for (let i = variablesWritten; i < numVariables; i++) {
const variable = variables[i];
if (containsYield(variable.initializer) && pendingExpressions.length > 0) {
if (containsYield(variable.initializer!) && pendingExpressions.length > 0) {
break;
}
@@ -1281,7 +1283,7 @@ namespace ts {
return setSourceMapRange(
createAssignment(
setSourceMapRange(<Identifier>getSynthesizedClone(node.name), node.name),
visitNode(node.initializer, visitor, isExpression)
visitNode(node.initializer!, visitor, isExpression)
),
node
);
@@ -1306,11 +1308,11 @@ namespace ts {
if (containsYield(node.thenStatement) || containsYield(node.elseStatement)) {
const endLabel = defineLabel();
const elseLabel = node.elseStatement ? defineLabel() : undefined;
emitBreakWhenFalse(node.elseStatement ? elseLabel : endLabel, visitNode(node.expression, visitor, isExpression), /*location*/ node.expression);
emitBreakWhenFalse(node.elseStatement ? elseLabel! : endLabel, visitNode(node.expression, visitor, isExpression), /*location*/ node.expression);
transformAndEmitEmbeddedStatement(node.thenStatement);
if (node.elseStatement) {
emitBreak(endLabel);
markLabel(elseLabel);
markLabel(elseLabel!);
transformAndEmitEmbeddedStatement(node.elseStatement);
}
markLabel(endLabel);
@@ -1866,7 +1868,7 @@ namespace ts {
function transformAndEmitThrowStatement(node: ThrowStatement): void {
emitThrow(
visitNode(node.expression, visitor, isExpression),
visitNode(node.expression!, visitor, isExpression),
/*location*/ node
);
}
@@ -1906,7 +1908,7 @@ namespace ts {
beginExceptionBlock();
transformAndEmitEmbeddedStatement(node.tryBlock);
if (node.catchClause) {
beginCatchBlock(node.catchClause.variableDeclaration);
beginCatchBlock(node.catchClause.variableDeclaration!); // TODO: GH#18217
transformAndEmitEmbeddedStatement(node.catchClause.block);
}
@@ -1922,8 +1924,8 @@ namespace ts {
}
}
function containsYield(node: Node) {
return node && (node.transformFlags & TransformFlags.ContainsYield) !== 0;
function containsYield(node: Node | undefined): boolean {
return !!node && (node.transformFlags & TransformFlags.ContainsYield) !== 0;
}
function countInitialNodesWithoutYield(nodes: NodeArray<Node>) {
@@ -2010,7 +2012,7 @@ namespace ts {
*/
function markLabel(label: Label): void {
Debug.assert(labelOffsets !== undefined, "No labels were defined.");
labelOffsets[label] = operations ? operations.length : 0;
labelOffsets![label] = operations ? operations.length : 0;
}
/**
@@ -2026,11 +2028,11 @@ namespace ts {
blockStack = [];
}
const index = blockActions.length;
blockActions[index] = BlockAction.Open;
blockOffsets[index] = operations ? operations.length : 0;
const index = blockActions!.length;
blockActions![index] = BlockAction.Open;
blockOffsets![index] = operations ? operations.length : 0;
blocks[index] = block;
blockStack.push(block);
blockStack!.push(block);
return index;
}
@@ -2039,13 +2041,13 @@ namespace ts {
*/
function endBlock(): CodeBlock {
const block = peekBlock();
Debug.assert(block !== undefined, "beginBlock was never called.");
if (block === undefined) return Debug.fail("beginBlock was never called.");
const index = blockActions.length;
blockActions[index] = BlockAction.Close;
blockOffsets[index] = operations ? operations.length : 0;
blocks[index] = block;
blockStack.pop();
const index = blockActions!.length;
blockActions![index] = BlockAction.Close;
blockOffsets![index] = operations ? operations.length : 0;
blocks![index] = block;
blockStack!.pop();
return block;
}
@@ -2053,13 +2055,13 @@ namespace ts {
* Gets the current open block.
*/
function peekBlock() {
return lastOrUndefined(blockStack);
return lastOrUndefined(blockStack!);
}
/**
* Gets the kind of the current open block.
*/
function peekBlockKind(): CodeBlockKind {
function peekBlockKind(): CodeBlockKind | undefined {
const block = peekBlock();
return block && block.kind;
}
@@ -2331,7 +2333,7 @@ namespace ts {
function hasImmediateContainingLabeledBlock(labelText: string, start: number) {
for (let j = start; j >= 0; j--) {
const containingBlock = blockStack[j];
const containingBlock = blockStack![j];
if (supportsLabeledBreakOrContinue(containingBlock)) {
if (containingBlock.labelText === labelText) {
return true;
@@ -2407,8 +2409,8 @@ namespace ts {
*
* @param label A label.
*/
function createLabel(label: Label): Expression {
if (label > 0) {
function createLabel(label: Label | undefined): Expression {
if (label !== undefined && label > 0) {
if (labelExpressions === undefined) {
labelExpressions = [];
}
@@ -2620,8 +2622,8 @@ namespace ts {
const operationIndex = operations.length;
operations[operationIndex] = code;
operationArguments[operationIndex] = args;
operationLocations[operationIndex] = location;
operationArguments![operationIndex] = args;
operationLocations![operationIndex] = location;
}
/**
@@ -2869,9 +2871,9 @@ namespace ts {
*/
function tryEnterOrLeaveBlock(operationIndex: number): void {
if (blocks) {
for (; blockIndex < blockActions.length && blockOffsets[blockIndex] <= operationIndex; blockIndex++) {
for (; blockIndex < blockActions!.length && blockOffsets![blockIndex] <= operationIndex; blockIndex++) {
const block = blocks[blockIndex];
const blockAction = blockActions[blockIndex];
const blockAction = blockActions![blockIndex];
switch (block.kind) {
case CodeBlockKind.Exception:
if (blockAction === BlockAction.Open) {
@@ -2883,11 +2885,11 @@ namespace ts {
statements = [];
}
exceptionBlockStack.push(currentExceptionBlock);
exceptionBlockStack.push(currentExceptionBlock!);
currentExceptionBlock = block;
}
else if (blockAction === BlockAction.Close) {
currentExceptionBlock = exceptionBlockStack.pop();
currentExceptionBlock = exceptionBlockStack!.pop();
}
break;
case CodeBlockKind.With:
@@ -2899,7 +2901,7 @@ namespace ts {
withBlockStack.push(block);
}
else if (blockAction === BlockAction.Close) {
withBlockStack.pop();
withBlockStack!.pop();
}
break;
// default: do nothing
@@ -2925,7 +2927,7 @@ namespace ts {
lastOperationWasAbrupt = false;
lastOperationWasCompletion = false;
const opcode = operations[operationIndex];
const opcode = operations![operationIndex];
if (opcode === OpCode.Nop) {
return;
}
@@ -2933,12 +2935,12 @@ namespace ts {
return writeEndfinally();
}
const args = operationArguments[operationIndex];
const args = operationArguments![operationIndex]!;
if (opcode === OpCode.Statement) {
return writeStatement(<Statement>args[0]);
}
const location = operationLocations[operationIndex];
const location = operationLocations![operationIndex];
switch (opcode) {
case OpCode.Assign:
return writeAssign(<Expression>args[0], <Expression>args[1], location);
@@ -2982,7 +2984,7 @@ namespace ts {
* @param right The right-hand side of the assignment.
* @param operationLocation The source map location for the operation.
*/
function writeAssign(left: Expression, right: Expression, operationLocation: TextRange): void {
function writeAssign(left: Expression, right: Expression, operationLocation: TextRange | undefined): void {
writeStatement(setTextRange(createStatement(createAssignment(left, right)), operationLocation));
}
@@ -2992,7 +2994,7 @@ namespace ts {
* @param expression The value to throw.
* @param operationLocation The source map location for the operation.
*/
function writeThrow(expression: Expression, operationLocation: TextRange): void {
function writeThrow(expression: Expression, operationLocation: TextRange | undefined): void {
lastOperationWasAbrupt = true;
lastOperationWasCompletion = true;
writeStatement(setTextRange(createThrow(expression), operationLocation));
@@ -3004,7 +3006,7 @@ namespace ts {
* @param expression The value to return.
* @param operationLocation The source map location for the operation.
*/
function writeReturn(expression: Expression, operationLocation: TextRange): void {
function writeReturn(expression: Expression | undefined, operationLocation: TextRange | undefined): void {
lastOperationWasAbrupt = true;
lastOperationWasCompletion = true;
writeStatement(
@@ -3029,7 +3031,7 @@ namespace ts {
* @param label The label for the Break.
* @param operationLocation The source map location for the operation.
*/
function writeBreak(label: Label, operationLocation: TextRange): void {
function writeBreak(label: Label, operationLocation: TextRange | undefined): void {
lastOperationWasAbrupt = true;
writeStatement(
setEmitFlags(
@@ -3054,7 +3056,7 @@ namespace ts {
* @param condition The condition for the Break.
* @param operationLocation The source map location for the operation.
*/
function writeBreakWhenTrue(label: Label, condition: Expression, operationLocation: TextRange): void {
function writeBreakWhenTrue(label: Label, condition: Expression, operationLocation: TextRange | undefined): void {
writeStatement(
setEmitFlags(
createIf(
@@ -3084,7 +3086,7 @@ namespace ts {
* @param condition The condition for the Break.
* @param operationLocation The source map location for the operation.
*/
function writeBreakWhenFalse(label: Label, condition: Expression, operationLocation: TextRange): void {
function writeBreakWhenFalse(label: Label, condition: Expression, operationLocation: TextRange | undefined): void {
writeStatement(
setEmitFlags(
createIf(
@@ -3113,7 +3115,7 @@ namespace ts {
* @param expression The expression to yield.
* @param operationLocation The source map location for the operation.
*/
function writeYield(expression: Expression, operationLocation: TextRange): void {
function writeYield(expression: Expression, operationLocation: TextRange | undefined): void {
lastOperationWasAbrupt = true;
writeStatement(
setEmitFlags(
@@ -3138,7 +3140,7 @@ namespace ts {
* @param expression The expression to yield.
* @param operationLocation The source map location for the operation.
*/
function writeYieldStar(expression: Expression, operationLocation: TextRange): void {
function writeYieldStar(expression: Expression, operationLocation: TextRange | undefined): void {
lastOperationWasAbrupt = true;
writeStatement(
setEmitFlags(
+7 -7
View File
@@ -50,7 +50,7 @@ namespace ts {
}
}
function transformJsxChildToExpression(node: JsxChild): Expression {
function transformJsxChildToExpression(node: JsxChild): Expression | undefined {
switch (node.kind) {
case SyntaxKind.JsxText:
return visitJsxText(node);
@@ -84,9 +84,9 @@ namespace ts {
return visitJsxOpeningFragment(node.openingFragment, node.children, isChild, /*location*/ node);
}
function visitJsxOpeningLikeElement(node: JsxOpeningLikeElement, children: ReadonlyArray<JsxChild>, isChild: boolean, location: TextRange) {
function visitJsxOpeningLikeElement(node: JsxOpeningLikeElement, children: ReadonlyArray<JsxChild> | undefined, isChild: boolean, location: TextRange) {
const tagName = getTagName(node);
let objectProperties: Expression;
let objectProperties: Expression | undefined;
const attrs = node.attributes.properties;
if (attrs.length === 0) {
// When there are no attributes, React wants "null"
@@ -118,7 +118,7 @@ namespace ts {
const element = createExpressionForJsxElement(
context.getEmitResolver().getJsxFactoryEntity(currentSourceFile),
compilerOptions.reactNamespace,
compilerOptions.reactNamespace!, // TODO: GH#18217
tagName,
objectProperties,
mapDefined(children, transformJsxChildToExpression),
@@ -136,7 +136,7 @@ namespace ts {
function visitJsxOpeningFragment(node: JsxOpeningFragment, children: ReadonlyArray<JsxChild>, isChild: boolean, location: TextRange) {
const element = createExpressionForJsxFragment(
context.getEmitResolver().getJsxFactoryEntity(currentSourceFile),
compilerOptions.reactNamespace,
compilerOptions.reactNamespace!, // TODO: GH#18217
mapDefined(children, transformJsxChildToExpression),
node,
location
@@ -159,7 +159,7 @@ namespace ts {
return createPropertyAssignment(name, expression);
}
function transformJsxAttributeInitializer(node: StringLiteral | JsxExpression) {
function transformJsxAttributeInitializer(node: StringLiteral | JsxExpression | undefined): Expression {
if (node === undefined) {
return createTrue();
}
@@ -563,4 +563,4 @@ namespace ts {
hearts: 0x2665,
diams: 0x2666
});
}
}
+2 -2
View File
@@ -9,7 +9,7 @@ namespace ts {
context.enableEmitNotification(SyntaxKind.SourceFile);
context.enableSubstitution(SyntaxKind.Identifier);
let currentSourceFile: SourceFile;
let currentSourceFile: SourceFile | undefined;
return chainBundle(transformSourceFile);
function transformSourceFile(node: SourceFile) {
@@ -104,7 +104,7 @@ namespace ts {
function substituteExpressionIdentifier(node: Identifier): Expression {
if (getEmitFlags(node) & EmitFlags.HelperName) {
const externalHelpersModuleName = getExternalHelpersModuleName(currentSourceFile);
const externalHelpersModuleName = getExternalHelpersModuleName(currentSourceFile!);
if (externalHelpersModuleName) {
return createPropertyAccess(externalHelpersModuleName, node);
}
+18 -18
View File
@@ -38,7 +38,7 @@ namespace ts {
context.enableEmitNotification(SyntaxKind.SourceFile); // Restore state when substituting nodes in a file.
const moduleInfoMap: ExternalModuleInfo[] = []; // The ExternalModuleInfo for each file.
const deferredExports: Statement[][] = []; // Exports to defer until an EndOfDeclarationMarker is found.
const deferredExports: (Statement[] | undefined)[] = []; // Exports to defer until an EndOfDeclarationMarker is found.
let currentSourceFile: SourceFile; // The current file.
let currentModuleInfo: ExternalModuleInfo; // The ExternalModuleInfo for the current file.
@@ -64,8 +64,8 @@ namespace ts {
// Perform the transformation.
const transformModule = getTransformModuleDelegate(moduleKind);
const updated = transformModule(node);
currentSourceFile = undefined;
currentModuleInfo = undefined;
currentSourceFile = undefined!;
currentModuleInfo = undefined!;
needUMDDynamicImportHelper = false;
return aggregateTransformFlags(updated);
}
@@ -391,7 +391,7 @@ namespace ts {
if (isImportEqualsDeclaration(node) || isExportDeclaration(node) || !getExternalModuleNameLiteral(node, currentSourceFile, host, resolver, compilerOptions)) {
return undefined;
}
const name = getLocalNameForExternalImport(node, currentSourceFile);
const name = getLocalNameForExternalImport(node, currentSourceFile)!; // TODO: GH#18217
const expr = getHelperExpressionForImport(node, name);
if (expr === name) {
return undefined;
@@ -605,7 +605,7 @@ namespace ts {
}
}
function createImportCallExpressionUMD(arg: Expression | undefined, containsLexicalThis: boolean): Expression {
function createImportCallExpressionUMD(arg: Expression, containsLexicalThis: boolean): Expression {
// (function (factory) {
// ... (regular UMD)
// }
@@ -762,7 +762,7 @@ namespace ts {
* @param node The node to visit.
*/
function visitImportDeclaration(node: ImportDeclaration): VisitResult<Statement> {
let statements: Statement[];
let statements: Statement[] | undefined;
const namespaceDeclaration = getNamespaceDeclarationNode(node);
if (moduleKind !== ModuleKind.AMD) {
if (!node.importClause) {
@@ -876,7 +876,7 @@ namespace ts {
function visitImportEqualsDeclaration(node: ImportEqualsDeclaration): VisitResult<Statement> {
Debug.assert(isExternalModuleImportEqualsDeclaration(node), "import= for internal module references should be handled in an earlier transformer.");
let statements: Statement[];
let statements: Statement[] | undefined;
if (moduleKind !== ModuleKind.AMD) {
if (hasModifier(node, ModifierFlags.Export)) {
statements = append(statements,
@@ -1009,7 +1009,7 @@ namespace ts {
return undefined;
}
let statements: Statement[];
let statements: Statement[] | undefined;
const original = node.original;
if (original && hasAssociatedEndOfDeclarationMarker(original)) {
// Defer exports until we encounter an EndOfDeclarationMarker node
@@ -1029,7 +1029,7 @@ namespace ts {
* @param node The node to visit.
*/
function visitFunctionDeclaration(node: FunctionDeclaration): VisitResult<Statement> {
let statements: Statement[];
let statements: Statement[] | undefined;
if (hasModifier(node, ModifierFlags.Export)) {
statements = append(statements,
setOriginalNode(
@@ -1072,7 +1072,7 @@ namespace ts {
* @param node The node to visit.
*/
function visitClassDeclaration(node: ClassDeclaration): VisitResult<Statement> {
let statements: Statement[];
let statements: Statement[] | undefined;
if (hasModifier(node, ModifierFlags.Export)) {
statements = append(statements,
setOriginalNode(
@@ -1113,12 +1113,12 @@ namespace ts {
* @param node The node to visit.
*/
function visitVariableStatement(node: VariableStatement): VisitResult<Statement> {
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<Modifier>;
let modifiers: NodeArray<Modifier> | undefined;
// If we're exporting these variables, then these just become assignments to 'exports.x'.
// We only want to emit assignments for variables with initializers.
@@ -1219,7 +1219,7 @@ namespace ts {
//
// To balance the declaration, add the exports of the elided variable
// statement.
if (hasAssociatedEndOfDeclarationMarker(node) && node.original.kind === SyntaxKind.VariableStatement) {
if (hasAssociatedEndOfDeclarationMarker(node) && node.original!.kind === SyntaxKind.VariableStatement) {
const id = getOriginalNodeId(node);
deferredExports[id] = appendExportsOfVariableStatement(deferredExports[id], <VariableStatement>node.original);
}
@@ -1532,9 +1532,9 @@ namespace ts {
previousOnEmitNode(hint, node, emitCallback);
currentSourceFile = undefined;
currentModuleInfo = undefined;
noSubstitution = undefined;
currentSourceFile = undefined!;
currentModuleInfo = undefined!;
noSubstitution = undefined!;
}
else {
previousOnEmitNode(hint, node, emitCallback);
+33 -37
View File
@@ -27,7 +27,7 @@ namespace ts {
context.enableEmitNotification(SyntaxKind.SourceFile); // Restore state when substituting nodes in a file.
const moduleInfoMap: ExternalModuleInfo[] = []; // The ExternalModuleInfo for each file.
const deferredExports: Statement[][] = []; // Exports to defer until an EndOfDeclarationMarker is found.
const deferredExports: (Statement[] | undefined)[] = []; // Exports to defer until an EndOfDeclarationMarker is found.
const exportFunctionsMap: Identifier[] = []; // The export function associated with a source file.
const noSubstitutionMap: boolean[][] = []; // Set of nodes for which substitution rules should be ignored for each file.
@@ -35,9 +35,9 @@ namespace ts {
let moduleInfo: ExternalModuleInfo; // ExternalModuleInfo for the current file.
let exportFunction: Identifier; // The export function for the current file.
let contextObject: Identifier; // The context object for the current file.
let hoistedStatements: Statement[];
let hoistedStatements: Statement[] | undefined;
let enclosingBlockScopedContainer: Node;
let noSubstitution: boolean[]; // Set of nodes for which substitution rules should be ignored.
let noSubstitution: boolean[] | undefined; // Set of nodes for which substitution rules should be ignored.
return chainBundle(transformSourceFile);
@@ -126,12 +126,12 @@ namespace ts {
noSubstitution = undefined;
}
currentSourceFile = undefined;
moduleInfo = undefined;
exportFunction = undefined;
contextObject = undefined;
hoistedStatements = undefined;
enclosingBlockScopedContainer = undefined;
currentSourceFile = undefined!;
moduleInfo = undefined!;
exportFunction = undefined!;
contextObject = undefined!;
hoistedStatements = undefined!;
enclosingBlockScopedContainer = undefined!;
return aggregateTransformFlags(updated);
}
@@ -259,7 +259,7 @@ namespace ts {
// - Temporary variables will appear at the top rather than at the bottom of the file
prependRange(statements, endLexicalEnvironment());
const exportStarFunction = addExportStarIfNeeded(statements);
const exportStarFunction = addExportStarIfNeeded(statements)!; // TODO: GH#18217
const moduleObject = createObjectLiteral([
createPropertyAssignment("setters",
createSettersArray(exportStarFunction, dependencyGroups)
@@ -464,7 +464,7 @@ namespace ts {
const parameterName = localName ? getGeneratedNameForNode(localName) : createUniqueName("");
const statements: Statement[] = [];
for (const entry of group.externalImports) {
const importVariableName = getLocalNameForExternalImport(entry, currentSourceFile);
const importVariableName = getLocalNameForExternalImport(entry, currentSourceFile)!; // TODO: GH#18217
switch (entry.kind) {
case SyntaxKind.ImportDeclaration:
if (!entry.importClause) {
@@ -590,9 +590,9 @@ namespace ts {
* @param node The node to visit.
*/
function visitImportDeclaration(node: ImportDeclaration): VisitResult<Statement> {
let statements: Statement[];
let statements: Statement[] | undefined;
if (node.importClause) {
hoistVariableDeclaration(getLocalNameForExternalImport(node, currentSourceFile));
hoistVariableDeclaration(getLocalNameForExternalImport(node, currentSourceFile)!); // TODO: GH#18217
}
if (hasAssociatedEndOfDeclarationMarker(node)) {
@@ -615,13 +615,13 @@ namespace ts {
function visitImportEqualsDeclaration(node: ImportEqualsDeclaration): VisitResult<Statement> {
Debug.assert(isExternalModuleImportEqualsDeclaration(node), "import= for internal module references should be handled in an earlier transformer.");
let statements: Statement[];
hoistVariableDeclaration(getLocalNameForExternalImport(node, currentSourceFile));
let statements: Statement[] | undefined;
hoistVariableDeclaration(getLocalNameForExternalImport(node, currentSourceFile)!); // TODO: GH#18217
if (hasAssociatedEndOfDeclarationMarker(node)) {
// Defer exports until we encounter an EndOfDeclarationMarker node
const id = getOriginalNodeId(node);
deferredExports[id] = appendExportsOfImportEqualsDeclaration(deferredExports[id], node);
deferredExports[id] = appendExportsOfImportEqualsDeclaration(deferredExports[id]!, node);
}
else {
statements = appendExportsOfImportEqualsDeclaration(statements, node);
@@ -694,7 +694,7 @@ namespace ts {
* @param node The node to visit.
*/
function visitClassDeclaration(node: ClassDeclaration): VisitResult<Statement> {
let statements: Statement[];
let statements: Statement[] | undefined;
// Hoist the name of the class declaration to the outer module body function.
const name = getLocalName(node);
@@ -745,7 +745,7 @@ namespace ts {
return visitNode(node, destructuringAndImportCallVisitor, isStatement);
}
let expressions: Expression[];
let expressions: Expression[] | undefined;
const isExportedDeclaration = hasModifier(node, ModifierFlags.Export);
const isMarkedDeclaration = hasAssociatedEndOfDeclarationMarker(node);
for (const variable of node.declarationList.declarations) {
@@ -757,7 +757,7 @@ namespace ts {
}
}
let statements: Statement[];
let statements: Statement[] | undefined;
if (expressions) {
statements = append(statements, setTextRange(createStatement(inlineExpressions(expressions)), node));
}
@@ -854,7 +854,7 @@ namespace ts {
* @param location The source map location for the assignment.
* @param isExportedDeclaration A value indicating whether the variable is exported.
*/
function createVariableAssignment(name: Identifier, value: Expression, location: TextRange, isExportedDeclaration: boolean) {
function createVariableAssignment(name: Identifier, value: Expression, location: TextRange | undefined, isExportedDeclaration: boolean) {
hoistVariableDeclaration(getSynthesizedClone(name));
return isExportedDeclaration
? createExportExpression(name, preventSubstitution(setTextRange(createAssignment(name, value), location)))
@@ -875,9 +875,9 @@ namespace ts {
//
// To balance the declaration, we defer the exports of the elided variable
// statement until we visit this declaration's `EndOfDeclarationMarker`.
if (hasAssociatedEndOfDeclarationMarker(node) && node.original.kind === SyntaxKind.VariableStatement) {
if (hasAssociatedEndOfDeclarationMarker(node) && node.original!.kind === SyntaxKind.VariableStatement) {
const id = getOriginalNodeId(node);
const isExportedDeclaration = hasModifier(node.original, ModifierFlags.Export);
const isExportedDeclaration = hasModifier(node.original!, ModifierFlags.Export);
deferredExports[id] = appendExportsOfVariableStatement(deferredExports[id], <VariableStatement>node.original, isExportedDeclaration);
}
@@ -928,7 +928,7 @@ namespace ts {
* appended.
* @param decl The declaration whose exports are to be recorded.
*/
function appendExportsOfImportDeclaration(statements: Statement[], decl: ImportDeclaration) {
function appendExportsOfImportDeclaration(statements: Statement[] | undefined, decl: ImportDeclaration) {
if (moduleInfo.exportEquals) {
return statements;
}
@@ -970,7 +970,7 @@ namespace ts {
* appended.
* @param decl The declaration whose exports are to be recorded.
*/
function appendExportsOfImportEqualsDeclaration(statements: Statement[], decl: ImportEqualsDeclaration): Statement[] | undefined {
function appendExportsOfImportEqualsDeclaration(statements: Statement[] | undefined, decl: ImportEqualsDeclaration): Statement[] | undefined {
if (moduleInfo.exportEquals) {
return statements;
}
@@ -1026,7 +1026,7 @@ namespace ts {
}
}
else if (!isGeneratedIdentifier(decl.name)) {
let excludeName: string;
let excludeName: string | undefined;
if (exportSelf) {
statements = appendExportStatement(statements, decl.name, getLocalName(decl));
excludeName = idText(decl.name);
@@ -1052,9 +1052,9 @@ namespace ts {
return statements;
}
let excludeName: string;
let excludeName: string | undefined;
if (hasModifier(decl, ModifierFlags.Export)) {
const exportName = hasModifier(decl, ModifierFlags.Default) ? createLiteral("default") : decl.name;
const exportName = hasModifier(decl, ModifierFlags.Default) ? createLiteral("default") : decl.name!;
statements = appendExportStatement(statements, exportName, getLocalName(decl));
excludeName = getTextOfIdentifierOrLiteral(exportName);
}
@@ -1221,7 +1221,7 @@ namespace ts {
node = updateFor(
node,
visitForInitializer(node.initializer),
node.initializer && visitForInitializer(node.initializer),
visitNode(node.condition, destructuringAndImportCallVisitor, isExpression),
visitNode(node.incrementor, destructuringAndImportCallVisitor, isExpression),
visitNode(node.statement, nestedElementVisitor, isStatement)
@@ -1289,12 +1289,8 @@ namespace ts {
* @param node The node to visit.
*/
function visitForInitializer(node: ForInitializer): ForInitializer {
if (!node) {
return node;
}
if (shouldHoistForInitializer(node)) {
let expressions: Expression[];
let expressions: Expression[] | undefined;
for (const variable of node.declarations) {
expressions = append(expressions, transformInitializedVariable(variable, /*isExportedDeclaration*/ false));
if (!variable.initializer) {
@@ -1598,9 +1594,9 @@ namespace ts {
previousOnEmitNode(hint, node, emitCallback);
currentSourceFile = undefined;
moduleInfo = undefined;
exportFunction = undefined;
currentSourceFile = undefined!;
moduleInfo = undefined!;
exportFunction = undefined!;
noSubstitution = undefined;
}
else {
@@ -1841,7 +1837,7 @@ namespace ts {
* @param name The name.
*/
function getExports(name: Identifier) {
let exportedNames: Identifier[];
let exportedNames: Identifier[] | undefined;
if (!isGeneratedIdentifier(name)) {
const valueDeclaration = resolver.getReferencedImportDeclaration(name)
|| resolver.getReferencedValueDeclaration(name);
+42 -42
View File
@@ -62,7 +62,7 @@ namespace ts {
let currentNamespace: ModuleDeclaration;
let currentNamespaceContainerName: Identifier;
let currentScope: SourceFile | Block | ModuleBlock | CaseBlock;
let currentScopeFirstDeclarationsOfName: UnderscoreEscapedMap<Node>;
let currentScopeFirstDeclarationsOfName: UnderscoreEscapedMap<Node> | undefined;
/**
* Keeps track of whether expression substitution has been enabled for specific edge cases.
@@ -121,7 +121,7 @@ namespace ts {
const visited = saveStateAndInvoke(node, visitSourceFile);
addEmitHelpers(visited, context.readEmitHelpers());
currentSourceFile = undefined;
currentSourceFile = undefined!;
return visited;
}
@@ -625,7 +625,7 @@ namespace ts {
// Write any pending expressions from elided or moved computed property names
if (some(pendingExpressions)) {
statements.push(createStatement(inlineExpressions(pendingExpressions)));
statements.push(createStatement(inlineExpressions(pendingExpressions!)));
}
pendingExpressions = savedPendingExpressions;
@@ -723,7 +723,7 @@ namespace ts {
* @param name The name of the class.
* @param facts Precomputed facts about the class.
*/
function createClassDeclarationHeadWithoutDecorators(node: ClassDeclaration, name: Identifier, facts: ClassFacts) {
function createClassDeclarationHeadWithoutDecorators(node: ClassDeclaration, name: Identifier | undefined, facts: ClassFacts) {
// ${modifiers} class ${name} ${heritageClauses} {
// ${members}
// }
@@ -759,7 +759,7 @@ namespace ts {
* Transforms a decorated class declaration and appends the resulting statements. If
* the class requires an alias to avoid issues with double-binding, the alias is returned.
*/
function createClassDeclarationHeadWithDecorators(node: ClassDeclaration, name: Identifier, facts: ClassFacts) {
function createClassDeclarationHeadWithDecorators(node: ClassDeclaration, name: Identifier | undefined, facts: ClassFacts) {
// When we emit an ES6 class that has a class decorator, we must tailor the
// emit to certain specific cases.
//
@@ -998,7 +998,7 @@ namespace ts {
*
* @param constructor The constructor declaration.
*/
function transformConstructorParameters(constructor: ConstructorDeclaration) {
function transformConstructorParameters(constructor: ConstructorDeclaration | undefined) {
// The ES2015 spec specifies in 14.5.14. Runtime Semantics: ClassDefinitionEvaluation:
// If constructor is empty, then
// If ClassHeritag_eopt is present and protoParent is not null, then
@@ -1026,7 +1026,7 @@ namespace ts {
* @param constructor The current class constructor.
* @param isDerivedClass A value indicating whether the class has an extends clause that does not extend 'null'.
*/
function transformConstructorBody(node: ClassExpression | ClassDeclaration, constructor: ConstructorDeclaration, isDerivedClass: boolean) {
function transformConstructorBody(node: ClassExpression | ClassDeclaration, constructor: ConstructorDeclaration | undefined, isDerivedClass: boolean) {
let statements: Statement[] = [];
let indexOfFirstStatement = 0;
@@ -1081,7 +1081,7 @@ namespace ts {
if (constructor) {
// The class already had a constructor, so we should add the existing statements, skipping the initial super call.
addRange(statements, visitNodes(constructor.body.statements, visitor, isStatement, indexOfFirstStatement));
addRange(statements, visitNodes(constructor.body!.statements, visitor, isStatement, indexOfFirstStatement));
}
// End the lexical environment.
@@ -1090,7 +1090,7 @@ namespace ts {
createBlock(
setTextRange(
createNodeArray(statements),
/*location*/ constructor ? constructor.body.statements : node.members
/*location*/ constructor ? constructor.body!.statements : node.members
),
/*multiLine*/ true
),
@@ -1266,7 +1266,7 @@ namespace ts {
const propertyName = isComputedPropertyName(property.name) && !isSimpleInlineableExpression(property.name.expression)
? updateComputedPropertyName(property.name, getGeneratedNameForNode(property.name))
: property.name;
const initializer = visitNode(property.initializer, visitor, isExpression);
const initializer = visitNode(property.initializer!, visitor, isExpression);
const memberAccess = createMemberAccessForPropertyName(receiver, propertyName, /*location*/ propertyName);
return createAssignment(memberAccess, initializer);
@@ -1319,8 +1319,8 @@ namespace ts {
* A structure describing the decorators for a class element.
*/
interface AllDecorators {
decorators: ReadonlyArray<Decorator>;
parameters?: ReadonlyArray<ReadonlyArray<Decorator>>;
decorators: ReadonlyArray<Decorator> | undefined;
parameters?: ReadonlyArray<ReadonlyArray<Decorator> | undefined>;
}
/**
@@ -1329,8 +1329,8 @@ namespace ts {
*
* @param node The function-like node.
*/
function getDecoratorsOfParameters(node: FunctionLikeDeclaration) {
let decorators: ReadonlyArray<Decorator>[];
function getDecoratorsOfParameters(node: FunctionLikeDeclaration | undefined) {
let decorators: (ReadonlyArray<Decorator> | undefined)[] | undefined;
if (node) {
const parameters = node.parameters;
for (let i = 0; i < parameters.length; i++) {
@@ -1354,7 +1354,7 @@ namespace ts {
*
* @param node The class node.
*/
function getAllDecoratorsOfConstructor(node: ClassExpression | ClassDeclaration): AllDecorators {
function getAllDecoratorsOfConstructor(node: ClassExpression | ClassDeclaration): AllDecorators | undefined {
const decorators = node.decorators;
const parameters = getDecoratorsOfParameters(getFirstConstructorWithBody(node));
if (!decorators && !parameters) {
@@ -1373,7 +1373,7 @@ namespace ts {
* @param node The class node that contains the member.
* @param member The class member.
*/
function getAllDecoratorsOfClassElement(node: ClassExpression | ClassDeclaration, member: ClassElement): AllDecorators {
function getAllDecoratorsOfClassElement(node: ClassExpression | ClassDeclaration, member: ClassElement): AllDecorators | undefined {
switch (member.kind) {
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
@@ -1396,7 +1396,7 @@ namespace ts {
* @param node The class node that contains the accessor.
* @param accessor The class accessor member.
*/
function getAllDecoratorsOfAccessors(node: ClassExpression | ClassDeclaration, accessor: AccessorDeclaration): AllDecorators {
function getAllDecoratorsOfAccessors(node: ClassExpression | ClassDeclaration, accessor: AccessorDeclaration): AllDecorators | undefined {
if (!accessor.body) {
return undefined;
}
@@ -1421,7 +1421,7 @@ namespace ts {
*
* @param method The class method member.
*/
function getAllDecoratorsOfMethod(method: MethodDeclaration): AllDecorators {
function getAllDecoratorsOfMethod(method: MethodDeclaration): AllDecorators | undefined {
if (!method.body) {
return undefined;
}
@@ -1440,7 +1440,7 @@ namespace ts {
*
* @param property The class property member.
*/
function getAllDecoratorsOfProperty(property: PropertyDeclaration): AllDecorators {
function getAllDecoratorsOfProperty(property: PropertyDeclaration): AllDecorators | undefined {
const decorators = property.decorators;
if (!decorators) {
return undefined;
@@ -1456,7 +1456,7 @@ namespace ts {
* @param node The declaration node.
* @param allDecorators An object containing all of the decorators for the declaration.
*/
function transformAllDecoratorsOfDeclaration(node: Declaration, container: ClassLikeDeclaration, allDecorators: AllDecorators) {
function transformAllDecoratorsOfDeclaration(node: Declaration, container: ClassLikeDeclaration, allDecorators: AllDecorators | undefined) {
if (!allDecorators) {
return undefined;
}
@@ -1490,7 +1490,7 @@ namespace ts {
*/
function generateClassElementDecorationExpressions(node: ClassExpression | ClassDeclaration, isStatic: boolean) {
const members = getDecoratedClassElements(node, isStatic);
let expressions: Expression[];
let expressions: Expression[] | undefined;
for (const member of members) {
const expression = generateClassElementDecorationExpression(node, member);
if (expression) {
@@ -1624,7 +1624,7 @@ namespace ts {
* @param parameterOffset The offset of the parameter.
*/
function transformDecoratorsOfParameter(decorators: Decorator[], parameterOffset: number) {
let expressions: Expression[];
let expressions: Expression[] | undefined;
if (decorators) {
expressions = [];
for (const decorator of decorators) {
@@ -1672,7 +1672,7 @@ namespace ts {
function addNewTypeMetadata(node: Declaration, container: ClassLikeDeclaration, decoratorExpressions: Expression[]) {
if (compilerOptions.emitDecoratorMetadata) {
let properties: ObjectLiteralElementLike[];
let properties: ObjectLiteralElementLike[] | undefined;
if (shouldAddTypeMetadata(node)) {
(properties || (properties = [])).push(createPropertyAssignment("type", createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, createToken(SyntaxKind.EqualsGreaterThanToken), serializeTypeOfNode(node))));
}
@@ -1837,7 +1837,7 @@ namespace ts {
*
* @param node The type node to serialize.
*/
function serializeTypeNode(node: TypeNode): SerializedTypeNode {
function serializeTypeNode(node: TypeNode | undefined): SerializedTypeNode {
if (node === undefined) {
return createIdentifier("Object");
}
@@ -1920,7 +1920,7 @@ namespace ts {
function serializeUnionOrIntersectionType(node: UnionOrIntersectionTypeNode): SerializedTypeNode {
// Note when updating logic here also update getEntityNameForDecoratorMetadata
// so that aliases can be marked as referenced
let serializedUnion: SerializedTypeNode;
let serializedUnion: SerializedTypeNode | undefined;
for (let typeNode of node.types) {
while (typeNode.kind === SyntaxKind.ParenthesizedType) {
typeNode = (typeNode as ParenthesizedTypeNode).type; // Skip parens if need be
@@ -2102,7 +2102,7 @@ namespace ts {
* @param member The member whose name should be converted into an expression.
*/
function getExpressionForPropertyName(member: ClassElement | EnumMember, generateNameForComputedPropertyName: boolean): Expression {
const name = member.name;
const name = member.name!;
if (isComputedPropertyName(name)) {
return generateNameForComputedPropertyName && !isSimpleInlineableExpression(name.expression)
? getGeneratedNameForNode(name)
@@ -2122,7 +2122,7 @@ namespace ts {
* @param shouldHoist Does the expression need to be reused? (ie, for an initializer or a decorator)
* @param omitSimple Should expressions with no observable side-effects be elided? (ie, the expression is not hoisted for a decorator or initializer and is a literal)
*/
function getPropertyNameExpressionIfNeeded(name: PropertyName, shouldHoist: boolean, omitSimple: boolean): Expression {
function getPropertyNameExpressionIfNeeded(name: PropertyName, shouldHoist: boolean, omitSimple: boolean): Expression | undefined {
if (isComputedPropertyName(name)) {
const expression = visitNode(name.expression, visitor, isExpression);
const innerExpression = skipPartiallyEmittedExpressions(expression);
@@ -2144,7 +2144,7 @@ namespace ts {
* @param member The member whose name should be visited.
*/
function visitPropertyNameOfClassElement(member: ClassElement): PropertyName {
const name = member.name;
const name = member.name!;
let expr = getPropertyNameExpressionIfNeeded(name, some(member.decorators), /*omitSimple*/ false);
if (expr) { // expr only exists if `name` is a computed property name
// Inline any pending expressions from previous elided or relocated computed property name expressions in order to preserve execution order
@@ -2168,7 +2168,7 @@ namespace ts {
*
* @param node The HeritageClause to transform.
*/
function visitHeritageClause(node: HeritageClause): HeritageClause {
function visitHeritageClause(node: HeritageClause): HeritageClause | undefined {
if (node.token === SyntaxKind.ExtendsKeyword) {
const types = visitNodes(node.types, visitor, isExpressionWithTypeArguments, 0, 1);
return setTextRange(
@@ -2455,7 +2455,7 @@ namespace ts {
* This function will be called when one of the following conditions are met:
* - The node is exported from a TypeScript namespace.
*/
function visitVariableStatement(node: VariableStatement): Statement {
function visitVariableStatement(node: VariableStatement): Statement | undefined {
if (isExportOfNamespace(node)) {
const variables = getInitializedVariables(node.declarationList);
if (variables.length === 0) {
@@ -2493,7 +2493,7 @@ namespace ts {
return setTextRange(
createAssignment(
getNamespaceMemberNameWithSourceMapsAndWithoutComments(name),
visitNode(node.initializer, visitor, isExpression)
visitNode(node.initializer!, visitor, isExpression)
),
/*location*/ node
);
@@ -2766,7 +2766,7 @@ namespace ts {
* @param node The module declaration node.
*/
function shouldEmitModuleDeclaration(node: ModuleDeclaration) {
return isInstantiatedModule(node, compilerOptions.preserveConstEnums || compilerOptions.isolatedModules);
return isInstantiatedModule(node, !!compilerOptions.preserveConstEnums || !!compilerOptions.isolatedModules);
}
/**
@@ -2984,8 +2984,8 @@ namespace ts {
startLexicalEnvironment();
let statementsLocation: TextRange;
let blockLocation: TextRange;
const body = node.body;
let blockLocation: TextRange | undefined;
const body = node.body!;
if (body.kind === SyntaxKind.ModuleBlock) {
saveStateAndInvoke(body, body => addRange(statements, visitNodes((<ModuleBlock>body).statements, namespaceElementVisitor, isStatement)));
statementsLocation = body.statements;
@@ -3002,7 +3002,7 @@ namespace ts {
}
}
const moduleBlock = <ModuleBlock>getInnerMostModuleDeclarationFromDottedModule(node).body;
const moduleBlock = <ModuleBlock>getInnerMostModuleDeclarationFromDottedModule(node)!.body;
statementsLocation = moveRangePos(moduleBlock.statements, -1);
}
@@ -3046,8 +3046,8 @@ namespace ts {
return block;
}
function getInnerMostModuleDeclarationFromDottedModule(moduleDeclaration: ModuleDeclaration): ModuleDeclaration {
if (moduleDeclaration.body.kind === SyntaxKind.ModuleDeclaration) {
function getInnerMostModuleDeclarationFromDottedModule(moduleDeclaration: ModuleDeclaration): ModuleDeclaration | undefined {
if (moduleDeclaration.body!.kind === SyntaxKind.ModuleDeclaration) {
const recursiveInnerModule = getInnerMostModuleDeclarationFromDottedModule(<ModuleDeclaration>moduleDeclaration.body);
return recursiveInnerModule || <ModuleDeclaration>moduleDeclaration.body;
}
@@ -3138,7 +3138,7 @@ namespace ts {
function visitExportDeclaration(node: ExportDeclaration): VisitResult<Statement> {
if (!node.exportClause) {
// Elide a star export if the module it references does not export a value.
return compilerOptions.isolatedModules || resolver.moduleExportsSomeValue(node.moduleSpecifier) ? node : undefined;
return compilerOptions.isolatedModules || resolver.moduleExportsSomeValue(node.moduleSpecifier!) ? node : undefined;
}
if (!resolver.isValueAliasDeclaration(node)) {
@@ -3494,7 +3494,7 @@ namespace ts {
|| node;
}
function trySubstituteClassAlias(node: Identifier): Expression {
function trySubstituteClassAlias(node: Identifier): Expression | undefined {
if (enabledSubstitutions & TypeScriptSubstitutionFlags.ClassAliases) {
if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.ConstructorReferenceInClass) {
// Due to the emit for class decorators, any reference to the class from inside of the class body
@@ -3504,7 +3504,7 @@ namespace ts {
// constructor references in static property initializers.
const declaration = resolver.getReferencedValueDeclaration(node);
if (declaration) {
const classAlias = classAliases[declaration.id];
const classAlias = classAliases[declaration.id!]; // TODO: GH#18217
if (classAlias) {
const clone = getSynthesizedClone(classAlias);
setSourceMapRange(clone, node);
@@ -3518,7 +3518,7 @@ namespace ts {
return undefined;
}
function trySubstituteNamespaceExportedName(node: Identifier): Expression {
function trySubstituteNamespaceExportedName(node: Identifier): Expression | undefined {
// If this is explicitly a local name, do not substitute.
if (enabledSubstitutions & applicableSubstitutions && !isGeneratedIdentifier(node) && !isLocalName(node)) {
// If we are nested within a namespace declaration, we may need to qualifiy
@@ -3569,7 +3569,7 @@ namespace ts {
return node;
}
function tryGetConstEnumValue(node: Node): string | number {
function tryGetConstEnumValue(node: Node): string | number | undefined {
if (compilerOptions.isolatedModules) {
return undefined;
}
+12 -12
View File
@@ -10,19 +10,19 @@ namespace ts {
externalHelpersImportDeclaration: ImportDeclaration | undefined; // import of external helpers
exportSpecifiers: Map<ExportSpecifier[]>; // export specifiers by name
exportedBindings: Identifier[][]; // exported names of local declarations
exportedNames: Identifier[]; // all exported names local to module
exportedNames: Identifier[] | undefined; // all exported names local to module
exportEquals: ExportAssignment | undefined; // an export= declaration if one was present
hasExportStarsToExportValues: boolean; // whether this module contains export*
}
function containsDefaultReference(node: NamedImportBindings) {
function containsDefaultReference(node: NamedImportBindings | undefined) {
if (!node) return false;
if (!isNamedImports(node)) return false;
return some(node.elements, isNamedDefaultReference);
}
function isNamedDefaultReference(e: ImportSpecifier) {
return e.propertyName && e.propertyName.escapedText === InternalSymbolName.Default;
function isNamedDefaultReference(e: ImportSpecifier): boolean {
return e.propertyName !== undefined && e.propertyName.escapedText === InternalSymbolName.Default;
}
export function chainBundle(transformSourceFile: (x: SourceFile) => SourceFile): (x: SourceFile | Bundle) => SourceFile | Bundle {
@@ -37,7 +37,7 @@ namespace ts {
}
}
export function getImportNeedsImportStarHelper(node: ImportDeclaration) {
export function getImportNeedsImportStarHelper(node: ImportDeclaration): boolean {
if (!!getNamespaceDeclarationNode(node)) {
return true;
}
@@ -56,9 +56,9 @@ namespace ts {
return (defaultRefCount > 0 && defaultRefCount !== bindings.elements.length) || (!!(bindings.elements.length - defaultRefCount) && isDefaultImport(node));
}
export function getImportNeedsImportDefaultHelper(node: ImportDeclaration) {
export function getImportNeedsImportDefaultHelper(node: ImportDeclaration): boolean {
// Import default is needed if there's a default import or a default ref and no other refs (meaning an import star helper wasn't requested)
return !getImportNeedsImportStarHelper(node) && (isDefaultImport(node) || (node.importClause && isNamedImports(node.importClause.namedBindings) && containsDefaultReference(node.importClause.namedBindings)));
return !getImportNeedsImportStarHelper(node) && (isDefaultImport(node) || (!!node.importClause && isNamedImports(node.importClause.namedBindings!) && containsDefaultReference(node.importClause.namedBindings))); // TODO: GH#18217
}
export function collectExternalModuleInfo(sourceFile: SourceFile, resolver: EmitResolver, compilerOptions: CompilerOptions): ExternalModuleInfo {
@@ -66,9 +66,9 @@ namespace ts {
const exportSpecifiers = createMultiMap<ExportSpecifier>();
const exportedBindings: Identifier[][] = [];
const uniqueExports = createMap<boolean>();
let exportedNames: Identifier[];
let exportedNames: Identifier[] | undefined;
let hasExportDefault = false;
let exportEquals: ExportAssignment;
let exportEquals: ExportAssignment | undefined;
let hasExportStarsToExportValues = false;
let hasImportStarOrImportDefault = false;
@@ -105,7 +105,7 @@ namespace ts {
}
else {
// export { x, y }
for (const specifier of (<ExportDeclaration>node).exportClause.elements) {
for (const specifier of (<ExportDeclaration>node).exportClause!.elements) {
if (!uniqueExports.get(idText(specifier.name))) {
const name = specifier.propertyName || specifier.name;
exportSpecifiers.add(idText(name), specifier);
@@ -150,7 +150,7 @@ namespace ts {
}
else {
// export function x() { }
const name = (<FunctionDeclaration>node).name;
const name = (<FunctionDeclaration>node).name!;
if (!uniqueExports.get(idText(name))) {
multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), name);
uniqueExports.set(idText(name), true);
@@ -198,7 +198,7 @@ namespace ts {
return { externalImports, exportSpecifiers, exportEquals, hasExportStarsToExportValues, exportedBindings, exportedNames, externalHelpersImportDeclaration };
}
function collectExportedVariableInfo(decl: VariableDeclaration | BindingElement, uniqueExports: Map<boolean>, exportedNames: Identifier[]) {
function collectExportedVariableInfo(decl: VariableDeclaration | BindingElement, uniqueExports: Map<boolean>, exportedNames: Identifier[] | undefined) {
if (isBindingPattern(decl.name)) {
for (const element of decl.name.elements) {
if (!isOmittedExpression(element)) {
+7 -7
View File
@@ -50,7 +50,7 @@ namespace ts {
const commandLine = parseCommandLine(args);
// Configuration file name (if any)
let configFileName: string;
let configFileName: string | undefined;
if (commandLine.options.locale) {
validateLocaleAndSetLanguage(commandLine.options.locale, sys, commandLine.errors);
}
@@ -74,7 +74,7 @@ namespace ts {
if (commandLine.options.help || commandLine.options.all) {
printVersion();
printHelp(commandLine.options.all);
printHelp(!!commandLine.options.all);
return sys.exit(ExitStatus.Success);
}
@@ -107,13 +107,13 @@ namespace ts {
if (commandLine.fileNames.length === 0 && !configFileName) {
printVersion();
printHelp(commandLine.options.all);
printHelp(!!commandLine.options.all);
return sys.exit(ExitStatus.Success);
}
const commandLineOptions = commandLine.options;
if (configFileName) {
const configParseResult = parseConfigFileWithSystem(configFileName, commandLineOptions, sys, reportDiagnostic);
const configParseResult = parseConfigFileWithSystem(configFileName, commandLineOptions, sys, reportDiagnostic)!; // TODO: GH#18217
updateReportDiagnostic(configParseResult.options);
if (isWatchSet(configParseResult.options)) {
reportWatchModeWithoutSysSupport();
@@ -168,7 +168,7 @@ namespace ts {
}
return compileUsingBuilder(rootNames, options, host, oldProgram, configFileParsingDiagnostics);
};
const emitFilesUsingBuilder = watchCompilerHost.afterProgramCreate;
const emitFilesUsingBuilder = watchCompilerHost.afterProgramCreate!; // TODO: GH#18217
watchCompilerHost.afterProgramCreate = builderProgram => {
emitFilesUsingBuilder(builderProgram);
reportStatistics(builderProgram.getProgram());
@@ -180,7 +180,7 @@ namespace ts {
}
function createWatchOfConfigFile(configParseResult: ParsedCommandLine, optionsToExtend: CompilerOptions) {
const watchCompilerHost = createWatchCompilerHostOfConfigFile(configParseResult.options.configFilePath, optionsToExtend, sys, /*createProgram*/ undefined, reportDiagnostic, createWatchStatusReporter(configParseResult.options));
const watchCompilerHost = createWatchCompilerHostOfConfigFile(configParseResult.options.configFilePath!, optionsToExtend, sys, /*createProgram*/ undefined, reportDiagnostic, createWatchStatusReporter(configParseResult.options)); // TODO: GH#18217
updateWatchCompilationHost(watchCompilerHost);
watchCompilerHost.configFileParsingResult = configParseResult;
createWatchProgram(watchCompilerHost);
@@ -302,7 +302,7 @@ namespace ts {
// Sort our options by their names, (e.g. "--noImplicitAny" comes before "--watch")
const optsList = showAllOptions ?
sort(optionDeclarations, (a, b) => compareStringsCaseInsensitive(a.name, b.name)) :
filter(optionDeclarations.slice(), v => v.showInSimplifiedHelpView);
filter(optionDeclarations.slice(), v => !!v.showInSimplifiedHelpView);
// We want our descriptions to align at the same column in our output,
// so we keep track of the longest option usage string.
+162 -156
View File
@@ -574,13 +574,13 @@ namespace ts {
kind: SyntaxKind;
flags: NodeFlags;
/* @internal */ modifierFlagsCache?: ModifierFlags;
/* @internal */ transformFlags?: TransformFlags;
/* @internal */ transformFlags: TransformFlags; // Flags for transforms, possibly undefined
decorators?: NodeArray<Decorator>; // Array of decorators (in document order)
modifiers?: ModifiersArray; // Array of modifiers
/* @internal */ id?: number; // Unique id (used to look up NodeLinks)
parent?: Node; // Parent node (initialized by binding)
parent: Node; // Parent node (initialized by binding)
/* @internal */ original?: Node; // The original node if this is an updated node.
/* @internal */ symbol?: Symbol; // Symbol declared by node (initialized by binding)
/* @internal */ symbol: Symbol; // Symbol declared by node (initialized by binding)
/* @internal */ locals?: SymbolTable; // Locals associated with node (initialized by binding)
/* @internal */ nextContainer?: Node; // Next container in declaration order (initialized by binding)
/* @internal */ localSymbol?: Symbol; // Local symbol declared by node (initialized by binding only for exported nodes)
@@ -667,7 +667,7 @@ namespace ts {
export interface NodeArray<T extends Node> extends ReadonlyArray<T>, TextRange {
hasTrailingComma?: boolean;
/* @internal */ transformFlags?: TransformFlags;
/* @internal */ transformFlags: TransformFlags; // Flags for transforms, possibly undefined
}
export interface Token<TKind extends SyntaxKind> extends Node {
@@ -794,13 +794,13 @@ namespace ts {
export interface Decorator extends Node {
kind: SyntaxKind.Decorator;
parent?: NamedDeclaration;
parent: NamedDeclaration;
expression: LeftHandSideExpression;
}
export interface TypeParameterDeclaration extends NamedDeclaration {
kind: SyntaxKind.TypeParameter;
parent?: DeclarationWithTypeParameters | InferTypeNode;
parent: DeclarationWithTypeParameters | InferTypeNode;
name: Identifier;
constraint?: TypeNode;
default?: TypeNode;
@@ -814,7 +814,7 @@ namespace ts {
name?: PropertyName;
typeParameters?: NodeArray<TypeParameterDeclaration>;
parameters: NodeArray<ParameterDeclaration>;
type: TypeNode | undefined;
type?: TypeNode;
/* @internal */ typeArguments?: NodeArray<TypeNode>; // Used for quick info, replaces typeParameters for instantiated signatures
}
@@ -845,7 +845,7 @@ namespace ts {
export interface VariableDeclaration extends NamedDeclaration {
kind: SyntaxKind.VariableDeclaration;
parent?: VariableDeclarationList | CatchClause;
parent: VariableDeclarationList | CatchClause;
name: BindingName; // Declared variable name
exclamationToken?: ExclamationToken; // Optional definite assignment assertion
type?: TypeNode; // Optional type annotation
@@ -854,13 +854,13 @@ namespace ts {
export interface VariableDeclarationList extends Node {
kind: SyntaxKind.VariableDeclarationList;
parent?: VariableStatement | ForStatement | ForOfStatement | ForInStatement;
parent: VariableStatement | ForStatement | ForOfStatement | ForInStatement;
declarations: NodeArray<VariableDeclaration>;
}
export interface ParameterDeclaration extends NamedDeclaration, JSDocContainer {
kind: SyntaxKind.Parameter;
parent?: SignatureDeclaration;
parent: SignatureDeclaration;
dotDotDotToken?: DotDotDotToken; // Present on rest parameter
name: BindingName; // Declared parameter name.
questionToken?: QuestionToken; // Present on optional parameter
@@ -870,7 +870,7 @@ namespace ts {
export interface BindingElement extends NamedDeclaration {
kind: SyntaxKind.BindingElement;
parent?: BindingPattern;
parent: BindingPattern;
propertyName?: PropertyName; // Binding property name (in object binding pattern)
dotDotDotToken?: DotDotDotToken; // Present on rest element (in object binding pattern)
name: BindingName; // Declared binding element name
@@ -955,13 +955,13 @@ namespace ts {
export interface ObjectBindingPattern extends Node {
kind: SyntaxKind.ObjectBindingPattern;
parent?: VariableDeclaration | ParameterDeclaration | BindingElement;
parent: VariableDeclaration | ParameterDeclaration | BindingElement;
elements: NodeArray<BindingElement>;
}
export interface ArrayBindingPattern extends Node {
kind: SyntaxKind.ArrayBindingPattern;
parent?: VariableDeclaration | ParameterDeclaration | BindingElement;
parent: VariableDeclaration | ParameterDeclaration | BindingElement;
elements: NodeArray<ArrayBindingElement>;
}
@@ -1004,7 +1004,7 @@ namespace ts {
export interface MethodSignature extends SignatureDeclarationBase, TypeElement {
kind: SyntaxKind.MethodSignature;
parent?: ObjectTypeDeclaration;
parent: ObjectTypeDeclaration;
name: PropertyName;
}
@@ -1019,14 +1019,14 @@ namespace ts {
// of the method, or use helpers like isObjectLiteralMethodDeclaration
export interface MethodDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer {
kind: SyntaxKind.MethodDeclaration;
parent?: ClassLikeDeclaration | ObjectLiteralExpression;
parent: ClassLikeDeclaration | ObjectLiteralExpression;
name: PropertyName;
body?: FunctionBody;
}
export interface ConstructorDeclaration extends FunctionLikeDeclarationBase, ClassElement, JSDocContainer {
kind: SyntaxKind.Constructor;
parent?: ClassLikeDeclaration;
parent: ClassLikeDeclaration;
body?: FunctionBody;
/* @internal */ returnFlowNode?: FlowNode;
}
@@ -1034,14 +1034,14 @@ namespace ts {
/** For when we encounter a semicolon in a class declaration. ES6 allows these as class elements. */
export interface SemicolonClassElement extends ClassElement {
kind: SyntaxKind.SemicolonClassElement;
parent?: ClassLikeDeclaration;
parent: ClassLikeDeclaration;
}
// See the comment on MethodDeclaration for the intuition behind GetAccessorDeclaration being a
// ClassElement and an ObjectLiteralElement.
export interface GetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer {
kind: SyntaxKind.GetAccessor;
parent?: ClassLikeDeclaration | ObjectLiteralExpression;
parent: ClassLikeDeclaration | ObjectLiteralExpression;
name: PropertyName;
body?: FunctionBody;
}
@@ -1050,7 +1050,7 @@ namespace ts {
// ClassElement and an ObjectLiteralElement.
export interface SetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer {
kind: SyntaxKind.SetAccessor;
parent?: ClassLikeDeclaration | ObjectLiteralExpression;
parent: ClassLikeDeclaration | ObjectLiteralExpression;
name: PropertyName;
body?: FunctionBody;
}
@@ -1059,7 +1059,7 @@ namespace ts {
export interface IndexSignatureDeclaration extends SignatureDeclarationBase, ClassElement, TypeElement {
kind: SyntaxKind.IndexSignature;
parent?: ObjectTypeDeclaration;
parent: ObjectTypeDeclaration;
}
export interface TypeNode extends Node {
@@ -1117,7 +1117,7 @@ namespace ts {
export interface TypePredicateNode extends TypeNode {
kind: SyntaxKind.TypePredicate;
parent?: SignatureDeclaration;
parent: SignatureDeclaration;
parameterName: Identifier | ThisTypeNode;
type: TypeNode;
}
@@ -1604,22 +1604,22 @@ namespace ts {
export interface NumericLiteral extends LiteralExpression {
kind: SyntaxKind.NumericLiteral;
/* @internal */
numericLiteralFlags?: TokenFlags;
numericLiteralFlags: TokenFlags;
}
export interface TemplateHead extends LiteralLikeNode {
kind: SyntaxKind.TemplateHead;
parent?: TemplateExpression;
parent: TemplateExpression;
}
export interface TemplateMiddle extends LiteralLikeNode {
kind: SyntaxKind.TemplateMiddle;
parent?: TemplateSpan;
parent: TemplateSpan;
}
export interface TemplateTail extends LiteralLikeNode {
kind: SyntaxKind.TemplateTail;
parent?: TemplateSpan;
parent: TemplateSpan;
}
export type TemplateLiteral = TemplateExpression | NoSubstitutionTemplateLiteral;
@@ -1634,7 +1634,7 @@ namespace ts {
// The template literal must have kind TemplateMiddleLiteral or TemplateTailLiteral.
export interface TemplateSpan extends Node {
kind: SyntaxKind.TemplateSpan;
parent?: TemplateExpression;
parent: TemplateExpression;
expression: Expression;
literal: TemplateMiddle | TemplateTail;
}
@@ -1653,7 +1653,7 @@ namespace ts {
export interface SpreadElement extends Expression {
kind: SyntaxKind.SpreadElement;
parent?: ArrayLiteralExpression | CallExpression | NewExpression;
parent: ArrayLiteralExpression | CallExpression | NewExpression;
expression: Expression;
}
@@ -1724,7 +1724,7 @@ namespace ts {
export interface ExpressionWithTypeArguments extends NodeWithTypeArguments {
kind: SyntaxKind.ExpressionWithTypeArguments;
parent?: HeritageClause;
parent: HeritageClause;
expression: LeftHandSideExpression;
}
@@ -1787,13 +1787,13 @@ namespace ts {
export type JsxTagNameExpression = PrimaryExpression | PropertyAccessExpression;
export interface JsxAttributes extends ObjectLiteralExpressionBase<JsxAttributeLike> {
parent?: JsxOpeningLikeElement;
parent: JsxOpeningLikeElement;
}
/// The opening element of a <Tag>...</Tag> JsxElement
export interface JsxOpeningElement extends Expression {
kind: SyntaxKind.JsxOpeningElement;
parent?: JsxElement;
parent: JsxElement;
tagName: JsxTagNameExpression;
typeArguments?: NodeArray<TypeNode>;
attributes: JsxAttributes;
@@ -1818,18 +1818,18 @@ namespace ts {
/// The opening element of a <>...</> JsxFragment
export interface JsxOpeningFragment extends Expression {
kind: SyntaxKind.JsxOpeningFragment;
parent?: JsxFragment;
parent: JsxFragment;
}
/// The closing element of a <>...</> JsxFragment
export interface JsxClosingFragment extends Expression {
kind: SyntaxKind.JsxClosingFragment;
parent?: JsxFragment;
parent: JsxFragment;
}
export interface JsxAttribute extends ObjectLiteralElement {
kind: SyntaxKind.JsxAttribute;
parent?: JsxAttributes;
parent: JsxAttributes;
name: Identifier;
/// JSX attribute initializers are optional; <X y /> is sugar for <X y={true} />
initializer?: StringLiteral | JsxExpression;
@@ -1837,19 +1837,19 @@ namespace ts {
export interface JsxSpreadAttribute extends ObjectLiteralElement {
kind: SyntaxKind.JsxSpreadAttribute;
parent?: JsxAttributes;
parent: JsxAttributes;
expression: Expression;
}
export interface JsxClosingElement extends Node {
kind: SyntaxKind.JsxClosingElement;
parent?: JsxElement;
parent: JsxElement;
tagName: JsxTagNameExpression;
}
export interface JsxExpression extends Expression {
kind: SyntaxKind.JsxExpression;
parent?: JsxElement | JsxAttributeLike;
parent: JsxElement | JsxAttributeLike;
dotDotDotToken?: Token<SyntaxKind.DotDotDotToken>;
expression?: Expression;
}
@@ -1857,7 +1857,7 @@ namespace ts {
export interface JsxText extends Node {
kind: SyntaxKind.JsxText;
containsOnlyWhiteSpaces: boolean;
parent?: JsxElement;
parent: JsxElement;
}
export type JsxChild = JsxText | JsxExpression | JsxElement | JsxSelfClosingElement | JsxFragment;
@@ -2009,20 +2009,20 @@ namespace ts {
export interface CaseBlock extends Node {
kind: SyntaxKind.CaseBlock;
parent?: SwitchStatement;
parent: SwitchStatement;
clauses: NodeArray<CaseOrDefaultClause>;
}
export interface CaseClause extends Node {
kind: SyntaxKind.CaseClause;
parent?: CaseBlock;
parent: CaseBlock;
expression: Expression;
statements: NodeArray<Statement>;
}
export interface DefaultClause extends Node {
kind: SyntaxKind.DefaultClause;
parent?: CaseBlock;
parent: CaseBlock;
statements: NodeArray<Statement>;
}
@@ -2036,7 +2036,7 @@ namespace ts {
export interface ThrowStatement extends Statement {
kind: SyntaxKind.ThrowStatement;
expression: Expression;
expression?: Expression;
}
export interface TryStatement extends Statement {
@@ -2048,7 +2048,7 @@ namespace ts {
export interface CatchClause extends Node {
kind: SyntaxKind.CatchClause;
parent?: TryStatement;
parent: TryStatement;
variableDeclaration?: VariableDeclaration;
block: Block;
}
@@ -2098,7 +2098,7 @@ namespace ts {
export interface HeritageClause extends Node {
kind: SyntaxKind.HeritageClause;
parent?: InterfaceDeclaration | ClassLikeDeclaration;
parent: InterfaceDeclaration | ClassLikeDeclaration;
token: SyntaxKind.ExtendsKeyword | SyntaxKind.ImplementsKeyword;
types: NodeArray<ExpressionWithTypeArguments>;
}
@@ -2112,7 +2112,7 @@ namespace ts {
export interface EnumMember extends NamedDeclaration, JSDocContainer {
kind: SyntaxKind.EnumMember;
parent?: EnumDeclaration;
parent: EnumDeclaration;
// This does include ComputedPropertyName, but the parser will give an error
// if it parses a ComputedPropertyName in an EnumMember
name: PropertyName;
@@ -2134,7 +2134,7 @@ namespace ts {
export interface ModuleDeclaration extends DeclarationStatement, JSDocContainer {
kind: SyntaxKind.ModuleDeclaration;
parent?: ModuleBody | SourceFile;
parent: ModuleBody | SourceFile;
name: ModuleName;
body?: ModuleBody | JSDocNamespaceDeclaration;
}
@@ -2150,12 +2150,12 @@ namespace ts {
export interface JSDocNamespaceDeclaration extends ModuleDeclaration {
name: Identifier;
body: JSDocNamespaceBody;
body?: JSDocNamespaceBody;
}
export interface ModuleBlock extends Node, Statement {
kind: SyntaxKind.ModuleBlock;
parent?: ModuleDeclaration;
parent: ModuleDeclaration;
statements: NodeArray<Statement>;
}
@@ -2168,7 +2168,7 @@ namespace ts {
*/
export interface ImportEqualsDeclaration extends DeclarationStatement, JSDocContainer {
kind: SyntaxKind.ImportEqualsDeclaration;
parent?: SourceFile | ModuleBlock;
parent: SourceFile | ModuleBlock;
name: Identifier;
// 'EntityName' for an internal module reference, 'ExternalModuleReference' for an external
@@ -2178,8 +2178,8 @@ namespace ts {
export interface ExternalModuleReference extends Node {
kind: SyntaxKind.ExternalModuleReference;
parent?: ImportEqualsDeclaration;
expression?: Expression;
parent: ImportEqualsDeclaration;
expression: Expression;
}
// In case of:
@@ -2188,7 +2188,7 @@ namespace ts {
// ImportClause information is shown at its declaration below.
export interface ImportDeclaration extends Statement {
kind: SyntaxKind.ImportDeclaration;
parent?: SourceFile | ModuleBlock;
parent: SourceFile | ModuleBlock;
importClause?: ImportClause;
/** If this is not a StringLiteral it will be a grammar error. */
moduleSpecifier: Expression;
@@ -2204,14 +2204,14 @@ namespace ts {
// import d, { a, b as x } from "mod" => name = d, namedBinding: NamedImports = { elements: [{ name: a }, { name: x, propertyName: b}]}
export interface ImportClause extends NamedDeclaration {
kind: SyntaxKind.ImportClause;
parent?: ImportDeclaration;
parent: ImportDeclaration;
name?: Identifier; // Default binding
namedBindings?: NamedImportBindings;
}
export interface NamespaceImport extends NamedDeclaration {
kind: SyntaxKind.NamespaceImport;
parent?: ImportClause;
parent: ImportClause;
name: Identifier;
}
@@ -2222,7 +2222,7 @@ namespace ts {
export interface ExportDeclaration extends DeclarationStatement {
kind: SyntaxKind.ExportDeclaration;
parent?: SourceFile | ModuleBlock;
parent: SourceFile | ModuleBlock;
/** Will not be assigned in the case of `export * from "foo";` */
exportClause?: NamedExports;
/** If this is not a StringLiteral it will be a grammar error. */
@@ -2231,13 +2231,13 @@ namespace ts {
export interface NamedImports extends Node {
kind: SyntaxKind.NamedImports;
parent?: ImportClause;
parent: ImportClause;
elements: NodeArray<ImportSpecifier>;
}
export interface NamedExports extends Node {
kind: SyntaxKind.NamedExports;
parent?: ExportDeclaration;
parent: ExportDeclaration;
elements: NodeArray<ExportSpecifier>;
}
@@ -2245,14 +2245,14 @@ namespace ts {
export interface ImportSpecifier extends NamedDeclaration {
kind: SyntaxKind.ImportSpecifier;
parent?: NamedImports;
parent: NamedImports;
propertyName?: Identifier; // Name preceding "as" keyword (or undefined when "as" is absent)
name: Identifier; // Declared name
}
export interface ExportSpecifier extends NamedDeclaration {
kind: SyntaxKind.ExportSpecifier;
parent?: NamedExports;
parent: NamedExports;
propertyName?: Identifier; // Name preceding "as" keyword (or undefined when "as" is absent)
name: Identifier; // Declared name
}
@@ -2265,7 +2265,7 @@ namespace ts {
*/
export interface ExportAssignment extends DeclarationStatement {
kind: SyntaxKind.ExportAssignment;
parent?: SourceFile;
parent: SourceFile;
isExportEquals?: boolean;
expression: Expression;
}
@@ -2337,16 +2337,16 @@ namespace ts {
export interface JSDoc extends Node {
kind: SyntaxKind.JSDocComment;
parent?: HasJSDoc;
tags: NodeArray<JSDocTag> | undefined;
comment: string | undefined;
parent: HasJSDoc;
tags?: NodeArray<JSDocTag>;
comment?: string;
}
export interface JSDocTag extends Node {
parent: JSDoc | JSDocTypeLiteral;
atToken: AtToken;
tagName: Identifier;
comment: string | undefined;
comment?: string;
}
export interface JSDocUnknownTag extends JSDocTag {
@@ -2373,12 +2373,12 @@ namespace ts {
export interface JSDocReturnTag extends JSDocTag {
kind: SyntaxKind.JSDocReturnTag;
typeExpression: JSDocTypeExpression;
typeExpression?: JSDocTypeExpression;
}
export interface JSDocTypeTag extends JSDocTag {
kind: SyntaxKind.JSDocTypeTag;
typeExpression: JSDocTypeExpression;
typeExpression?: JSDocTypeExpression;
}
export interface JSDocTypedefTag extends JSDocTag, NamedDeclaration {
@@ -2475,7 +2475,7 @@ namespace ts {
// FlowLabel represents a junction with multiple possible preceding control flows.
export interface FlowLabel extends FlowNodeBase {
antecedents: FlowNode[];
antecedents: FlowNode[] | undefined;
}
// FlowAssignment represents a node that assigns a value to a narrowable reference,
@@ -2518,7 +2518,7 @@ namespace ts {
export interface AmdDependency {
path: string;
name: string;
name?: string;
}
/* @internal */
@@ -2557,10 +2557,10 @@ namespace ts {
* (See `createRedirectSourceFile` in program.ts.)
* The redirect will have this set. The redirected-to source file will be in `redirectTargetsSet`.
*/
/* @internal */ redirectInfo?: RedirectInfo | undefined;
/* @internal */ redirectInfo?: RedirectInfo;
amdDependencies: ReadonlyArray<AmdDependency>;
moduleName: string;
moduleName?: string;
referencedFiles: ReadonlyArray<FileReference>;
typeReferenceDirectives: ReadonlyArray<FileReference>;
languageVariant: LanguageVariant;
@@ -2588,9 +2588,9 @@ namespace ts {
* This is intended to be the first top-level import/export,
* but could be arbitrarily nested (e.g. `import.meta`).
*/
/* @internal */ externalModuleIndicator: Node;
/* @internal */ externalModuleIndicator?: Node;
// The first node that causes this file to be a CommonJS module
/* @internal */ commonJsModuleIndicator: Node;
/* @internal */ commonJsModuleIndicator?: Node;
/* @internal */ identifiers: Map<string>; // Map from a string to an interned string
/* @internal */ nodeCount: number;
@@ -2618,7 +2618,7 @@ namespace ts {
// Stores a mapping 'external module reference text' -> 'resolved file name' | undefined
// It is used to resolve module names in the checker.
// Content of this field should never be used directly - use getResolvedModuleFileName/setResolvedModuleFileName functions instead
/* @internal */ resolvedModules: Map<ResolvedModuleFull | undefined>;
/* @internal */ resolvedModules?: Map<ResolvedModuleFull | undefined>;
/* @internal */ resolvedTypeReferenceDirectiveNames: Map<ResolvedTypeReferenceDirective>;
/* @internal */ imports: ReadonlyArray<StringLiteralLike>;
/**
@@ -2631,7 +2631,7 @@ namespace ts {
/* @internal */ moduleAugmentations: ReadonlyArray<StringLiteral | Identifier>;
/* @internal */ patternAmbientModules?: PatternAmbientModule[];
/* @internal */ ambientModuleNames: ReadonlyArray<string>;
/* @internal */ checkJsDirective: CheckJsDirective | undefined;
/* @internal */ checkJsDirective?: CheckJsDirective;
/* @internal */ version: string;
/* @internal */ pragmas: PragmaMap;
/* @internal */ localJsxNamespace?: __String;
@@ -2702,7 +2702,7 @@ namespace ts {
data: string,
writeByteOrderMark: boolean,
onError: ((message: string) => void) | undefined,
sourceFiles: ReadonlyArray<SourceFile>,
sourceFiles?: ReadonlyArray<SourceFile>,
) => void;
export class OperationCanceledException { }
@@ -2714,6 +2714,7 @@ namespace ts {
throwIfCancellationRequested(): void;
}
// TODO: This should implement TypeCheckerHost but that's an internal type.
export interface Program extends ScriptReferenceHost {
/**
@@ -2861,8 +2862,8 @@ namespace ts {
emitSkipped: boolean;
/** Contains declaration emit diagnostics */
diagnostics: ReadonlyArray<Diagnostic>;
emittedFiles: string[]; // Array of files the compiler wrote to disk
/* @internal */ sourceMaps: SourceMapData[]; // Array of sourceMapData if compiler emitted sourcemaps
emittedFiles?: string[]; // Array of files the compiler wrote to disk
/* @internal */ sourceMaps?: SourceMapData[]; // Array of sourceMapData if compiler emitted sourcemaps
}
/* @internal */
@@ -2894,9 +2895,10 @@ namespace ts {
getNullableType(type: Type, flags: TypeFlags): Type;
getNonNullableType(type: Type): Type;
// TODO: GH#18217 `xToDeclaration` calls are frequently asserted as defined.
/** Note that the resulting nodes cannot be checked. */
typeToTypeNode(type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): TypeNode;
/* @internal */ typeToTypeNode(type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker): TypeNode; // tslint:disable-line unified-signatures
typeToTypeNode(type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): TypeNode | undefined;
/* @internal */ typeToTypeNode(type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker): TypeNode | undefined; // tslint:disable-line unified-signatures
/** Note that the resulting nodes cannot be checked. */
signatureToSignatureDeclaration(signature: Signature, kind: SyntaxKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): SignatureDeclaration & {typeArguments?: NodeArray<TypeNode>} | undefined;
/** Note that the resulting nodes cannot be checked. */
@@ -2931,7 +2933,7 @@ namespace ts {
*/
getExportSymbolOfSymbol(symbol: Symbol): Symbol;
getPropertySymbolOfDestructuringAssignment(location: Identifier): Symbol | undefined;
getTypeAtLocation(node: Node): Type;
getTypeAtLocation(node: Node): Type | undefined;
getTypeFromTypeNode(node: TypeNode): Type;
signatureToString(signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): string;
@@ -2953,15 +2955,16 @@ namespace ts {
getAugmentedPropertiesOfType(type: Type): Symbol[];
getRootSymbols(symbol: Symbol): Symbol[];
getContextualType(node: Expression): Type | undefined;
/* @internal */ getContextualTypeForArgumentAtIndex(call: CallLikeExpression, argIndex: number): Type;
/* @internal */ getContextualTypeForArgumentAtIndex(call: CallLikeExpression, argIndex: number): Type | undefined;
/* @internal */ getContextualTypeForJsxAttribute(attribute: JsxAttribute | JsxSpreadAttribute): Type | undefined;
/* @internal */ isContextSensitive(node: Expression | MethodDeclaration | ObjectLiteralElementLike | JsxAttributeLike): boolean;
/**
* returns unknownSignature in the case of an error.
* returns undefined if the node is not valid.
* @param argumentCount Apparent number of arguments, passed in case of a possibly incomplete call. This should come from an ArgumentListInfo. See `signatureHelp.ts`.
*/
getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[], argumentCount?: number): Signature;
getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[], argumentCount?: number): Signature | undefined;
getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature | undefined;
isImplementationOfOverload(node: SignatureDeclaration): boolean | undefined;
isUndefinedSymbol(symbol: Symbol): boolean;
@@ -2976,7 +2979,7 @@ namespace ts {
/** Follow all aliases to get the original symbol. */
getAliasedSymbol(symbol: Symbol): Symbol;
/** Follow a *single* alias to get the immediately aliased symbol. */
/* @internal */ getImmediateAliasedSymbol(symbol: Symbol): Symbol;
/* @internal */ getImmediateAliasedSymbol(symbol: Symbol): Symbol | undefined;
getExportsOfModule(moduleSymbol: Symbol): Symbol[];
/** Unlike `getExportsOfModule`, this includes properties of an `export =` value. */
/* @internal */ getExportsAndPropertiesOfModule(moduleSymbol: Symbol): Symbol[];
@@ -3012,10 +3015,10 @@ namespace ts {
/* @internal */ createArrayType(elementType: Type): Type;
/* @internal */ createPromiseType(type: Type): Type;
/* @internal */ createAnonymousType(symbol: Symbol, members: SymbolTable, callSignatures: Signature[], constructSignatures: Signature[], stringIndexInfo: IndexInfo, numberIndexInfo: IndexInfo): Type;
/* @internal */ createAnonymousType(symbol: Symbol, members: SymbolTable, callSignatures: Signature[], constructSignatures: Signature[], stringIndexInfo: IndexInfo | undefined, numberIndexInfo: IndexInfo | undefined): Type;
/* @internal */ createSignature(
declaration: SignatureDeclaration,
typeParameters: TypeParameter[],
typeParameters: TypeParameter[] | undefined,
thisParameter: Symbol | undefined,
parameters: Symbol[],
resolvedReturnType: Type,
@@ -3026,7 +3029,7 @@ namespace ts {
): Signature;
/* @internal */ createSymbol(flags: SymbolFlags, name: __String): TransientSymbol;
/* @internal */ createIndexInfo(type: Type, isReadonly: boolean, declaration?: SignatureDeclaration): IndexInfo;
/* @internal */ isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags, shouldComputeAliasToMarkVisible: boolean): SymbolAccessibilityResult;
/* @internal */ isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags, shouldComputeAliasToMarkVisible: boolean): SymbolAccessibilityResult;
/* @internal */ tryFindAmbientModuleWithoutAugmentations(moduleName: string): Symbol | undefined;
/* @internal */ getSymbolWalker(accept?: (symbol: Symbol) => boolean): SymbolWalker;
@@ -3313,9 +3316,9 @@ namespace ts {
/* @internal */
export interface AllAccessorDeclarations {
firstAccessor: AccessorDeclaration;
secondAccessor: AccessorDeclaration;
getAccessor: AccessorDeclaration;
setAccessor: AccessorDeclaration;
secondAccessor: AccessorDeclaration | undefined;
getAccessor: AccessorDeclaration | undefined;
setAccessor: AccessorDeclaration | undefined;
}
/** Indicates how to serialize the name for a TypeReferenceNode when emitting decorator metadata */
@@ -3342,9 +3345,9 @@ namespace ts {
/* @internal */
export interface EmitResolver {
hasGlobalName(name: string): boolean;
getReferencedExportContainer(node: Identifier, prefixLocals?: boolean): SourceFile | ModuleDeclaration | EnumDeclaration;
getReferencedImportDeclaration(node: Identifier): Declaration;
getReferencedDeclarationWithCollidingName(node: Identifier): Declaration;
getReferencedExportContainer(node: Identifier, prefixLocals?: boolean): SourceFile | ModuleDeclaration | EnumDeclaration | undefined;
getReferencedImportDeclaration(node: Identifier): Declaration | undefined;
getReferencedDeclarationWithCollidingName(node: Identifier): Declaration | undefined;
isDeclarationWithCollidingName(node: Declaration): boolean;
isValueAliasDeclaration(node: Node): boolean;
isReferencedAliasDeclaration(node: Node, checkChildren?: boolean): boolean;
@@ -3352,28 +3355,28 @@ namespace ts {
getNodeCheckFlags(node: Node): NodeCheckFlags;
isDeclarationVisible(node: Declaration | AnyImportSyntax): boolean;
isLateBound(node: Declaration): node is LateBoundDeclaration;
collectLinkedAliases(node: Identifier): Node[];
collectLinkedAliases(node: Identifier): Node[] | undefined;
isImplementationOfOverload(node: FunctionLike): boolean | undefined;
isRequiredInitializedParameter(node: ParameterDeclaration): boolean;
isOptionalUninitializedParameterProperty(node: ParameterDeclaration): boolean;
createTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker, addUndefined?: boolean): TypeNode;
createReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker): TypeNode;
createTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker): TypeNode;
createTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker, addUndefined?: boolean): TypeNode | undefined;
createReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker): TypeNode | undefined;
createTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker): TypeNode | undefined;
createLiteralConstValue(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration): Expression;
isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags, shouldComputeAliasToMarkVisible: boolean): SymbolAccessibilityResult;
isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags | undefined, shouldComputeAliasToMarkVisible: boolean): SymbolAccessibilityResult;
isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node): SymbolVisibilityResult;
// Returns the constant value this property access resolves to, or 'undefined' for a non-constant
getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): string | number;
getReferencedValueDeclaration(reference: Identifier): Declaration;
getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): string | number | undefined;
getReferencedValueDeclaration(reference: Identifier): Declaration | undefined;
getTypeReferenceSerializationKind(typeName: EntityName, location?: Node): TypeReferenceSerializationKind;
isOptionalParameter(node: ParameterDeclaration): boolean;
moduleExportsSomeValue(moduleReferenceExpression: Expression): boolean;
isArgumentsLocalBinding(node: Identifier): boolean;
getExternalModuleFileFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration | ImportTypeNode): SourceFile;
getTypeReferenceDirectivesForEntityName(name: EntityNameOrEntityNameExpression): string[];
getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags): string[];
getExternalModuleFileFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration | ImportTypeNode): SourceFile | undefined;
getTypeReferenceDirectivesForEntityName(name: EntityNameOrEntityNameExpression): string[] | undefined;
getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags): string[] | undefined;
isLiteralConstDeclaration(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration): boolean;
getJsxFactoryEntity(location?: Node): EntityName;
getJsxFactoryEntity(location?: Node): EntityName | undefined;
getAllAccessorDeclarations(declaration: AccessorDeclaration): AllAccessorDeclarations;
}
@@ -3469,8 +3472,8 @@ namespace ts {
export interface Symbol {
flags: SymbolFlags; // Symbol flags
escapedName: __String; // Name of symbol
declarations?: Declaration[]; // Declarations associated with this symbol
valueDeclaration?: Declaration; // First value declaration of the symbol
declarations: Declaration[]; // Declarations associated with this symbol
valueDeclaration: Declaration; // First value declaration of the symbol
members?: SymbolTable; // Class, interface or object literal instance members
exports?: SymbolTable; // Module exports
globalExports?: SymbolTable; // Conditional global UMD exports
@@ -3641,7 +3644,7 @@ namespace ts {
/* @internal */
export interface NodeLinks {
flags?: NodeCheckFlags; // Set of flags specific to Node
flags: NodeCheckFlags; // Set of flags specific to Node
resolvedType?: Type; // Cached type of type node
resolvedSignature?: Signature; // Cached signature of signature node or call expression
resolvedSignatures?: Map<Signature[]>; // Cached signatures of jsx node
@@ -3652,7 +3655,7 @@ namespace ts {
isVisible?: boolean; // Is this node visible
containsArgumentsReference?: boolean; // Whether a function-like declaration contains an 'arguments' reference
hasReportedStatementInAmbientContext?: boolean; // Cache boolean if we report statements in ambient context
jsxFlags?: JsxFlags; // flags for knowing what kind of element/attributes we're dealing with
jsxFlags: JsxFlags; // flags for knowing what kind of element/attributes we're dealing with
resolvedJsxElementAttributesType?: Type; // resolved element attributes type of a JSX openinglike element
resolvedJsxElementAllAttributesType?: Type; // resolved all element attributes type of a JSX openinglike element
hasSuperCall?: boolean; // recorded result when we try to find super-call. We only try to find one if this flag is undefined, indicating that we haven't made an attempt.
@@ -3756,7 +3759,7 @@ namespace ts {
flags: TypeFlags; // Flags
/* @internal */ id: number; // Unique ID
/* @internal */ checker: TypeChecker;
symbol?: Symbol; // Symbol associated with type (if any)
symbol: Symbol; // Symbol associated with type (if any)
pattern?: DestructuringPattern; // Destructuring pattern represented by type (if any)
aliasSymbol?: Symbol; // Alias associated with type
aliasTypeArguments?: Type[]; // Alias type arguments (if any)
@@ -3774,8 +3777,8 @@ namespace ts {
// Numeric literal types (TypeFlags.NumberLiteral)
export interface LiteralType extends Type {
value: string | number; // Value of literal
freshType?: LiteralType; // Fresh version of type
regularType?: LiteralType; // Regular version of type
freshType: LiteralType; // Fresh version of type
regularType: LiteralType; // Regular version of type
}
// Unique symbol types (TypeFlags.UniqueESSymbol)
@@ -3820,25 +3823,25 @@ namespace ts {
/** Class and interface types (ObjectFlags.Class and ObjectFlags.Interface). */
export interface InterfaceType extends ObjectType {
typeParameters: TypeParameter[]; // Type parameters (undefined if non-generic)
outerTypeParameters: TypeParameter[]; // Outer type parameters (undefined if none)
localTypeParameters: TypeParameter[]; // Local type parameters (undefined if none)
thisType: TypeParameter; // The "this" type (undefined if none)
typeParameters: TypeParameter[] | undefined; // Type parameters (undefined if non-generic)
outerTypeParameters: TypeParameter[] | undefined; // Outer type parameters (undefined if none)
localTypeParameters: TypeParameter[] | undefined; // Local type parameters (undefined if none)
thisType: TypeParameter | undefined; // The "this" type (undefined if none)
/* @internal */
resolvedBaseConstructorType?: Type; // Resolved base constructor type of class
resolvedBaseConstructorType?: Type; // Resolved base constructor type of class
/* @internal */
resolvedBaseTypes: BaseType[]; // Resolved base types
resolvedBaseTypes: BaseType[]; // Resolved base types
}
// Object type or intersection of object types
export type BaseType = ObjectType | IntersectionType;
export interface InterfaceTypeWithDeclaredMembers extends InterfaceType {
declaredProperties: Symbol[]; // Declared members
declaredCallSignatures: Signature[]; // Declared call signatures
declaredConstructSignatures: Signature[]; // Declared construct signatures
declaredStringIndexInfo: IndexInfo; // Declared string indexing info
declaredNumberIndexInfo: IndexInfo; // Declared numeric indexing info
declaredProperties: Symbol[]; // Declared members
declaredCallSignatures: Signature[]; // Declared call signatures
declaredConstructSignatures: Signature[]; // Declared construct signatures
declaredStringIndexInfo?: IndexInfo; // Declared string indexing info
declaredNumberIndexInfo?: IndexInfo; // Declared numeric indexing info
}
/**
@@ -3928,12 +3931,12 @@ namespace ts {
/* @internal */
// Resolved object, union, or intersection type
export interface ResolvedType extends ObjectType, UnionOrIntersectionType {
members: SymbolTable; // Properties by name
properties: Symbol[]; // Properties
callSignatures: Signature[]; // Call signatures of type
constructSignatures: Signature[]; // Construct signatures of type
stringIndexInfo?: IndexInfo; // String indexing info
numberIndexInfo?: IndexInfo; // Numeric indexing info
members: SymbolTable; // Properties by name
properties: Symbol[]; // Properties
callSignatures: Signature[]; // Call signatures of type
constructSignatures: Signature[]; // Construct signatures of type
stringIndexInfo?: IndexInfo; // String indexing info
numberIndexInfo?: IndexInfo; // Numeric indexing info
}
/* @internal */
@@ -4016,11 +4019,11 @@ namespace ts {
trueType: Type;
falseType: Type;
isDistributive: boolean;
inferTypeParameters: TypeParameter[];
inferTypeParameters?: TypeParameter[];
outerTypeParameters?: TypeParameter[];
instantiations?: Map<Type>;
aliasSymbol: Symbol;
aliasTypeArguments: Type[];
aliasSymbol?: Symbol;
aliasTypeArguments?: Type[];
}
// T extends U ? X : Y (TypeFlags.Conditional)
@@ -4062,12 +4065,12 @@ namespace ts {
thisParameter?: Symbol; // symbol of this-type parameter
/* @internal */
// See comment in `instantiateSignature` for why these are set lazily.
resolvedReturnType: Type | undefined; // Lazily set by `getReturnTypeOfSignature`.
resolvedReturnType?: Type; // Lazily set by `getReturnTypeOfSignature`.
/* @internal */
// Lazily set by `getTypePredicateOfSignature`.
// `undefined` indicates a type predicate that has not yet been computed.
// Uses a special `noTypePredicate` sentinel value to indicate that there is no type predicate. This looks like a TypePredicate at runtime to avoid polymorphism.
resolvedTypePredicate: TypePredicate | undefined;
resolvedTypePredicate?: TypePredicate;
/* @internal */
minArgumentCount: number; // Number of non-optional parameters
/* @internal */
@@ -4118,13 +4121,13 @@ namespace ts {
/* @internal */
export interface InferenceInfo {
typeParameter: TypeParameter; // Type parameter for which inferences are being made
candidates: Type[]; // Candidates in covariant positions (or undefined)
contraCandidates: Type[]; // Candidates in contravariant positions (or undefined)
inferredType: Type; // Cache for resolved inferred type
priority: InferencePriority; // Priority of current inference set
topLevel: boolean; // True if all inferences are to top level occurrences
isFixed: boolean; // True if inferences are fixed
typeParameter: TypeParameter; // Type parameter for which inferences are being made
candidates: Type[] | undefined; // Candidates in covariant positions (or undefined)
contraCandidates: Type[] | undefined; // Candidates in contravariant positions (or undefined)
inferredType?: Type; // Cache for resolved inferred type
priority?: InferencePriority; // Priority of current inference set
topLevel: boolean; // True if all inferences are to top level occurrences
isFixed: boolean; // True if inferences are fixed
}
/* @internal */
@@ -4157,7 +4160,7 @@ namespace ts {
/* @internal */
export interface InferenceContext extends TypeMapper {
typeParameters: TypeParameter[]; // Type parameters for which inferences are made
signature: Signature; // Generic signature for which inferences are made (if any)
signature?: Signature; // Generic signature for which inferences are made (if any)
inferences: InferenceInfo[]; // Inferences made for each type parameter
flags: InferenceFlags; // Inference flags
compareTypes: TypeComparer; // Type comparer function
@@ -4355,7 +4358,7 @@ namespace ts {
suppressExcessPropertyErrors?: boolean;
suppressImplicitAnyIndexErrors?: boolean;
/* @internal */ suppressOutputPathCheck?: boolean;
target?: ScriptTarget;
target?: ScriptTarget; // TODO: GH#18217 frequently asserted as defined
traceResolution?: boolean;
resolveJsonModule?: boolean;
types?: string[];
@@ -4462,18 +4465,18 @@ namespace ts {
/* @internal */
export interface ConfigFileSpecs {
filesSpecs: ReadonlyArray<string>;
filesSpecs: ReadonlyArray<string> | undefined;
referencesSpecs: ReadonlyArray<ProjectReference> | undefined;
/**
* Present to report errors (user specified specs), validatedIncludeSpecs are used for file name matching
*/
includeSpecs: ReadonlyArray<string>;
includeSpecs?: ReadonlyArray<string>;
/**
* Present to report errors (user specified specs), validatedExcludeSpecs are used for file name matching
*/
excludeSpecs: ReadonlyArray<string>;
validatedIncludeSpecs: ReadonlyArray<string>;
validatedExcludeSpecs: ReadonlyArray<string>;
excludeSpecs?: ReadonlyArray<string>;
validatedIncludeSpecs?: ReadonlyArray<string>;
validatedExcludeSpecs?: ReadonlyArray<string>;
wildcardDirectories: MapLike<WatchDirectoryFlags>;
}
@@ -4671,6 +4674,8 @@ namespace ts {
}
export interface ModuleResolutionHost {
// TODO: GH#18217 Optional methods frequently used as non-optional
fileExists(fileName: string): boolean;
// readFile function is used to read arbitrary text files on disk, i.e. when resolution procedure needs the content of 'package.json'
// to determine location of bundled typings for node module
@@ -4760,7 +4765,7 @@ namespace ts {
}
export interface ResolvedTypeReferenceDirectiveWithFailedLookupLocations {
readonly resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective;
readonly resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective | undefined;
readonly failedLookupLocations: ReadonlyArray<string>;
}
@@ -4792,8 +4797,8 @@ namespace ts {
/**
* This method is a companion for 'resolveModuleNames' and is used to resolve 'types' references to actual type declaration files
*/
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): (ResolvedTypeReferenceDirective | undefined)[];
getEnvironmentVariable?(name: string): string;
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[];
getEnvironmentVariable?(name: string): string | undefined;
/* @internal */ onReleaseOldSourceFile?(oldSourceFile: SourceFile, oldOptions: CompilerOptions): void;
/* @internal */ hasInvalidatedResolution?: HasInvalidatedResolution;
/* @internal */ hasChangedAutomaticTypeDirectiveNames?: boolean;
@@ -4897,12 +4902,12 @@ namespace ts {
/* @internal */
export interface EmitNode {
annotatedNodes?: Node[]; // Tracks Parse-tree nodes with EmitNodes for eventual cleanup.
flags?: EmitFlags; // Flags that customize emit
flags: EmitFlags; // Flags that customize emit
leadingComments?: SynthesizedComment[]; // Synthesized leading comments
trailingComments?: SynthesizedComment[]; // Synthesized trailing comments
commentRange?: TextRange; // The text range to use when emitting leading or trailing comments
sourceMapRange?: SourceMapRange; // The text range to use when emitting leading or trailing source mappings
tokenSourceMapRanges?: SourceMapRange[]; // The text range to use when emitting source mappings for tokens
tokenSourceMapRanges?: (SourceMapRange | undefined)[]; // The text range to use when emitting source mappings for tokens
constantValue?: string | number; // The constant value of an expression
externalHelpersModuleName?: Identifier; // The local name for an imported helpers module
helpers?: EmitHelper[]; // Emit helpers for the node
@@ -4910,6 +4915,7 @@ namespace ts {
}
export const enum EmitFlags {
None = 0,
SingleLine = 1 << 0, // The contents of this node should be emitted on a single line.
AdviseOnEmitNode = 1 << 1, // The printer should invoke the onEmitNode callback when printing this node.
NoSubstitution = 1 << 2, // Disables further substitution of an expression.
@@ -5040,7 +5046,7 @@ namespace ts {
resumeLexicalEnvironment(): void;
/** Ends a lexical environment, returning any declarations. */
endLexicalEnvironment(): Statement[];
endLexicalEnvironment(): Statement[] | undefined;
/** Hoists a function declaration to the containing scope. */
hoistFunctionDeclaration(node: FunctionDeclaration): void;
@@ -5169,7 +5175,7 @@ namespace ts {
*/
printBundle(bundle: Bundle): string;
/*@internal*/ writeNode(hint: EmitHint, node: Node, sourceFile: SourceFile | undefined, writer: EmitTextWriter): void;
/*@internal*/ writeList<T extends Node>(format: ListFormat, list: NodeArray<T>, sourceFile: SourceFile | undefined, writer: EmitTextWriter): void;
/*@internal*/ writeList<T extends Node>(format: ListFormat, list: NodeArray<T> | undefined, sourceFile: SourceFile | undefined, writer: EmitTextWriter): void;
/*@internal*/ writeFile(sourceFile: SourceFile, writer: EmitTextWriter): void;
/*@internal*/ writeBundle(bundle: Bundle, writer: EmitTextWriter, info?: BundleInfo): void;
}
@@ -5214,7 +5220,7 @@ namespace ts {
* });
* ```
*/
onEmitNode?(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void;
onEmitNode?(hint: EmitHint, node: Node | undefined, emitCallback: (hint: EmitHint, node: Node | undefined) => void): void;
/**
* A hook used by the Printer to perform just-in-time substitution of a node. This is
* primarily used by node transformations that need to substitute one node for another,
@@ -5233,11 +5239,11 @@ namespace ts {
*/
substituteNode?(hint: EmitHint, node: Node): Node;
/*@internal*/ onEmitSourceMapOfNode?: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void;
/*@internal*/ onEmitSourceMapOfToken?: (node: Node, token: SyntaxKind, writer: (s: string) => void, pos: number, emitCallback: (token: SyntaxKind, writer: (s: string) => void, pos: number) => number) => number;
/*@internal*/ onEmitSourceMapOfToken?: (node: Node | undefined, token: SyntaxKind, writer: (s: string) => void, pos: number, emitCallback: (token: SyntaxKind, writer: (s: string) => void, pos: number) => number) => number;
/*@internal*/ onEmitSourceMapOfPosition?: (pos: number) => void;
/*@internal*/ onSetSourceFile?: (node: SourceFile) => void;
/*@internal*/ onBeforeEmitNodeArray?: (nodes: NodeArray<any>) => void;
/*@internal*/ onAfterEmitNodeArray?: (nodes: NodeArray<any>) => void;
/*@internal*/ onBeforeEmitNodeArray?: (nodes: NodeArray<any> | undefined) => void;
/*@internal*/ onAfterEmitNodeArray?: (nodes: NodeArray<any> | undefined) => void;
/*@internal*/ onBeforeEmitToken?: (node: Node) => void;
/*@internal*/ onAfterEmitToken?: (node: Node) => void;
}
+154 -137
View File
@@ -6,7 +6,7 @@ namespace ts {
export const externalHelpersModuleNameText = "tslib";
export function getDeclarationOfKind<T extends Declaration>(symbol: Symbol, kind: T["kind"]): T {
export function getDeclarationOfKind<T extends Declaration>(symbol: Symbol, kind: T["kind"]): T | undefined {
const declarations = symbol.declarations;
if (declarations) {
for (const declaration of declarations) {
@@ -103,7 +103,7 @@ namespace ts {
}
function packageIdIsEqual(a: PackageId | undefined, b: PackageId | undefined): boolean {
return a === b || a && b && a.name === b.name && a.subModuleName === b.subModuleName && a.version === b.version;
return a === b || !!a && !!b && a.name === b.name && a.subModuleName === b.subModuleName && a.version === b.version;
}
export function packageIdToString({ name, subModuleName, version }: PackageId): string {
@@ -118,7 +118,7 @@ namespace ts {
export function hasChangesInResolutions<T>(
names: ReadonlyArray<string>,
newResolutions: ReadonlyArray<T>,
oldResolutions: ReadonlyMap<T>,
oldResolutions: ReadonlyMap<T> | undefined,
comparer: (oldResolution: T, newResolution: T) => boolean): boolean {
Debug.assert(names.length === newResolutions.length);
@@ -162,6 +162,8 @@ namespace ts {
}
}
export function getSourceFileOfNode(node: Node): SourceFile;
export function getSourceFileOfNode(node: Node | undefined): SourceFile | undefined;
export function getSourceFileOfNode(node: Node): SourceFile {
while (node && node.kind !== SyntaxKind.SourceFile) {
node = node.parent;
@@ -240,7 +242,7 @@ namespace ts {
// code). So the parser will attempt to parse out a type, and will create an actual node.
// However, this node will be 'missing' in the sense that no actual source-code/tokens are
// contained within it.
export function nodeIsMissing(node: Node) {
export function nodeIsMissing(node: Node | undefined): boolean {
if (node === undefined) {
return true;
}
@@ -248,7 +250,7 @@ namespace ts {
return node.pos === node.end && node.pos >= 0 && node.kind !== SyntaxKind.EndOfFileToken;
}
export function nodeIsPresent(node: Node) {
export function nodeIsPresent(node: Node | undefined): boolean {
return !nodeIsMissing(node);
}
@@ -290,7 +292,7 @@ namespace ts {
}
if (includeJsDoc && hasJSDocNodes(node)) {
return getTokenPosOfNode(node.jsDoc[0]);
return getTokenPosOfNode(node.jsDoc![0]);
}
// For a syntax list, it is possible that one of its children has JSDocComment nodes, while
@@ -343,9 +345,9 @@ namespace ts {
/**
* Gets flags that control emit behavior of a node.
*/
export function getEmitFlags(node: Node): EmitFlags | undefined {
export function getEmitFlags(node: Node): EmitFlags {
const emitNode = node.emitNode;
return emitNode && emitNode.flags;
return emitNode && emitNode.flags || 0;
}
export function getLiteralText(node: LiteralLikeNode, sourceFile: SourceFile) {
@@ -382,7 +384,7 @@ namespace ts {
return node.text;
}
Debug.fail(`Literal kind '${node.kind}' not accounted for.`);
return Debug.fail(`Literal kind '${node.kind}' not accounted for.`);
}
export function getTextOfConstantValue(value: string | number) {
@@ -471,7 +473,7 @@ namespace ts {
return isExternalModule(node) || compilerOptions.isolatedModules || ((getEmitModuleKind(compilerOptions) === ModuleKind.CommonJS) && !!node.commonJsModuleIndicator);
}
export function isBlockScope(node: Node, parentNode: Node) {
export function isBlockScope(node: Node, parentNode: Node): boolean {
switch (node.kind) {
case SyntaxKind.SourceFile:
case SyntaxKind.CaseBlock:
@@ -492,7 +494,7 @@ namespace ts {
case SyntaxKind.Block:
// function block is not considered block-scope container
// see comment in binder.ts: bind(...), case for SyntaxKind.Block
return parentNode && !isFunctionLike(parentNode);
return !isFunctionLike(parentNode);
}
return false;
@@ -564,7 +566,7 @@ namespace ts {
// Gets the nearest enclosing block scope container that has the provided node
// as a descendant, that is not the provided node.
export function getEnclosingBlockScopeContainer(node: Node): Node {
return findAncestor(node.parent, current => isBlockScope(current, current.parent));
return findAncestor(node.parent, current => isBlockScope(current, current.parent))!;
}
// Return display name of an identifier
@@ -586,7 +588,7 @@ namespace ts {
case SyntaxKind.NumericLiteral:
return escapeLeadingUnderscores(name.text);
case SyntaxKind.ComputedPropertyName:
return isStringOrNumericLiteral(name.expression) ? escapeLeadingUnderscores(name.expression.text) : undefined;
return isStringOrNumericLiteral(name.expression) ? escapeLeadingUnderscores(name.expression.text) : undefined!; // TODO: GH#18217 Almost all uses of this assume the result to be defined!
default:
Debug.assertNever(name);
}
@@ -600,6 +602,8 @@ namespace ts {
return entityNameToString(name.left) + "." + entityNameToString(name.right);
case SyntaxKind.PropertyAccessExpression:
return entityNameToString(name.expression) + "." + entityNameToString(name.name);
default:
throw Debug.assertNever(name);
}
}
@@ -658,7 +662,7 @@ namespace ts {
}
export function getErrorSpanForNode(sourceFile: SourceFile, node: Node): TextSpan {
let errorNode = node;
let errorNode: Node | undefined = node;
switch (node.kind) {
case SyntaxKind.SourceFile:
const pos = skipTrivia(sourceFile.text, 0, /*stopAfterLineBreak*/ false);
@@ -817,8 +821,8 @@ namespace ts {
// falls through
case SyntaxKind.QualifiedName:
case SyntaxKind.PropertyAccessExpression:
case SyntaxKind.ThisKeyword:
const parent = node.parent;
case SyntaxKind.ThisKeyword: {
const { parent } = node;
if (parent.kind === SyntaxKind.TypeQuery) {
return false;
}
@@ -866,6 +870,7 @@ namespace ts {
// TODO (drosen): TaggedTemplateExpressions may eventually support type arguments.
return false;
}
}
}
return false;
@@ -883,11 +888,11 @@ namespace ts {
// Warning: This has the same semantics as the forEach family of functions,
// in that traversal terminates in the event that 'visitor' supplies a truthy value.
export function forEachReturnStatement<T>(body: Block, visitor: (stmt: ReturnStatement) => T): T {
export function forEachReturnStatement<T>(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(<ReturnStatement>node);
@@ -958,7 +963,7 @@ namespace ts {
*
* @param node The type node.
*/
export function getRestParameterElementType(node: TypeNode) {
export function getRestParameterElementType(node: TypeNode | undefined) {
if (node && node.kind === SyntaxKind.ArrayType) {
return (<ArrayTypeNode>node).elementType;
}
@@ -1008,7 +1013,7 @@ namespace ts {
&& node.parent.parent.kind === SyntaxKind.VariableStatement;
}
export function isValidESSymbolDeclaration(node: Node) {
export function isValidESSymbolDeclaration(node: Node): node is VariableDeclaration | PropertyDeclaration | SignatureDeclaration {
return isVariableDeclaration(node) ? isConst(node) && isIdentifier(node.name) && isVariableDeclarationInVariableStatement(node) :
isPropertyDeclaration(node) ? hasReadonlyModifier(node) && hasStaticModifier(node) :
isPropertySignature(node) && hasReadonlyModifier(node);
@@ -1028,7 +1033,7 @@ namespace ts {
return false;
}
export function unwrapInnermostStatementOfLabel(node: LabeledStatement, beforeUnwrapLabelCallback?: (node: LabeledStatement) => void) {
export function unwrapInnermostStatementOfLabel(node: LabeledStatement, beforeUnwrapLabelCallback?: (node: LabeledStatement) => void): Statement {
while (true) {
if (beforeUnwrapLabelCallback) {
beforeUnwrapLabelCallback(node);
@@ -1040,7 +1045,7 @@ namespace ts {
}
}
export function isFunctionBlock(node: Node) {
export function isFunctionBlock(node: Node): boolean {
return node && node.kind === SyntaxKind.Block && isFunctionLike(node.parent);
}
@@ -1066,15 +1071,16 @@ namespace ts {
return filter(objectLiteral.properties, (property): property is PropertyAssignment => {
if (property.kind === SyntaxKind.PropertyAssignment) {
const propName = getTextOfPropertyName(property.name);
return key === propName || (key2 && key2 === propName);
return key === propName || (!!key2 && key2 === propName);
}
return false;
});
}
export function getTsConfigObjectLiteralExpression(tsConfigSourceFile: TsConfigSourceFile | undefined) {
export function getTsConfigObjectLiteralExpression(tsConfigSourceFile: TsConfigSourceFile | undefined): ObjectLiteralExpression | undefined {
if (tsConfigSourceFile && tsConfigSourceFile.statements.length) {
const expression = tsConfigSourceFile.statements[0].expression;
return isObjectLiteralExpression(expression) && expression;
return tryCast(expression, isObjectLiteralExpression);
}
}
@@ -1087,19 +1093,20 @@ namespace ts {
undefined);
}
export function getContainingFunction(node: Node): SignatureDeclaration {
export function getContainingFunction(node: Node): SignatureDeclaration | undefined {
return findAncestor(node.parent, isFunctionLike);
}
export function getContainingClass(node: Node): ClassLikeDeclaration {
export function getContainingClass(node: Node): ClassLikeDeclaration | undefined {
return findAncestor(node.parent, isClassLike);
}
export function getThisContainer(node: Node, includeArrowFunctions: boolean): Node {
Debug.assert(node.kind !== SyntaxKind.SourceFile);
while (true) {
node = node.parent;
if (!node) {
return undefined;
return Debug.fail(); // If we never pass in a SourceFile, this should be unreachable, since we'll stop when we reach that.
}
switch (node.kind) {
case SyntaxKind.ComputedPropertyName:
@@ -1219,7 +1226,7 @@ namespace ts {
}
}
export function getImmediatelyInvokedFunctionExpression(func: Node): CallExpression {
export function getImmediatelyInvokedFunctionExpression(func: Node): CallExpression | undefined {
if (func.kind === SyntaxKind.FunctionExpression || func.kind === SyntaxKind.ArrowFunction) {
let prev = func;
let parent = func.parent;
@@ -1251,7 +1258,7 @@ namespace ts {
&& (<PropertyAccessExpression | ElementAccessExpression>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 (<TypeReferenceNode>node).typeName;
@@ -1292,22 +1299,22 @@ namespace ts {
case SyntaxKind.PropertyDeclaration:
// property declarations are valid if their parent is a class declaration.
return parent.kind === SyntaxKind.ClassDeclaration;
return parent!.kind === SyntaxKind.ClassDeclaration;
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.MethodDeclaration:
// if this method has a body and its parent is a class declaration, this is a valid target.
return (<FunctionLikeDeclaration>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 (<FunctionLikeDeclaration>parent).body !== undefined
&& (parent.kind === SyntaxKind.Constructor
|| parent.kind === SyntaxKind.MethodDeclaration
|| parent.kind === SyntaxKind.SetAccessor)
&& grandparent.kind === SyntaxKind.ClassDeclaration;
&& (parent!.kind === SyntaxKind.Constructor
|| parent!.kind === SyntaxKind.MethodDeclaration
|| parent!.kind === SyntaxKind.SetAccessor)
&& grandparent!.kind === SyntaxKind.ClassDeclaration;
}
return false;
@@ -1318,14 +1325,14 @@ namespace ts {
export function nodeIsDecorated(node: Node, parent: Node, grandparent: Node): boolean;
export function nodeIsDecorated(node: Node, parent?: Node, grandparent?: Node): boolean {
return node.decorators !== undefined
&& nodeCanBeDecorated(node, parent, grandparent);
&& nodeCanBeDecorated(node, parent!, grandparent!); // TODO: GH#18217
}
export function nodeOrChildIsDecorated(node: ClassDeclaration): boolean;
export function nodeOrChildIsDecorated(node: ClassElement, parent: Node): boolean;
export function nodeOrChildIsDecorated(node: Node, parent: Node, grandparent: Node): boolean;
export function nodeOrChildIsDecorated(node: Node, parent?: Node, grandparent?: Node): boolean {
return nodeIsDecorated(node, parent, grandparent) || childIsDecorated(node, parent);
return nodeIsDecorated(node, parent!, grandparent!) || childIsDecorated(node, parent!); // TODO: GH#18217
}
export function childIsDecorated(node: ClassDeclaration): boolean;
@@ -1333,15 +1340,17 @@ namespace ts {
export function childIsDecorated(node: Node, parent?: Node): boolean {
switch (node.kind) {
case SyntaxKind.ClassDeclaration:
return forEach((<ClassDeclaration>node).members, m => nodeOrChildIsDecorated(m, node, parent));
return some((<ClassDeclaration>node).members, m => nodeOrChildIsDecorated(m, node, parent!)); // TODO: GH#18217
case SyntaxKind.MethodDeclaration:
case SyntaxKind.SetAccessor:
return forEach((<FunctionLikeDeclaration>node).parameters, p => nodeIsDecorated(p, node, parent));
return some((<FunctionLikeDeclaration>node).parameters, p => nodeIsDecorated(p, node, parent!)); // TODO: GH#18217
default:
return false;
}
}
export function isJSXTagName(node: Node) {
const parent = node.parent;
const { parent } = node;
if (parent.kind === SyntaxKind.JsxOpeningElement ||
parent.kind === SyntaxKind.JsxSelfClosingElement ||
parent.kind === SyntaxKind.JsxClosingElement) {
@@ -1409,7 +1418,7 @@ namespace ts {
}
export function isInExpressionContext(node: Node): boolean {
const parent = node.parent;
const { parent } = node;
switch (parent.kind) {
case SyntaxKind.VariableDeclaration:
case SyntaxKind.Parameter:
@@ -1480,15 +1489,15 @@ namespace ts {
}
export function isInJavaScriptFile(node: Node | undefined): boolean {
return node && !!(node.flags & NodeFlags.JavaScriptFile);
return !!node && !!(node.flags & NodeFlags.JavaScriptFile);
}
export function isInJsonFile(node: Node | undefined): boolean {
return node && !!(node.flags & NodeFlags.JsonFile);
return !!node && !!(node.flags & NodeFlags.JsonFile);
}
export function isInJSDoc(node: Node | undefined): boolean {
return node && !!(node.flags & NodeFlags.JSDoc);
return !!node && !!(node.flags & NodeFlags.JSDoc);
}
export function isJSDocIndexSignature(node: TypeReferenceNode | ExpressionWithTypeArguments) {
@@ -1538,7 +1547,7 @@ namespace ts {
* Container-like initializer behave like namespaces, so the binder needs to add contained symbols
* to their exports. An example is a function with assignments to `this` inside.
*/
export function getJSInitializerSymbol(symbol: Symbol) {
export function getJSInitializerSymbol(symbol: Symbol | undefined) {
if (!symbol || !symbol.valueDeclaration) {
return symbol;
}
@@ -1577,7 +1586,7 @@ namespace ts {
*
* This function returns the provided initializer, or undefined if it is not valid.
*/
export function getJavascriptInitializer(initializer: Node, isPrototypeAssignment: boolean): Expression {
export function getJavascriptInitializer(initializer: Node, isPrototypeAssignment: boolean): Expression | undefined {
if (isCallExpression(initializer)) {
const e = skipParentheses(initializer.expression);
return e.kind === SyntaxKind.FunctionExpression || e.kind === SyntaxKind.ArrowFunction ? initializer : undefined;
@@ -1744,7 +1753,7 @@ namespace ts {
}
}
export function getExternalModuleName(node: AnyImportOrReExport | ImportTypeNode): Expression {
export function getExternalModuleName(node: AnyImportOrReExport | ImportTypeNode): Expression | undefined {
switch (node.kind) {
case SyntaxKind.ImportDeclaration:
case SyntaxKind.ExportDeclaration:
@@ -1758,7 +1767,7 @@ namespace ts {
}
}
export function getNamespaceDeclarationNode(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration): ImportEqualsDeclaration | NamespaceImport {
export function getNamespaceDeclarationNode(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration): ImportEqualsDeclaration | NamespaceImport | undefined {
switch (node.kind) {
case SyntaxKind.ImportDeclaration:
return node.importClause && tryCast(node.importClause.namedBindings, isNamespaceImport);
@@ -1771,8 +1780,8 @@ namespace ts {
}
}
export function isDefaultImport(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration) {
return node.kind === SyntaxKind.ImportDeclaration && node.importClause && !!node.importClause.name;
export function isDefaultImport(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration): boolean {
return node.kind === SyntaxKind.ImportDeclaration && !!node.importClause && !!node.importClause.name;
}
export function hasQuestionToken(node: Node) {
@@ -1807,20 +1816,22 @@ namespace ts {
return isJSDocTypeAlias(node) || isTypeAliasDeclaration(node);
}
function getSourceOfAssignment(node: Node): Node {
function getSourceOfAssignment(node: Node): Node | undefined {
return isExpressionStatement(node) &&
node.expression && isBinaryExpression(node.expression) &&
node.expression.operatorToken.kind === SyntaxKind.EqualsToken &&
node.expression.right;
node.expression.operatorToken.kind === SyntaxKind.EqualsToken
? node.expression.right
: undefined;
}
function getSourceOfDefaultedAssignment(node: Node): Node {
function getSourceOfDefaultedAssignment(node: Node): Node | undefined {
return isExpressionStatement(node) &&
isBinaryExpression(node.expression) &&
getSpecialPropertyAssignmentKind(node.expression) !== SpecialPropertyAssignmentKind.None &&
isBinaryExpression(node.expression.right) &&
node.expression.right.operatorToken.kind === SyntaxKind.BarBarToken &&
node.expression.right.right;
node.expression.right.operatorToken.kind === SyntaxKind.BarBarToken
? node.expression.right.right
: undefined;
}
function getSingleInitializerOfVariableStatementOrPropertyDeclaration(node: Node): Expression | undefined {
@@ -1836,16 +1847,15 @@ namespace ts {
}
function getSingleVariableOfVariableStatement(node: Node): VariableDeclaration | undefined {
return isVariableStatement(node) &&
node.declarationList.declarations.length > 0 &&
node.declarationList.declarations[0];
return isVariableStatement(node) ? firstOrUndefined(node.declarationList.declarations) : undefined;
}
function getNestedModuleDeclaration(node: Node): Node {
return node.kind === SyntaxKind.ModuleDeclaration &&
(node as ModuleDeclaration).body &&
(node as ModuleDeclaration).body.kind === SyntaxKind.ModuleDeclaration &&
(node as ModuleDeclaration).body;
function getNestedModuleDeclaration(node: Node): Node | undefined {
return isModuleDeclaration(node) &&
node.body &&
node.body.kind === SyntaxKind.ModuleDeclaration
? node.body
: undefined;
}
export function getJSDocCommentsAndTags(hostNode: Node): ReadonlyArray<JSDoc | JSDocTag> {
@@ -1885,8 +1895,8 @@ namespace ts {
result = addRange(result, getJSDocParameterTags(node as ParameterDeclaration));
}
if (isVariableLike(node) && hasInitializer(node) && node.initializer !== hostNode && hasJSDocNodes(node.initializer)) {
result = addRange(result, node.initializer.jsDoc);
if (isVariableLike(node) && hasInitializer(node) && node.initializer !== hostNode && hasJSDocNodes(node.initializer!)) {
result = addRange(result, (node.initializer as HasJSDoc).jsDoc);
}
if (hasJSDocNodes(node)) {
@@ -1933,17 +1943,17 @@ namespace ts {
export function getTypeParameterFromJsDoc(node: TypeParameterDeclaration & { parent: JSDocTemplateTag }): TypeParameterDeclaration | undefined {
const name = node.name.escapedText;
const { typeParameters } = (node.parent.parent.parent as SignatureDeclaration | InterfaceDeclaration | ClassDeclaration);
return find(typeParameters, p => p.name.escapedText === name);
return find(typeParameters!, p => p.name.escapedText === name);
}
export function hasRestParameter(s: SignatureDeclaration | JSDocSignature): boolean {
const last = lastOrUndefined<ParameterDeclaration | JSDocParameterTag>(s.parameters);
return last && isRestParameter(last);
return !!last && isRestParameter(last);
}
export function isRestParameter(node: ParameterDeclaration | JSDocParameterTag): boolean {
const type = isJSDocParameterTag(node) ? (node.typeExpression && node.typeExpression.type) : node.type;
return (node as ParameterDeclaration).dotDotDotToken !== undefined || type && type.kind === SyntaxKind.JSDocVariadicType;
return (node as ParameterDeclaration).dotDotDotToken !== undefined || !!type && type.kind === SyntaxKind.JSDocVariadicType;
}
export const enum AssignmentKind {
@@ -2108,9 +2118,10 @@ namespace ts {
switch (name.kind) {
case SyntaxKind.Identifier:
case SyntaxKind.StringLiteral:
case SyntaxKind.NumericLiteral:
if (isDeclaration(name.parent)) {
return name.parent.name === name;
case SyntaxKind.NumericLiteral: {
const parent = name.parent;
if (isDeclaration(parent)) {
return parent.name === name;
}
else if (isQualifiedName(name.parent)) {
const tag = name.parent.parent;
@@ -2120,6 +2131,7 @@ namespace ts {
const binExp = name.parent.parent;
return isBinaryExpression(binExp) && getSpecialPropertyAssignmentKind(binExp) !== SpecialPropertyAssignmentKind.None && getNameOfDeclaration(binExp) === name;
}
}
default:
return false;
}
@@ -2213,7 +2225,7 @@ namespace ts {
return heritageClause ? heritageClause.types : undefined;
}
export function getHeritageClause(clauses: NodeArray<HeritageClause>, kind: SyntaxKind) {
export function getHeritageClause(clauses: NodeArray<HeritageClause> | undefined, kind: SyntaxKind) {
if (clauses) {
for (const clause of clauses) {
if (clause.token === kind) {
@@ -2333,7 +2345,7 @@ namespace ts {
*/
export function hasDynamicName(declaration: Declaration): declaration is DynamicNamedDeclaration {
const name = getNameOfDeclaration(declaration);
return name && isDynamicName(name);
return !!name && isDynamicName(name);
}
export function isDynamicName(name: DeclarationName): boolean {
@@ -2351,7 +2363,7 @@ namespace ts {
return isPropertyAccessExpression(node) && isESSymbolIdentifier(node.expression);
}
export function getPropertyNameForPropertyNameNode(name: DeclarationName): __String {
export function getPropertyNameForPropertyNameNode(name: DeclarationName): __String | undefined {
if (name.kind === SyntaxKind.Identifier) {
return name.escapedText;
}
@@ -2643,8 +2655,8 @@ namespace ts {
}
export function createDiagnosticCollection(): DiagnosticCollection {
let nonFileDiagnostics = [] as SortedArray<Diagnostic>;
const filesWithDiagnostics = [] as SortedArray<string>;
let nonFileDiagnostics = [] as Diagnostic[] as SortedArray<Diagnostic>; // See GH#19873
const filesWithDiagnostics = [] as string[] as SortedArray<string>;
const fileDiagnostics = createMap<SortedArray<DiagnosticWithLocation>>();
let hasReadNonFileDiagnostics = false;
@@ -2660,11 +2672,11 @@ namespace ts {
}
function add(diagnostic: Diagnostic): void {
let diagnostics: SortedArray<Diagnostic>;
let diagnostics: SortedArray<Diagnostic> | undefined;
if (diagnostic.file) {
diagnostics = fileDiagnostics.get(diagnostic.file.fileName);
if (!diagnostics) {
diagnostics = [] as SortedArray<DiagnosticWithLocation>;
diagnostics = [] as Diagnostic[] as SortedArray<DiagnosticWithLocation>; // See GH#19873
fileDiagnostics.set(diagnostic.file.fileName, diagnostics as SortedArray<DiagnosticWithLocation>);
insertSorted(filesWithDiagnostics, diagnostic.file.fileName, compareStringsCaseSensitive);
}
@@ -2826,7 +2838,7 @@ namespace ts {
const lineStartsOfS = computeLineStarts(s);
if (lineStartsOfS.length > 1) {
lineCount = lineCount + lineStartsOfS.length - 1;
linePos = output.length - s.length + lastOrUndefined(lineStartsOfS);
linePos = output.length - s.length + last(lineStartsOfS);
}
}
}
@@ -2880,7 +2892,7 @@ namespace ts {
return file.moduleName || getExternalModuleNameFromPath(host, file.fileName, referenceFile && referenceFile.fileName);
}
export function getExternalModuleNameFromDeclaration(host: ModuleNameResolverHost, resolver: EmitResolver, declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration | ImportTypeNode): string {
export function getExternalModuleNameFromDeclaration(host: ModuleNameResolverHost, resolver: EmitResolver, declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration | ImportTypeNode): string | undefined {
const file = resolver.getExternalModuleFileFromDeclaration(declaration);
if (!file || file.isDeclarationFile) {
return undefined;
@@ -2983,7 +2995,7 @@ namespace ts {
return computeLineAndCharacterOfPosition(lineMap, pos).line;
}
export function getFirstConstructorWithBody(node: ClassLikeDeclaration): ConstructorDeclaration {
export function getFirstConstructorWithBody(node: ClassLikeDeclaration): ConstructorDeclaration | undefined {
return find(node.members, (member): member is ConstructorDeclaration => isConstructorDeclaration(member) && nodeIsPresent(member.body));
}
@@ -2995,7 +3007,7 @@ namespace ts {
}
/** Get the type annotation for the value parameter. */
export function getSetAccessorTypeAnnotationNode(accessor: SetAccessorDeclaration): TypeNode {
export function getSetAccessorTypeAnnotationNode(accessor: SetAccessorDeclaration): TypeNode | undefined {
const parameter = getSetAccessorValueParameter(accessor);
return parameter && parameter.type;
}
@@ -3015,7 +3027,7 @@ namespace ts {
}
export function isThisIdentifier(node: Node | undefined): boolean {
return node && node.kind === SyntaxKind.Identifier && identifierIsThisKeyword(node as Identifier);
return !!node && node.kind === SyntaxKind.Identifier && identifierIsThisKeyword(node as Identifier);
}
export function identifierIsThisKeyword(id: Identifier): boolean {
@@ -3023,10 +3035,11 @@ namespace ts {
}
export function getAllAccessorDeclarations(declarations: NodeArray<Declaration>, accessor: AccessorDeclaration): AllAccessorDeclarations {
let firstAccessor: AccessorDeclaration;
let secondAccessor: AccessorDeclaration;
let getAccessor: AccessorDeclaration;
let setAccessor: AccessorDeclaration;
// TODO: GH#18217
let firstAccessor!: AccessorDeclaration;
let secondAccessor!: AccessorDeclaration;
let getAccessor!: AccessorDeclaration;
let setAccessor!: AccessorDeclaration;
if (hasDynamicName(accessor)) {
firstAccessor = accessor;
if (accessor.kind === SyntaxKind.GetAccessor) {
@@ -3043,7 +3056,7 @@ namespace ts {
forEach(declarations, (member: Declaration) => {
if ((member.kind === SyntaxKind.GetAccessor || member.kind === SyntaxKind.SetAccessor)
&& hasModifier(member, ModifierFlags.Static) === hasModifier(accessor, ModifierFlags.Static)) {
const memberName = getPropertyNameForPropertyNameNode((member as NamedDeclaration).name);
const memberName = getPropertyNameForPropertyNameNode((member as NamedDeclaration).name!);
const accessorName = getPropertyNameForPropertyNameNode(accessor.name);
if (memberName === accessorName) {
if (!firstAccessor) {
@@ -3126,16 +3139,16 @@ namespace ts {
* Gets the effective type annotation of the value parameter of a set accessor. If the node
* was parsed in a JavaScript file, gets the type annotation from JSDoc.
*/
export function getEffectiveSetAccessorTypeAnnotationNode(node: SetAccessorDeclaration): TypeNode {
export function getEffectiveSetAccessorTypeAnnotationNode(node: SetAccessorDeclaration): TypeNode | undefined {
const parameter = getSetAccessorValueParameter(node);
return parameter && getEffectiveTypeAnnotationNode(parameter);
}
export function emitNewLineBeforeLeadingComments(lineMap: ReadonlyArray<number>, writer: EmitTextWriter, node: TextRange, leadingComments: ReadonlyArray<CommentRange>) {
export function emitNewLineBeforeLeadingComments(lineMap: ReadonlyArray<number>, writer: EmitTextWriter, node: TextRange, leadingComments: ReadonlyArray<CommentRange> | undefined) {
emitNewLineBeforeLeadingCommentsOfPosition(lineMap, writer, node.pos, leadingComments);
}
export function emitNewLineBeforeLeadingCommentsOfPosition(lineMap: ReadonlyArray<number>, writer: EmitTextWriter, pos: number, leadingComments: ReadonlyArray<CommentRange>) {
export function emitNewLineBeforeLeadingCommentsOfPosition(lineMap: ReadonlyArray<number>, writer: EmitTextWriter, pos: number, leadingComments: ReadonlyArray<CommentRange> | undefined) {
// If the leading comments start on different line than the start of node, write new line
if (leadingComments && leadingComments.length && pos !== leadingComments[0].pos &&
getLineOfLocalPositionFromLineMap(lineMap, pos) !== getLineOfLocalPositionFromLineMap(lineMap, leadingComments[0].pos)) {
@@ -3155,7 +3168,7 @@ namespace ts {
text: string,
lineMap: ReadonlyArray<number>,
writer: EmitTextWriter,
comments: ReadonlyArray<CommentRange>,
comments: ReadonlyArray<CommentRange> | undefined,
leadingSeparator: boolean,
trailingSeparator: boolean,
newLine: string,
@@ -3194,8 +3207,8 @@ namespace ts {
export function emitDetachedComments(text: string, lineMap: ReadonlyArray<number>, writer: EmitTextWriter,
writeComment: (text: string, lineMap: ReadonlyArray<number>, writer: EmitTextWriter, commentPos: number, commentEnd: number, newLine: string) => void,
node: TextRange, newLine: string, removeComments: boolean) {
let leadingComments: CommentRange[];
let currentDetachedCommentInfo: { nodePos: number, detachedCommentEndPos: number };
let leadingComments: CommentRange[] | undefined;
let currentDetachedCommentInfo: { nodePos: number, detachedCommentEndPos: number } | undefined;
if (removeComments) {
// removeComments is true, only reserve pinned comment at the top of file
// For example:
@@ -3213,7 +3226,7 @@ namespace ts {
if (leadingComments) {
const detachedComments: CommentRange[] = [];
let lastComment: CommentRange;
let lastComment: CommentRange | undefined;
for (const comment of leadingComments) {
if (lastComment) {
@@ -3236,13 +3249,13 @@ namespace ts {
// All comments look like they could have been part of the copyright header. Make
// sure there is at least one blank line between it and the node. If not, it's not
// a copyright header.
const lastCommentLine = getLineOfLocalPositionFromLineMap(lineMap, lastOrUndefined(detachedComments).end);
const lastCommentLine = getLineOfLocalPositionFromLineMap(lineMap, last(detachedComments).end);
const nodeLine = getLineOfLocalPositionFromLineMap(lineMap, skipTrivia(text, node.pos));
if (nodeLine >= lastCommentLine + 2) {
// Valid detachedComments
emitNewLineBeforeLeadingComments(lineMap, writer, node, leadingComments);
emitComments(text, lineMap, writer, detachedComments, /*leadingSeparator*/ false, /*trailingSeparator*/ true, newLine, writeComment);
currentDetachedCommentInfo = { nodePos: node.pos, detachedCommentEndPos: lastOrUndefined(detachedComments).end };
currentDetachedCommentInfo = { nodePos: node.pos, detachedCommentEndPos: last(detachedComments).end };
}
}
}
@@ -3259,7 +3272,7 @@ namespace ts {
if (text.charCodeAt(commentPos + 1) === CharacterCodes.asterisk) {
const firstCommentLineAndCharacter = computeLineAndCharacterOfPosition(lineMap, commentPos);
const lineCount = lineMap.length;
let firstCommentLineIndent: number;
let firstCommentLineIndent: number | undefined;
for (let pos = commentPos, currentLine = firstCommentLineAndCharacter.line; pos < commentEnd; currentLine++) {
const nextLineStart = (currentLine + 1) === lineCount
? text.length + 1
@@ -3373,8 +3386,8 @@ namespace ts {
}
export function getModifierFlags(node: Node): ModifierFlags {
if (node.modifierFlagsCache & ModifierFlags.HasComputedFlags) {
return node.modifierFlagsCache & ~ModifierFlags.HasComputedFlags;
if (node.modifierFlagsCache! & ModifierFlags.HasComputedFlags) {
return node.modifierFlagsCache! & ~ModifierFlags.HasComputedFlags;
}
const flags = getModifierFlagsNoCache(node);
@@ -3427,8 +3440,8 @@ namespace ts {
/** Get `C` given `N` if `N` is in the position `class C extends N` where `N` is an ExpressionWithTypeArguments. */
export function tryGetClassExtendingExpressionWithTypeArguments(node: Node): ClassLikeDeclaration | undefined {
if (node.kind === SyntaxKind.ExpressionWithTypeArguments &&
(<HeritageClause>node.parent).token === SyntaxKind.ExtendsKeyword &&
if (isExpressionWithTypeArguments(node) &&
node.parent.token === SyntaxKind.ExtendsKeyword &&
isClassLike(node.parent.parent)) {
return node.parent.parent;
}
@@ -3714,31 +3727,31 @@ namespace ts {
return stableSort<[number, string]>(result, (x, y) => compareValues(x[0], y[0]));
}
export function formatSyntaxKind(kind: SyntaxKind): string {
export function formatSyntaxKind(kind: SyntaxKind | undefined): string {
return formatEnum(kind, (<any>ts).SyntaxKind, /*isFlags*/ false);
}
export function formatModifierFlags(flags: ModifierFlags): string {
export function formatModifierFlags(flags: ModifierFlags | undefined): string {
return formatEnum(flags, (<any>ts).ModifierFlags, /*isFlags*/ true);
}
export function formatTransformFlags(flags: TransformFlags): string {
export function formatTransformFlags(flags: TransformFlags | undefined): string {
return formatEnum(flags, (<any>ts).TransformFlags, /*isFlags*/ true);
}
export function formatEmitFlags(flags: EmitFlags): string {
export function formatEmitFlags(flags: EmitFlags | undefined): string {
return formatEnum(flags, (<any>ts).EmitFlags, /*isFlags*/ true);
}
export function formatSymbolFlags(flags: SymbolFlags): string {
export function formatSymbolFlags(flags: SymbolFlags | undefined): string {
return formatEnum(flags, (<any>ts).SymbolFlags, /*isFlags*/ true);
}
export function formatTypeFlags(flags: TypeFlags): string {
export function formatTypeFlags(flags: TypeFlags | undefined): string {
return formatEnum(flags, (<any>ts).TypeFlags, /*isFlags*/ true);
}
export function formatObjectFlags(flags: ObjectFlags): string {
export function formatObjectFlags(flags: ObjectFlags | undefined): string {
return formatEnum(flags, (<any>ts).ObjectFlags, /*isFlags*/ true);
}
@@ -3806,7 +3819,7 @@ namespace ts {
* @param token The token.
*/
export function createTokenRange(pos: number, token: SyntaxKind): TextRange {
return createRange(pos, pos + tokenToString(token).length);
return createRange(pos, pos + tokenToString(token)!.length);
}
export function rangeIsOnSingleLine(range: TextRange, sourceFile: SourceFile) {
@@ -4055,7 +4068,7 @@ namespace ts {
return !!forEachAncestorDirectory(directory, d => callback(d) ? true : undefined);
}
export function isUMDExportSymbol(symbol: Symbol) {
export function isUMDExportSymbol(symbol: Symbol | undefined) {
return symbol && symbol.declarations && symbol.declarations[0] && isNamespaceExportDeclaration(symbol.declarations[0]);
}
@@ -4135,7 +4148,7 @@ namespace ts {
return textSpanOverlap(span, other) !== undefined;
}
export function textSpanOverlap(span1: TextSpan, span2: TextSpan) {
export function textSpanOverlap(span1: TextSpan, span2: TextSpan): TextSpan | undefined {
const overlap = textSpanIntersection(span1, span2);
return overlap && overlap.length === 0 ? undefined : overlap;
}
@@ -4158,7 +4171,7 @@ namespace ts {
return position <= textSpanEnd(span) && position >= span.start;
}
export function textSpanIntersection(span1: TextSpan, span2: TextSpan) {
export function textSpanIntersection(span1: TextSpan, span2: TextSpan): TextSpan | undefined {
const start = Math.max(span1.start, span2.start);
const end = Math.min(textSpanEnd(span1), textSpanEnd(span2));
return start <= end ? createTextSpanFromBounds(start, end) : undefined;
@@ -4327,7 +4340,7 @@ namespace ts {
return createTextChangeRange(createTextSpanFromBounds(oldStartN, oldEndN), /*newLength*/ newEndN - oldStartN);
}
export function getTypeParameterOwner(d: Declaration): Declaration {
export function getTypeParameterOwner(d: Declaration): Declaration | undefined {
if (d && d.kind === SyntaxKind.TypeParameter) {
for (let current: Node = d; current; current = current.parent) {
if (isFunctionLike(current) || isClassLike(current) || current.kind === SyntaxKind.InterfaceDeclaration) {
@@ -4439,7 +4452,7 @@ namespace ts {
// Set the UI locale for string collation
setUILocale(locale);
function trySetLanguageAndTerritory(language: string, territory: string, errors?: Push<Diagnostic>): boolean {
function trySetLanguageAndTerritory(language: string, territory: string | undefined, errors?: Push<Diagnostic>): boolean {
const compilerFilePath = normalizePath(sys.getExecutingFilePath());
const containingDirectoryPath = getDirectoryPath(compilerFilePath);
@@ -4456,7 +4469,7 @@ namespace ts {
}
// TODO: Add codePage support for readFile?
let fileContents = "";
let fileContents: string | undefined = "";
try {
fileContents = sys.readFile(filePath);
}
@@ -4468,9 +4481,9 @@ namespace ts {
}
try {
// tslint:disable-next-line no-unnecessary-qualifier (making clear this is a global mutation!)
ts.localizedDiagnosticMessages = JSON.parse(fileContents);
ts.localizedDiagnosticMessages = JSON.parse(fileContents!);
}
catch (e) {
catch {
if (errors) {
errors.push(createCompilerDiagnostic(Diagnostics.Corrupted_locale_file_0, filePath));
}
@@ -4483,7 +4496,9 @@ namespace ts {
export function getOriginalNode(node: Node): Node;
export function getOriginalNode<T extends Node>(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<T extends Node>(node: Node | undefined, nodeTest: (node: Node | undefined) => node is T): T | undefined;
export function getOriginalNode(node: Node | undefined, nodeTest?: (node: Node | undefined) => boolean): Node | undefined {
if (node) {
while (node.original !== undefined) {
node = node.original;
@@ -4517,8 +4532,8 @@ namespace ts {
* @param nodeTest A callback used to ensure the correct type of parse tree node is returned.
* @returns The original parse tree node if found; otherwise, undefined.
*/
export function getParseTreeNode<T extends Node>(node: Node, nodeTest?: (node: Node) => node is T): T;
export function getParseTreeNode(node: Node, nodeTest?: (node: Node) => boolean): Node {
export function getParseTreeNode<T extends Node>(node: Node | undefined, nodeTest?: (node: Node) => node is T): T | undefined;
export function getParseTreeNode(node: Node | undefined, nodeTest?: (node: Node) => boolean): Node | undefined {
if (node === undefined || isParseTreeNode(node)) {
return node;
}
@@ -4609,7 +4624,7 @@ namespace ts {
}
}
function getDeclarationIdentifier(node: Declaration | Expression) {
function getDeclarationIdentifier(node: Declaration | Expression): Identifier | undefined {
const name = getNameOfDeclaration(node);
return isIdentifier(name) ? name : undefined;
}
@@ -4623,15 +4638,16 @@ namespace ts {
return !!(node as NamedDeclaration).name; // A 'name' property should always be a DeclarationName.
}
export function getNameOfDeclaration(declaration: Declaration | Expression): DeclarationName | undefined {
// TODO: GH#18217 This is often used as if it returns a defined result
export function getNameOfDeclaration(declaration: Declaration | Expression): DeclarationName {
if (!declaration) {
return undefined;
return undefined!;
}
switch (declaration.kind) {
case SyntaxKind.ClassExpression:
case SyntaxKind.FunctionExpression:
if (!(declaration as ClassExpression | FunctionExpression).name) {
return getAssignedName(declaration);
return getAssignedName(declaration)!;
}
break;
case SyntaxKind.Identifier:
@@ -4653,22 +4669,22 @@ namespace ts {
case SpecialPropertyAssignmentKind.PrototypeProperty:
return (expr.left as PropertyAccessExpression).name;
default:
return undefined;
return undefined!;
}
}
case SyntaxKind.JSDocCallbackTag:
return (declaration as JSDocCallbackTag).name;
return (declaration as JSDocCallbackTag).name!;
case SyntaxKind.JSDocTypedefTag:
return getNameOfJSDocTypedef(declaration as JSDocTypedefTag);
return getNameOfJSDocTypedef(declaration as JSDocTypedefTag)!;
case SyntaxKind.ExportAssignment: {
const { expression } = declaration as ExportAssignment;
return isIdentifier(expression) ? expression : undefined;
return isIdentifier(expression) ? expression : undefined!;
}
}
return (declaration as NamedDeclaration).name;
return (declaration as NamedDeclaration).name!;
}
function getAssignedName(node: Node): DeclarationName {
function getAssignedName(node: Node): DeclarationName | undefined {
if (!node.parent) {
return undefined;
}
@@ -5573,8 +5589,7 @@ namespace ts {
/* @internal */
export function isGeneratedIdentifier(node: Node): node is GeneratedIdentifier {
// Using `>` here catches both `GeneratedIdentifierKind.None` and `undefined`.
return isIdentifier(node) && (node.autoGenerateFlags & GeneratedIdentifierFlags.KindMask) > GeneratedIdentifierFlags.None;
return isIdentifier(node) && (node.autoGenerateFlags! & GeneratedIdentifierFlags.KindMask) > GeneratedIdentifierFlags.None;
}
// Keywords
@@ -5785,7 +5800,7 @@ namespace ts {
// Binding patterns
/* @internal */
export function isBindingPattern(node: Node): node is BindingPattern {
export function isBindingPattern(node: Node | undefined): node is BindingPattern {
if (node) {
const kind = node.kind;
return kind === SyntaxKind.ArrayBindingPattern
@@ -6303,8 +6318,10 @@ namespace ts {
/** True if has jsdoc nodes attached to it. */
/* @internal */
// TODO: GH#19856 Would like to return `node is Node & { jsDoc: JSDoc[] }` but it causes long compile times
export function hasJSDocNodes(node: Node): node is HasJSDoc {
return !!(node as JSDocContainer).jsDoc && (node as JSDocContainer).jsDoc.length > 0;
const { jsDoc } = node as JSDocContainer;
return !!jsDoc && jsDoc.length > 0;
}
/** True if has type node attached to it. */
+28 -28
View File
@@ -9,7 +9,7 @@ namespace ts {
* @param test A callback to execute to verify the Node is valid.
* @param lift An optional callback to execute to lift a NodeArray into a valid Node.
*/
export function visitNode<T extends Node>(node: T, visitor: Visitor, test?: (node: Node) => boolean, lift?: (node: NodeArray<Node>) => T): T;
export function visitNode<T extends Node>(node: T | undefined, visitor: Visitor | undefined, test?: (node: Node) => boolean, lift?: (node: NodeArray<Node>) => T): T;
/**
* Visits a Node using the supplied visitor, possibly returning a new Node in its place.
@@ -19,9 +19,9 @@ namespace ts {
* @param test A callback to execute to verify the Node is valid.
* @param lift An optional callback to execute to lift a NodeArray into a valid Node.
*/
export function visitNode<T extends Node>(node: T | undefined, visitor: Visitor, test?: (node: Node) => boolean, lift?: (node: NodeArray<Node>) => T): T | undefined;
export function visitNode<T extends Node>(node: T | undefined, visitor: Visitor | undefined, test?: (node: Node) => boolean, lift?: (node: NodeArray<Node>) => T): T | undefined;
export function visitNode<T extends Node>(node: T | undefined, visitor: Visitor, test?: (node: Node) => boolean, lift?: (node: NodeArray<Node>) => T): T | undefined {
export function visitNode<T extends Node>(node: T | undefined, visitor: Visitor | undefined, test?: (node: Node) => boolean, lift?: (node: NodeArray<Node>) => T): T | undefined {
if (node === undefined || visitor === undefined) {
return node;
}
@@ -32,7 +32,7 @@ namespace ts {
return node;
}
let visitedNode: Node;
let visitedNode: Node | undefined;
if (visited === undefined) {
return undefined;
}
@@ -44,7 +44,7 @@ namespace ts {
}
Debug.assertNode(visitedNode, test);
aggregateTransformFlags(visitedNode);
aggregateTransformFlags(visitedNode!);
return <T>visitedNode;
}
@@ -57,7 +57,7 @@ namespace ts {
* @param start An optional value indicating the starting offset at which to start visiting.
* @param count An optional value indicating the maximum number of nodes to visit.
*/
export function visitNodes<T extends Node>(nodes: NodeArray<T>, visitor: Visitor, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray<T>;
export function visitNodes<T extends Node>(nodes: NodeArray<T> | undefined, visitor: Visitor, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray<T>;
/**
* Visits a NodeArray using the supplied visitor, possibly returning a new NodeArray in its place.
@@ -84,7 +84,7 @@ namespace ts {
return nodes;
}
let updated: MutableNodeArray<T>;
let updated: MutableNodeArray<T> | undefined;
// Ensure start and count have valid values
const length = nodes.length;
@@ -152,7 +152,7 @@ namespace ts {
* Starts a new lexical environment and visits a parameter list, suspending the lexical
* environment upon completion.
*/
export function visitParameterList(nodes: NodeArray<ParameterDeclaration>, visitor: Visitor, context: TransformationContext, nodesVisitor = visitNodes) {
export function visitParameterList(nodes: NodeArray<ParameterDeclaration> | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor = visitNodes) {
context.startLexicalEnvironment();
const updated = nodesVisitor(nodes, visitor, isParameterDeclaration);
context.suspendLexicalEnvironment();
@@ -174,7 +174,7 @@ namespace ts {
* environment and merging hoisted declarations upon completion.
*/
export function visitFunctionBody(node: ConciseBody, visitor: Visitor, context: TransformationContext): ConciseBody;
export function visitFunctionBody(node: ConciseBody, visitor: Visitor, context: TransformationContext): ConciseBody {
export function visitFunctionBody(node: ConciseBody | undefined, visitor: Visitor, context: TransformationContext): ConciseBody | undefined {
context.resumeLexicalEnvironment();
const updated = visitNode(node, visitor, isConciseBody);
const declarations = context.endLexicalEnvironment();
@@ -204,7 +204,7 @@ namespace ts {
*/
export function visitEachChild<T extends Node>(node: T | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: typeof visitNodes, tokenVisitor?: Visitor): T | undefined;
export function visitEachChild(node: Node, visitor: Visitor, context: TransformationContext, nodesVisitor = visitNodes, tokenVisitor?: Visitor): Node {
export function visitEachChild(node: Node | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor = visitNodes, tokenVisitor?: Visitor): Node | undefined {
if (node === undefined) {
return undefined;
}
@@ -290,14 +290,14 @@ namespace ts {
nodesVisitor((<MethodDeclaration>node).typeParameters, visitor, isTypeParameterDeclaration),
visitParameterList((<MethodDeclaration>node).parameters, visitor, context, nodesVisitor),
visitNode((<MethodDeclaration>node).type, visitor, isTypeNode),
visitFunctionBody((<MethodDeclaration>node).body, visitor, context));
visitFunctionBody((<MethodDeclaration>node).body!, visitor, context));
case SyntaxKind.Constructor:
return updateConstructor(<ConstructorDeclaration>node,
nodesVisitor((<ConstructorDeclaration>node).decorators, visitor, isDecorator),
nodesVisitor((<ConstructorDeclaration>node).modifiers, visitor, isModifier),
visitParameterList((<ConstructorDeclaration>node).parameters, visitor, context, nodesVisitor),
visitFunctionBody((<ConstructorDeclaration>node).body, visitor, context));
visitFunctionBody((<ConstructorDeclaration>node).body!, visitor, context));
case SyntaxKind.GetAccessor:
return updateGetAccessor(<GetAccessorDeclaration>node,
@@ -306,7 +306,7 @@ namespace ts {
visitNode((<GetAccessorDeclaration>node).name, visitor, isPropertyName),
visitParameterList((<GetAccessorDeclaration>node).parameters, visitor, context, nodesVisitor),
visitNode((<GetAccessorDeclaration>node).type, visitor, isTypeNode),
visitFunctionBody((<GetAccessorDeclaration>node).body, visitor, context));
visitFunctionBody((<GetAccessorDeclaration>node).body!, visitor, context));
case SyntaxKind.SetAccessor:
return updateSetAccessor(<SetAccessorDeclaration>node,
@@ -314,7 +314,7 @@ namespace ts {
nodesVisitor((<SetAccessorDeclaration>node).modifiers, visitor, isModifier),
visitNode((<SetAccessorDeclaration>node).name, visitor, isPropertyName),
visitParameterList((<SetAccessorDeclaration>node).parameters, visitor, context, nodesVisitor),
visitFunctionBody((<SetAccessorDeclaration>node).body, visitor, context));
visitFunctionBody((<SetAccessorDeclaration>node).body!, visitor, context));
case SyntaxKind.CallSignature:
return updateCallSignature(<CallSignatureDeclaration>node,
@@ -333,7 +333,7 @@ namespace ts {
nodesVisitor((<IndexSignatureDeclaration>node).decorators, visitor, isDecorator),
nodesVisitor((<IndexSignatureDeclaration>node).modifiers, visitor, isModifier),
nodesVisitor((<IndexSignatureDeclaration>node).parameters, visitor, isParameterDeclaration),
visitNode((<IndexSignatureDeclaration>node).type, visitor, isTypeNode));
visitNode((<IndexSignatureDeclaration>node).type!, visitor, isTypeNode));
// Types
@@ -555,7 +555,7 @@ namespace ts {
case SyntaxKind.YieldExpression:
return updateYield(<YieldExpression>node,
visitNode((<YieldExpression>node).asteriskToken, tokenVisitor, isToken),
visitNode((<YieldExpression>node).expression, visitor, isExpression));
visitNode((<YieldExpression>node).expression!, visitor, isExpression));
case SyntaxKind.SpreadElement:
return updateSpread(<SpreadElement>node,
@@ -674,7 +674,7 @@ namespace ts {
case SyntaxKind.ThrowStatement:
return updateThrow(<ThrowStatement>node,
visitNode((<ThrowStatement>node).expression, visitor, isExpression));
visitNode((<ThrowStatement>node).expression!, visitor, isExpression));
case SyntaxKind.TryStatement:
return updateTry(<TryStatement>node,
@@ -848,7 +848,7 @@ namespace ts {
case SyntaxKind.JsxAttribute:
return updateJsxAttribute(<JsxAttribute>node,
visitNode((<JsxAttribute>node).name, visitor, isIdentifier),
visitNode((<JsxAttribute>node).initializer, visitor, isStringLiteralOrJsxExpression));
visitNode((<JsxAttribute>node).initializer!, visitor, isStringLiteralOrJsxExpression));
case SyntaxKind.JsxAttributes:
return updateJsxAttributes(<JsxAttributes>node,
@@ -930,7 +930,7 @@ namespace ts {
*
* @param nodes The NodeArray.
*/
function extractSingleNode(nodes: ReadonlyArray<Node>): Node {
function extractSingleNode(nodes: ReadonlyArray<Node>): Node | undefined {
Debug.assert(nodes.length <= 1, "Too many nodes written to output.");
return singleOrUndefined(nodes);
}
@@ -938,11 +938,11 @@ namespace ts {
/* @internal */
namespace ts {
function reduceNode<T>(node: Node, f: (memo: T, node: Node) => T, initial: T) {
function reduceNode<T>(node: Node | undefined, f: (memo: T, node: Node) => T, initial: T) {
return node ? f(initial, node) : initial;
}
function reduceNodeArray<T>(nodes: NodeArray<Node>, f: (memo: T, nodes: NodeArray<Node>) => T, initial: T) {
function reduceNodeArray<T>(nodes: NodeArray<Node> | undefined, f: (memo: T, nodes: NodeArray<Node>) => T, initial: T) {
return nodes ? f(initial, nodes) : initial;
}
@@ -954,12 +954,12 @@ namespace ts {
* @param initial The initial value to supply to the reduction.
* @param f The callback function
*/
export function reduceEachChild<T>(node: Node, initial: T, cbNode: (memo: T, node: Node) => T, cbNodeArray?: (memo: T, nodes: NodeArray<Node>) => T): T {
export function reduceEachChild<T>(node: Node | undefined, initial: T, cbNode: (memo: T, node: Node) => T, cbNodeArray?: (memo: T, nodes: NodeArray<Node>) => T): T {
if (node === undefined) {
return initial;
}
const reduceNodes: (nodes: NodeArray<Node>, f: ((memo: T, node: Node) => T) | ((memo: T, node: NodeArray<Node>) => T), initial: T) => T = cbNodeArray ? reduceNodeArray : reduceLeft;
const reduceNodes: (nodes: NodeArray<Node> | undefined, f: ((memo: T, node: Node) => T) | ((memo: T, node: NodeArray<Node>) => T), initial: T) => T = cbNodeArray ? reduceNodeArray : reduceLeft;
const cbNodes = cbNodeArray || cbNode;
const kind = node.kind;
@@ -1456,13 +1456,13 @@ namespace ts {
/**
* Merges generated lexical declarations into a new statement list.
*/
export function mergeLexicalEnvironment(statements: NodeArray<Statement>, declarations: ReadonlyArray<Statement>): NodeArray<Statement>;
export function mergeLexicalEnvironment(statements: NodeArray<Statement>, declarations: ReadonlyArray<Statement> | undefined): NodeArray<Statement>;
/**
* Appends generated lexical declarations to an array of statements.
*/
export function mergeLexicalEnvironment(statements: Statement[], declarations: ReadonlyArray<Statement>): Statement[];
export function mergeLexicalEnvironment(statements: Statement[] | NodeArray<Statement>, declarations: ReadonlyArray<Statement>) {
export function mergeLexicalEnvironment(statements: Statement[], declarations: ReadonlyArray<Statement> | undefined): Statement[];
export function mergeLexicalEnvironment(statements: Statement[] | NodeArray<Statement>, declarations: ReadonlyArray<Statement> | undefined) {
if (!some(declarations)) {
return statements;
}
@@ -1566,10 +1566,10 @@ namespace ts {
: noop;
export const assertNode = shouldAssert(AssertionLevel.Normal)
? (node: Node, test: (node: Node) => boolean, message?: string): void => assert(
? (node: Node | undefined, test: ((node: Node | undefined) => boolean) | undefined, message?: string): void => assert(
test === undefined || test(node),
message || "Unexpected node.",
() => `Node ${formatSyntaxKind(node.kind)} did not pass test '${getFunctionName(test)}'.`,
() => `Node ${formatSyntaxKind(node!.kind)} did not pass test '${getFunctionName(test!)}'.`,
assertNode)
: noop;
+44 -41
View File
@@ -4,7 +4,7 @@ namespace ts {
getCurrentDirectory: () => sys.getCurrentDirectory(),
getNewLine: () => sys.newLine,
getCanonicalFileName: createGetCanonicalFileName(sys.useCaseSensitiveFileNames)
} : undefined;
} : undefined!; // TODO: GH#18217
/**
* Create a function that reports error by writing to the system and handles the formating of the diagnostic
@@ -23,7 +23,7 @@ namespace ts {
return diagnostic => {
diagnostics[0] = diagnostic;
system.write(formatDiagnosticsWithColorAndContext(diagnostics, host) + host.getNewLine());
diagnostics[0] = undefined;
diagnostics[0] = undefined!; // TODO: GH#18217
};
}
@@ -91,7 +91,7 @@ namespace ts {
const host: ParseConfigFileHost = <any>system;
host.onUnRecoverableConfigFileDiagnostic = diagnostic => reportUnrecoverableDiagnostic(sys, reportDiagnostic, diagnostic);
const result = getParsedCommandLineOfConfigFile(configFileName, optionsToExtend, host);
host.onUnRecoverableConfigFileDiagnostic = undefined;
host.onUnRecoverableConfigFileDiagnostic = undefined!; // TODO: GH#18217
return result;
}
@@ -177,9 +177,9 @@ namespace ts {
/**
* Creates the watch compiler host that can be extended with config file or root file names and options host
*/
function createWatchCompilerHost<T extends BuilderProgram = EmitAndSemanticDiagnosticsBuilderProgram>(system = sys, createProgram?: CreateProgram<T>, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHost<T> {
function createWatchCompilerHost<T extends BuilderProgram = EmitAndSemanticDiagnosticsBuilderProgram>(system = sys, createProgram: CreateProgram<T> | undefined, reportDiagnostic: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHost<T> {
if (!createProgram) {
createProgram = createEmitAndSemanticDiagnosticsBuilderProgram as any;
createProgram = createEmitAndSemanticDiagnosticsBuilderProgram as any as CreateProgram<T>;
}
let host: DirectoryStructureHost = system;
@@ -197,18 +197,18 @@ namespace ts {
directoryExists: path => system.directoryExists(path),
getDirectories: path => system.getDirectories(path),
readDirectory: (path, extensions, exclude, include, depth) => system.readDirectory(path, extensions, exclude, include, depth),
realpath: system.realpath && (path => system.realpath(path)),
realpath: system.realpath && (path => system.realpath!(path)),
getEnvironmentVariable: system.getEnvironmentVariable && (name => system.getEnvironmentVariable(name)),
watchFile: system.watchFile ? ((path, callback, pollingInterval) => system.watchFile(path, callback, pollingInterval)) : () => noopFileWatcher,
watchDirectory: system.watchDirectory ? ((path, callback, recursive) => system.watchDirectory(path, callback, recursive)) : () => noopFileWatcher,
setTimeout: system.setTimeout ? ((callback, ms, ...args: any[]) => system.setTimeout.call(system, callback, ms, ...args)) : noop,
clearTimeout: system.clearTimeout ? (timeoutId => system.clearTimeout(timeoutId)) : noop,
watchFile: system.watchFile ? ((path, callback, pollingInterval) => system.watchFile!(path, callback, pollingInterval)) : () => noopFileWatcher,
watchDirectory: system.watchDirectory ? ((path, callback, recursive) => system.watchDirectory!(path, callback, recursive)) : () => noopFileWatcher,
setTimeout: system.setTimeout ? ((callback, ms, ...args: any[]) => system.setTimeout!.call(system, callback, ms, ...args)) : noop,
clearTimeout: system.clearTimeout ? (timeoutId => system.clearTimeout!(timeoutId)) : noop,
trace: s => system.write(s),
onWatchStatusChange,
createDirectory: path => system.createDirectory(path),
writeFile: (path, data, writeByteOrderMark) => system.writeFile(path, data, writeByteOrderMark),
onCachedDirectoryStructureHostCreate: cacheHost => host = cacheHost || system,
createHash: system.createHash && (s => system.createHash(s)),
createHash: system.createHash && (s => system.createHash!(s)),
createProgram,
afterProgramCreate: emitFilesAndReportErrorUsingBuilder
};
@@ -246,9 +246,9 @@ namespace ts {
* Creates the watch compiler host from system for config file in watch mode
*/
export function createWatchCompilerHostOfConfigFile<T extends BuilderProgram = EmitAndSemanticDiagnosticsBuilderProgram>(configFileName: string, optionsToExtend: CompilerOptions | undefined, system: System, createProgram?: CreateProgram<T>, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHostOfConfigFile<T> {
reportDiagnostic = reportDiagnostic || createDiagnosticReporter(system);
const host = createWatchCompilerHost(system, createProgram, reportDiagnostic, reportWatchStatus) as WatchCompilerHostOfConfigFile<T>;
host.onUnRecoverableConfigFileDiagnostic = diagnostic => reportUnrecoverableDiagnostic(system, reportDiagnostic, diagnostic);
const diagnosticReporter = reportDiagnostic || createDiagnosticReporter(system);
const host = createWatchCompilerHost(system, createProgram, diagnosticReporter, reportWatchStatus) as WatchCompilerHostOfConfigFile<T>;
host.onUnRecoverableConfigFileDiagnostic = diagnostic => reportUnrecoverableDiagnostic(system, diagnosticReporter, diagnostic);
host.configFileName = configFileName;
host.optionsToExtend = optionsToExtend;
return host;
@@ -270,6 +270,8 @@ namespace ts {
/** Create the program with rootNames and options, if they are undefined, oldProgram and new configFile diagnostics create new program */
export type CreateProgram<T extends BuilderProgram> = (rootNames: ReadonlyArray<string> | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: T, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>) => T;
export interface WatchCompilerHost<T extends BuilderProgram> {
// TODO: GH#18217 Optional methods are frequently asserted
/**
* Used to create the program when need for program creation or recreation detected
*/
@@ -314,12 +316,12 @@ namespace ts {
/** If provided would be used to write log about compilation */
trace?(s: string): void;
/** If provided is used to get the environment variable */
getEnvironmentVariable?(name: string): string;
getEnvironmentVariable?(name: string): string | undefined;
/** If provided, used to resolve the module names, otherwise typescript's default module resolution */
resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[]): ResolvedModule[];
/** If provided, used to resolve type reference directives, otherwise typescript's default resolution */
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): (ResolvedTypeReferenceDirective | undefined)[];
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[];
/** Used to watch changes in source files, missing files needed to update the program or config file */
watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher;
@@ -334,6 +336,7 @@ namespace ts {
/** Internal interface used to wire emit through same host */
/*@internal*/
export interface WatchCompilerHost<T extends BuilderProgram> {
// TODO: GH#18217 Optional methods are frequently asserted
createDirectory?(path: string): void;
writeFile?(path: string, data: string, writeByteOrderMark?: boolean): void;
onCachedDirectoryStructureHostCreate?(host: CachedDirectoryStructureHost): void;
@@ -405,7 +408,7 @@ namespace ts {
export function createWatchCompilerHost<T extends BuilderProgram>(configFileName: string, optionsToExtend: CompilerOptions | undefined, system: System, createProgram?: CreateProgram<T>, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHostOfConfigFile<T>;
export function createWatchCompilerHost<T extends BuilderProgram>(rootFilesOrConfigFileName: string | string[], options: CompilerOptions | undefined, system: System, createProgram?: CreateProgram<T>, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHostOfFilesAndCompilerOptions<T> | WatchCompilerHostOfConfigFile<T> {
if (isArray(rootFilesOrConfigFileName)) {
return createWatchCompilerHostOfFilesAndCompilerOptions(rootFilesOrConfigFileName, options, system, createProgram, reportDiagnostic, reportWatchStatus);
return createWatchCompilerHostOfFilesAndCompilerOptions(rootFilesOrConfigFileName, options!, system, createProgram, reportDiagnostic, reportWatchStatus); // TODO: GH#18217
}
else {
return createWatchCompilerHostOfConfigFile(rootFilesOrConfigFileName, options, system, createProgram, reportDiagnostic, reportWatchStatus);
@@ -442,7 +445,7 @@ namespace ts {
let timerToUpdateProgram: any; // timer callback to recompile the program
const sourceFilesCache = createMap<HostFileInfo>(); // Cache that stores the source file and version info
let missingFilePathsRequestedForRelease: Path[]; // These paths are held temparirly so that we can remove the entry from source file cache if the file is not tracked by missing files
let missingFilePathsRequestedForRelease: Path[] | undefined; // These paths are held temparirly so that we can remove the entry from source file cache if the file is not tracked by missing files
let hasChangedCompilerOptions = false; // True if the compiler options have changed between compilations
let hasChangedAutomaticTypeDirectiveNames = false; // True if the automatic type directives have changed
@@ -456,14 +459,14 @@ namespace ts {
let configFileParsingDiagnostics: ReadonlyArray<Diagnostic> | undefined;
let hasChangedConfigFileParsingErrors = false;
const cachedDirectoryStructureHost = configFileName && createCachedDirectoryStructureHost(host, currentDirectory, useCaseSensitiveFileNames);
const cachedDirectoryStructureHost = configFileName === undefined ? undefined : createCachedDirectoryStructureHost(host, currentDirectory, useCaseSensitiveFileNames);
if (cachedDirectoryStructureHost && host.onCachedDirectoryStructureHostCreate) {
host.onCachedDirectoryStructureHostCreate(cachedDirectoryStructureHost);
}
const directoryStructureHost: DirectoryStructureHost = cachedDirectoryStructureHost || host;
const parseConfigFileHost: ParseConfigFileHost = {
useCaseSensitiveFileNames,
readDirectory: (path, extensions, exclude, include, depth) => directoryStructureHost.readDirectory(path, extensions, exclude, include, depth),
readDirectory: (path, extensions, exclude, include, depth) => directoryStructureHost.readDirectory!(path, extensions, exclude, include, depth),
fileExists: path => host.fileExists(path),
readFile,
getCurrentDirectory,
@@ -485,10 +488,10 @@ namespace ts {
newLine = updateNewLine();
}
const trace = host.trace && ((s: string) => { host.trace(s + newLine); });
const trace = host.trace && ((s: string) => { host.trace!(s + newLine); });
const watchLogLevel = trace ? compilerOptions.extendedDiagnostics ? WatchLogLevel.Verbose :
compilerOptions.diagnostis ? WatchLogLevel.TriggerOnly : WatchLogLevel.None : WatchLogLevel.None;
const writeLog: (s: string) => void = watchLogLevel !== WatchLogLevel.None ? trace : noop;
const writeLog: (s: string) => void = watchLogLevel !== WatchLogLevel.None ? trace! : noop; // TODO: GH#18217
const { watchFile, watchFilePath, watchDirectory } = getWatchFactory<string>(watchLogLevel, writeLog);
const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames);
@@ -502,7 +505,7 @@ namespace ts {
// Members for CompilerHost
getSourceFile: (fileName, languageVersion, onError?, shouldCreateNewSourceFile?) => getVersionedSourceFileByPath(fileName, toPath(fileName), languageVersion, onError, shouldCreateNewSourceFile),
getSourceFileByPath: getVersionedSourceFileByPath,
getDefaultLibLocation: host.getDefaultLibLocation && (() => host.getDefaultLibLocation()),
getDefaultLibLocation: host.getDefaultLibLocation && (() => host.getDefaultLibLocation!()),
getDefaultLibFileName: options => host.getDefaultLibFileName(options),
writeFile,
getCurrentDirectory,
@@ -512,12 +515,12 @@ namespace ts {
fileExists,
readFile,
trace,
directoryExists: directoryStructureHost.directoryExists && (path => directoryStructureHost.directoryExists(path)),
getDirectories: directoryStructureHost.getDirectories && (path => directoryStructureHost.getDirectories(path)),
realpath: host.realpath && (s => host.realpath(s)),
getEnvironmentVariable: host.getEnvironmentVariable ? (name => host.getEnvironmentVariable(name)) : (() => ""),
directoryExists: directoryStructureHost.directoryExists && (path => directoryStructureHost.directoryExists!(path)),
getDirectories: (directoryStructureHost.getDirectories && ((path: string) => directoryStructureHost.getDirectories!(path)))!, // TODO: GH#18217
realpath: host.realpath && (s => host.realpath!(s)),
getEnvironmentVariable: host.getEnvironmentVariable ? (name => host.getEnvironmentVariable!(name)) : (() => ""),
onReleaseOldSourceFile,
createHash: host.createHash && (data => host.createHash(data)),
createHash: host.createHash && (data => host.createHash!(data)),
// Members for ResolutionCacheHost
toPath,
getCompilationSettings: () => compilerOptions,
@@ -541,10 +544,10 @@ namespace ts {
);
// Resolve module using host module resolution strategy if provided otherwise use resolution cache to resolve module names
compilerHost.resolveModuleNames = host.resolveModuleNames ?
((moduleNames, containingFile, reusedNames) => host.resolveModuleNames(moduleNames, containingFile, reusedNames)) :
((moduleNames, containingFile, reusedNames) => host.resolveModuleNames!(moduleNames, containingFile, reusedNames)) :
((moduleNames, containingFile, reusedNames) => resolutionCache.resolveModuleNames(moduleNames, containingFile, reusedNames));
compilerHost.resolveTypeReferenceDirectives = host.resolveTypeReferenceDirectives ?
((typeDirectiveNames, containingFile) => host.resolveTypeReferenceDirectives(typeDirectiveNames, containingFile)) :
((typeDirectiveNames, containingFile) => host.resolveTypeReferenceDirectives!(typeDirectiveNames, containingFile)) :
((typeDirectiveNames, containingFile) => resolutionCache.resolveTypeReferenceDirectives(typeDirectiveNames, containingFile));
const userProvidedResolution = !!host.resolveModuleNames || !!host.resolveTypeReferenceDirectives;
@@ -659,15 +662,15 @@ namespace ts {
const path = toPath(fileName);
// If file is missing on host from cache, we can definitely say file doesnt exist
// otherwise we need to ensure from the disk
if (isFileMissingOnHost(sourceFilesCache.get(path))) {
if (isFileMissingOnHost(sourceFilesCache.get(path)!)) {
return true;
}
return directoryStructureHost.fileExists(fileName);
}
function getVersionedSourceFileByPath(fileName: string, path: Path, languageVersion: ScriptTarget, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile {
const hostSourceFile = sourceFilesCache.get(path);
function getVersionedSourceFileByPath(fileName: string, path: Path, languageVersion: ScriptTarget, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined {
const hostSourceFile = sourceFilesCache.get(path)!;
// No source file on the host
if (isFileMissingOnHost(hostSourceFile)) {
return undefined;
@@ -712,7 +715,7 @@ namespace ts {
return hostSourceFile.sourceFile;
function getNewSourceFile() {
let text: string;
let text: string | undefined;
try {
performance.mark("beforeIORead");
text = host.readFile(fileName, compilerOptions.charset);
@@ -742,7 +745,7 @@ namespace ts {
}
}
function getSourceVersion(path: Path): string {
function getSourceVersion(path: Path): string | undefined {
const hostSourceFile = sourceFilesCache.get(path);
return !hostSourceFile || isFileMissingOnHost(hostSourceFile) ? undefined : hostSourceFile.version.toString();
}
@@ -843,13 +846,13 @@ namespace ts {
}
function parseConfigFile() {
setConfigFileParsingResult(getParsedCommandLineOfConfigFile(configFileName, optionsToExtendForConfigFile, parseConfigFileHost));
setConfigFileParsingResult(getParsedCommandLineOfConfigFile(configFileName, optionsToExtendForConfigFile, parseConfigFileHost)!); // TODO: GH#18217
}
function setConfigFileParsingResult(configFileParseResult: ParsedCommandLine) {
rootFileNames = configFileParseResult.fileNames;
compilerOptions = configFileParseResult.options;
configFileSpecs = configFileParseResult.configFileSpecs;
configFileSpecs = configFileParseResult.configFileSpecs!; // TODO: GH#18217
configFileParsingDiagnostics = getConfigFileParsingDiagnostics(configFileParseResult);
hasChangedConfigFileParsingErrors = true;
}
@@ -881,7 +884,7 @@ namespace ts {
updateCachedSystemWithFile(fileName, missingFilePath, eventKind);
if (eventKind === FileWatcherEventKind.Created && missingFilesMap.has(missingFilePath)) {
missingFilesMap.get(missingFilePath).close();
missingFilesMap.get(missingFilePath)!.close();
missingFilesMap.delete(missingFilePath);
// Delete the entry in the source files cache so that new source file is created
@@ -941,10 +944,10 @@ namespace ts {
}
function ensureDirectoriesExist(directoryPath: string) {
if (directoryPath.length > getRootLength(directoryPath) && !host.directoryExists(directoryPath)) {
if (directoryPath.length > getRootLength(directoryPath) && !host.directoryExists!(directoryPath)) {
const parentDirectory = getDirectoryPath(directoryPath);
ensureDirectoriesExist(parentDirectory);
host.createDirectory(directoryPath);
host.createDirectory!(directoryPath);
}
}
@@ -953,7 +956,7 @@ namespace ts {
performance.mark("beforeIOWrite");
ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName)));
host.writeFile(fileName, text, writeByteOrderMark);
host.writeFile!(fileName, text, writeByteOrderMark);
performance.mark("afterIOWrite");
performance.measure("I/O Write", "beforeIOWrite", "afterIOWrite");
+11 -10
View File
@@ -7,6 +7,7 @@ namespace ts {
fileExists(path: string): boolean;
readFile(path: string, encoding?: string): string | undefined;
// TODO: GH#18217 Optional methods are frequently used as non-optional
directoryExists?(path: string): boolean;
getDirectories?(path: string): string[];
readDirectory?(path: string, extensions?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>, depth?: number): string[];
@@ -76,8 +77,8 @@ namespace ts {
function createCachedFileSystemEntries(rootDir: string, rootDirPath: Path) {
const resultFromHost: MutableFileSystemEntries = {
files: map(host.readDirectory(rootDir, /*extensions*/ undefined, /*exclude*/ undefined, /*include*/["*.*"]), getBaseNameOfFileName) || [],
directories: host.getDirectories(rootDir) || []
files: map(host.readDirectory!(rootDir, /*extensions*/ undefined, /*exclude*/ undefined, /*include*/["*.*"]), getBaseNameOfFileName) || [],
directories: host.getDirectories!(rootDir) || []
};
cachedReadDirectoryResult.set(ensureTrailingDirectorySeparator(rootDirPath), resultFromHost);
@@ -131,7 +132,7 @@ namespace ts {
if (result) {
updateFilesOfFileSystemEntry(result, getBaseNameOfFileName(fileName), /*fileExists*/ true);
}
return host.writeFile(fileName, data, writeByteOrderMark);
return host.writeFile!(fileName, data, writeByteOrderMark);
}
function fileExists(fileName: string): boolean {
@@ -143,7 +144,7 @@ namespace ts {
function directoryExists(dirPath: string): boolean {
const path = toPath(dirPath);
return cachedReadDirectoryResult.has(ensureTrailingDirectorySeparator(path)) || host.directoryExists(dirPath);
return cachedReadDirectoryResult.has(ensureTrailingDirectorySeparator(path)) || host.directoryExists!(dirPath);
}
function createDirectory(dirPath: string) {
@@ -153,7 +154,7 @@ namespace ts {
if (result) {
updateFileSystemEntry(result.directories, baseFileName, /*isValid*/ true);
}
host.createDirectory(dirPath);
host.createDirectory!(dirPath);
}
function getDirectories(rootDir: string): string[] {
@@ -162,7 +163,7 @@ namespace ts {
if (result) {
return result.directories.slice();
}
return host.getDirectories(rootDir);
return host.getDirectories!(rootDir);
}
function readDirectory(rootDir: string, extensions?: ReadonlyArray<string>, excludes?: ReadonlyArray<string>, includes?: ReadonlyArray<string>, depth?: number): string[] {
@@ -171,12 +172,12 @@ namespace ts {
if (result) {
return matchFiles(rootDir, extensions, excludes, includes, useCaseSensitiveFileNames, currentDirectory, depth, getFileSystemEntries);
}
return host.readDirectory(rootDir, extensions, excludes, includes, depth);
return host.readDirectory!(rootDir, extensions, excludes, includes, depth);
function getFileSystemEntries(dir: string) {
function getFileSystemEntries(dir: string): FileSystemEntries {
const path = toPath(dir);
if (path === rootDirPath) {
return result;
return result!;
}
return tryReadDirectory(dir, path) || emptyFileSystemEntries;
}
@@ -387,7 +388,7 @@ namespace ts {
type WatchCallback<T, U> = (fileName: string, cbOptional?: T, passThrough?: U) => void;
type AddWatch<H, T, U, V> = (host: H, file: string, cb: WatchCallback<U, V>, flags: T, passThrough?: V, detailInfo1?: undefined, detailInfo2?: undefined) => FileWatcher;
export type GetDetailWatchInfo<X, Y> = (detailInfo1: X, detailInfo2: Y) => string;
export type GetDetailWatchInfo<X, Y> = (detailInfo1: X, detailInfo2: Y | undefined) => string;
type CreateFileWatcher<H, T, U, V, X, Y> = (host: H, file: string, cb: WatchCallback<U, V>, flags: T, passThrough: V | undefined, detailInfo1: X | undefined, detailInfo2: Y | undefined, addWatch: AddWatch<H, T, U, V>, log: (s: string) => void, watchCaption: string, getDetailWatchInfo: GetDetailWatchInfo<X, Y> | undefined) => FileWatcher;
function getCreateFileWatcher<H, T, U, V, X, Y>(watchLogLevel: WatchLogLevel, addWatch: AddWatch<H, T, U, V>): CreateFileWatcher<H, T, U, V, X, Y> {
+2 -2
View File
@@ -182,8 +182,8 @@ namespace compiler {
}
public getSourceMapRecord(): string | undefined {
if (this.result.sourceMaps && this.result.sourceMaps.length > 0) {
return Harness.SourceMapRecorder.getSourceMapRecord(this.result.sourceMaps, this.program, Array.from(this.js.values()), Array.from(this.dts.values()));
if (this.result!.sourceMaps && this.result!.sourceMaps!.length > 0) {
return Harness.SourceMapRecorder.getSourceMapRecord(this.result!.sourceMaps!, this.program!, Array.from(this.js.values()), Array.from(this.dts.values()));
}
}
+11 -11
View File
@@ -81,7 +81,7 @@ class CompilerBaselineRunner extends RunnerBase {
private runSuite(fileName: string, test?: CompilerFileBasedTest, configuration?: Harness.FileBasedTestConfiguration) {
// Mocha holds onto the closure environment of the describe callback even after the test is done.
// Everything declared here should be cleared out in the "after" callback.
let compilerTest: CompilerTest | undefined;
let compilerTest!: CompilerTest;
before(() => { compilerTest = new CompilerTest(fileName, test && test.payload, configuration); });
it(`Correct errors for ${fileName}`, () => { compilerTest.verifyDiagnostics(); });
it(`Correct module resolution tracing for ${fileName}`, () => { compilerTest.verifyModuleResolution(); });
@@ -89,7 +89,7 @@ class CompilerBaselineRunner extends RunnerBase {
it(`Correct JS output for ${fileName}`, () => { if (this.emit) compilerTest.verifyJavaScriptOutput(); });
it(`Correct Sourcemap output for ${fileName}`, () => { compilerTest.verifySourceMapOutput(); });
it(`Correct type/symbol baselines for ${fileName}`, () => { compilerTest.verifyTypesAndSymbols(); });
after(() => { compilerTest = undefined; });
after(() => { compilerTest = undefined!; });
}
private parseOptions() {
@@ -131,7 +131,7 @@ class CompilerTest {
const rootDir = fileName.indexOf("conformance") === -1 ? "tests/cases/compiler/" : ts.getDirectoryPath(fileName) + "/";
if (testCaseContent === undefined) {
testCaseContent = Harness.TestCaseParser.makeUnitsFromTest(Harness.IO.readFile(fileName), fileName, rootDir);
testCaseContent = Harness.TestCaseParser.makeUnitsFromTest(Harness.IO.readFile(fileName)!, fileName, rootDir);
}
if (configurationOverrides) {
@@ -140,13 +140,13 @@ class CompilerTest {
const units = testCaseContent.testUnitData;
this.harnessSettings = testCaseContent.settings;
let tsConfigOptions: ts.CompilerOptions;
let tsConfigOptions: ts.CompilerOptions | undefined;
this.tsConfigFiles = [];
if (testCaseContent.tsConfig) {
assert.equal(testCaseContent.tsConfig.fileNames.length, 0, `list of files in tsconfig is not currently supported`);
tsConfigOptions = ts.cloneCompilerOptions(testCaseContent.tsConfig.options);
this.tsConfigFiles.push(this.createHarnessTestFile(testCaseContent.tsConfigFileUnitData, rootDir, ts.combinePaths(rootDir, tsConfigOptions.configFilePath)));
this.tsConfigFiles.push(this.createHarnessTestFile(testCaseContent.tsConfigFileUnitData!, rootDir, ts.combinePaths(rootDir, tsConfigOptions.configFilePath!)));
}
else {
const baseUrl = this.harnessSettings.baseUrl;
@@ -156,7 +156,7 @@ class CompilerTest {
}
this.lastUnit = units[units.length - 1];
this.hasNonDtsFiles = ts.forEach(units, unit => !ts.fileExtensionIs(unit.name, ts.Extension.Dts));
this.hasNonDtsFiles = units.some(unit => !ts.fileExtensionIs(unit.name, ts.Extension.Dts));
// We need to assemble the list of input files for the compiler and other related files on the 'filesystem' (ie in a multi-file test)
// If the last file in a test uses require or a triple slash reference we'll assume all other files will be brought in via references,
// otherwise, assume all files are just meant to be in the same compilation session without explicit references to one another.
@@ -179,7 +179,7 @@ class CompilerTest {
if (tsConfigOptions && tsConfigOptions.configFilePath !== undefined) {
tsConfigOptions.configFilePath = ts.combinePaths(rootDir, tsConfigOptions.configFilePath);
tsConfigOptions.configFile.fileName = tsConfigOptions.configFilePath;
tsConfigOptions.configFile!.fileName = tsConfigOptions.configFilePath;
}
this.result = Harness.Compiler.compileFiles(
@@ -194,7 +194,7 @@ class CompilerTest {
public static getConfigurations(file: string): CompilerFileBasedTest {
// also see `parseCompilerTestConfigurations` in tests/webTestServer.ts
const content = Harness.IO.readFile(file);
const content = Harness.IO.readFile(file)!;
const rootDir = file.indexOf("conformance") === -1 ? "tests/cases/compiler/" : ts.getDirectoryPath(file) + "/";
const payload = Harness.TestCaseParser.makeUnitsFromTest(content, file, rootDir);
const settings = Harness.TestCaseParser.extractCompilerSettings(content);
@@ -222,7 +222,7 @@ class CompilerTest {
public verifySourceMapRecord() {
if (this.options.sourceMap || this.options.inlineSourceMap || this.options.declarationMap) {
Harness.Baseline.runBaseline(this.justName.replace(/\.tsx?$/, ".sourcemap.txt"), () => {
const record = utils.removeTestPathPrefixes(this.result.getSourceMapRecord());
const record = utils.removeTestPathPrefixes(this.result.getSourceMapRecord()!);
if ((this.options.noEmitOnError && this.result.diagnostics.length !== 0) || record === undefined) {
// Because of the noEmitOnError option no files are created. We need to return null because baselining isn't required.
/* tslint:disable:no-null-keyword */
@@ -263,8 +263,8 @@ class CompilerTest {
Harness.Compiler.doTypeAndSymbolBaseline(
this.justName,
this.result.program,
this.toBeCompiled.concat(this.otherFiles).filter(file => !!this.result.program.getSourceFile(file.unitName)));
this.result.program!,
this.toBeCompiled.concat(this.otherFiles).filter(file => !!this.result.program!.getSourceFile(file.unitName)));
}
private makeUnitName(name: string, root: string) {
+2 -2
View File
@@ -151,9 +151,9 @@ namespace documents {
return match ? new SourceMap(/*mapFile*/ undefined, new Buffer(match[1], "base64").toString("utf8")) : undefined;
}
public static fromSource(text: string) {
public static fromSource(text: string): SourceMap | undefined {
const url = this.getUrl(text);
return url && this.fromUrl(url);
return url === undefined ? undefined : this.fromUrl(url);
}
public getMappingsForEmittedLine(emittedLine: number): ReadonlyArray<Mapping> | undefined {
+2 -2
View File
@@ -16,7 +16,7 @@ interface UserConfig {
abstract class ExternalCompileRunnerBase extends RunnerBase {
abstract testDir: string;
abstract report(result: ExecResult, cwd: string): string;
abstract report(result: ExecResult, cwd: string): string | null;
enumerateTestFiles() {
return Harness.IO.getDirectories(this.testDir);
}
@@ -48,7 +48,7 @@ abstract class ExternalCompileRunnerBase extends RunnerBase {
let cwd = path.join(Harness.IO.getWorkspaceRoot(), cls.testDir, directoryName);
const originalCwd = cwd;
const stdio = isWorker ? "pipe" : "inherit";
let types: string[];
let types: string[] | undefined;
if (fs.existsSync(path.join(cwd, "test.json"))) {
const submoduleDir = path.join(cwd, directoryName);
const reset = cp.spawnSync("git", ["reset", "HEAD", "--hard"], { cwd: submoduleDir, timeout, shell: true, stdio });
+6 -6
View File
@@ -19,7 +19,7 @@ namespace fakes {
public readonly output: string[] = [];
public readonly newLine: string;
public readonly useCaseSensitiveFileNames: boolean;
public exitCode: number;
public exitCode: number | undefined;
private readonly _executingFilePath: string | undefined;
private readonly _env: Record<string, string> | undefined;
@@ -128,7 +128,7 @@ namespace fakes {
public getModifiedTime(path: string) {
const stats = this._getStats(path);
return stats ? stats.mtime : undefined;
return stats ? stats.mtime : undefined!; // TODO: GH#18217
}
public createHash(data: string): string {
@@ -144,8 +144,8 @@ namespace fakes {
}
}
public getEnvironmentVariable(name: string): string | undefined {
return this._env && this._env[name];
public getEnvironmentVariable(name: string): string {
return (this._env && this._env[name])!; // TODO: GH#18217
}
private _getStats(path: string) {
@@ -275,7 +275,7 @@ namespace fakes {
this._outputsMap.set(document.file, this.outputs.length);
this.outputs.push(document);
}
this.outputs[this._outputsMap.get(document.file)] = document;
this.outputs[this._outputsMap.get(document.file)!] = document;
}
public trace(s: string): void {
@@ -332,7 +332,7 @@ namespace fakes {
let fs = this.vfs;
while (fs.shadowRoot) {
try {
const shadowRootStats = fs.shadowRoot.existsSync(canonicalFileName) && fs.shadowRoot.statSync(canonicalFileName);
const shadowRootStats = fs.shadowRoot.existsSync(canonicalFileName) ? fs.shadowRoot.statSync(canonicalFileName) : undefined!; // TODO: GH#18217
if (shadowRootStats.dev !== stats.dev ||
shadowRootStats.ino !== stats.ino ||
shadowRootStats.mtimeMs !== stats.mtimeMs) {
+117 -117
View File
@@ -184,7 +184,7 @@ namespace FourSlash {
private inputFiles = ts.createMap<string>(); // Map between inputFile's fileName and its content for easily looking up when resolving references
private static getDisplayPartsJson(displayParts: ts.SymbolDisplayPart[]) {
private static getDisplayPartsJson(displayParts: ts.SymbolDisplayPart[] | undefined) {
let result = "";
ts.forEach(displayParts, part => {
if (result) {
@@ -204,7 +204,7 @@ namespace FourSlash {
// Add input file which has matched file name with the given reference-file path.
// This is necessary when resolveReference flag is specified
private addMatchedInputFile(referenceFilePath: string, extensions: ReadonlyArray<string>) {
private addMatchedInputFile(referenceFilePath: string, extensions: ReadonlyArray<string> | undefined) {
const inputFiles = this.inputFiles;
const languageServiceAdapterHost = this.languageServiceAdapterHost;
const didAdd = tryAdd(referenceFilePath);
@@ -243,16 +243,16 @@ namespace FourSlash {
compilationOptions.skipDefaultLibCheck = true;
// Initialize the language service with all the scripts
let startResolveFileRef: FourSlashFile;
let startResolveFileRef: FourSlashFile | undefined;
let configFileName: string;
let configFileName: string | undefined;
for (const file of testData.files) {
// Create map between fileName and its content for easily looking up when resolveReference flag is specified
this.inputFiles.set(file.fileName, file.content);
if (isConfig(file)) {
const configJson = ts.parseConfigFileTextToJson(file.fileName, file.content);
if (configJson.config === undefined) {
throw new Error(`Failed to parse test ${file.fileName}: ${configJson.error.messageText}`);
throw new Error(`Failed to parse test ${file.fileName}: ${configJson.error!.messageText}`);
}
// Extend our existing compiler options so that we can also support tsconfig only options
@@ -280,12 +280,12 @@ namespace FourSlash {
const baseDir = ts.normalizePath(ts.getDirectoryPath(configFileName));
const files: vfs.FileSet = { [baseDir]: {} };
this.inputFiles.forEach((data, path) => {
const scriptInfo = new Harness.LanguageService.ScriptInfo(path, undefined, /*isRootFile*/ false);
const scriptInfo = new Harness.LanguageService.ScriptInfo(path, undefined!, /*isRootFile*/ false); // TODO: GH#18217
files[path] = new vfs.File(data, { meta: { scriptInfo } });
});
const fs = new vfs.FileSystem(/*ignoreCase*/ true, { cwd: baseDir, files });
const host = new fakes.ParseConfigHost(fs);
const jsonSourceFile = ts.parseJsonText(configFileName, this.inputFiles.get(configFileName));
const jsonSourceFile = ts.parseJsonText(configFileName, this.inputFiles.get(configFileName)!);
compilationOptions = ts.parseJsonSourceFileConfigFileContent(jsonSourceFile, host, baseDir, compilationOptions, configFileName).options;
}
@@ -323,7 +323,7 @@ namespace FourSlash {
// Check if no-default-lib flag is false and if so add default library
if (!resolvedResult.isLibFile) {
this.languageServiceAdapterHost.addScript(Harness.Compiler.defaultLibFileName,
Harness.Compiler.getDefaultLibrarySourceFile().text, /*isRootFile*/ false);
Harness.Compiler.getDefaultLibrarySourceFile()!.text, /*isRootFile*/ false);
}
}
else {
@@ -335,7 +335,7 @@ namespace FourSlash {
});
if (!compilationOptions.noLib) {
this.languageServiceAdapterHost.addScript(Harness.Compiler.defaultLibFileName,
Harness.Compiler.getDefaultLibrarySourceFile().text, /*isRootFile*/ false);
Harness.Compiler.getDefaultLibrarySourceFile()!.text, /*isRootFile*/ false);
}
}
@@ -393,7 +393,7 @@ namespace FourSlash {
(...args) => args.join("|,|")
);
proxy[key] = (...args: any[]) => memo(
target.languageServiceAdapterHost.getScriptInfo(target.activeFile.fileName).version,
target.languageServiceAdapterHost.getScriptInfo(target.activeFile.fileName)!.version,
target.activeFile.fileName,
target.currentCaretPosition,
target.selectionEnd,
@@ -406,7 +406,7 @@ namespace FourSlash {
}
private getFileContent(fileName: string): string {
const script = this.languageServiceAdapterHost.getScriptInfo(fileName);
const script = this.languageServiceAdapterHost.getScriptInfo(fileName)!;
return script.content;
}
@@ -548,9 +548,9 @@ namespace FourSlash {
}
}
private anyErrorInRange(predicate: (errorMinChar: number, errorLimChar: number, startPos: number, endPos: number) => boolean, startMarker: Marker, endMarker?: Marker): boolean {
private anyErrorInRange(predicate: (errorMinChar: number, errorLimChar: number, startPos: number, endPos: number | undefined) => boolean, startMarker: Marker, endMarker?: Marker): boolean {
return this.getDiagnostics(startMarker.fileName).some(({ start, length }) =>
predicate(start, start + length, startMarker.position, endMarker === undefined ? undefined : endMarker.position));
predicate(start!, start! + length!, startMarker.position, endMarker === undefined ? undefined : endMarker.position)); // TODO: GH#18217
}
private printErrorLog(expectErrors: boolean, errors: ts.Diagnostic[]) {
@@ -562,12 +562,12 @@ namespace FourSlash {
}
for (const { start, length, messageText, file } of errors) {
Harness.IO.log(" " + this.formatRange(file, start, length) +
Harness.IO.log(" " + this.formatRange(file, start!, length!) + // TODO: GH#18217
", message: " + ts.flattenDiagnosticMessageText(messageText, Harness.IO.newLine()) + "\n");
}
}
private formatRange(file: ts.SourceFile, start: number, length: number) {
private formatRange(file: ts.SourceFile | undefined, start: number, length: number) {
if (file) {
return `from: ${this.formatLineAndCharacterOfPosition(file, start)}, to: ${this.formatLineAndCharacterOfPosition(file, start + length)}`;
}
@@ -597,7 +597,7 @@ namespace FourSlash {
if (errors.length) {
this.printErrorLog(/*expectErrors*/ false, errors);
const error = errors[0];
this.raiseError(`Found an error: ${this.formatPosition(error.file, error.start)}: ${error.messageText}`);
this.raiseError(`Found an error: ${this.formatPosition(error.file!, error.start!)}: ${error.messageText}`);
}
});
}
@@ -635,11 +635,11 @@ namespace FourSlash {
}
private getGoToDefinition(): ts.DefinitionInfo[] {
return this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition);
return this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition)!;
}
private getGoToDefinitionAndBoundSpan(): ts.DefinitionInfoAndBoundSpan {
return this.languageService.getDefinitionAndBoundSpan(this.activeFile.fileName, this.currentCaretPosition);
return this.languageService.getDefinitionAndBoundSpan(this.activeFile.fileName, this.currentCaretPosition)!;
}
public verifyGoToType(arg0: any, endMarkerNames?: ArrayOrSingle<string>) {
@@ -694,9 +694,9 @@ namespace FourSlash {
testName = "goToDefinitions";
}
else {
this.verifyDefinitionTextSpan(defs, startMarkerName);
this.verifyDefinitionTextSpan(defs, startMarkerName!);
definitions = defs.definitions;
definitions = defs.definitions!; // TODO: GH#18217
testName = "goToDefinitionsAndBoundSpan";
}
@@ -713,7 +713,7 @@ namespace FourSlash {
}
private verifyDefinitionTextSpan(defs: ts.DefinitionInfoAndBoundSpan, startMarkerName: string) {
const range = this.testData.ranges.find(range => this.markerName(range.marker) === startMarkerName);
const range = this.testData.ranges.find(range => this.markerName(range.marker!) === startMarkerName);
if (!range && !defs.textSpan) {
return;
@@ -791,7 +791,7 @@ namespace FourSlash {
return;
}
const entries = this.getCompletionListAtCaret().entries;
const entries = this.getCompletionListAtCaret()!.entries;
assert.isTrue(items.length <= entries.length, `Amount of expected items in completion list [ ${items.length} ] is greater than actual number of items in list [ ${entries.length} ]`);
ts.zipWith(entries, items, (entry, item) => {
assert.equal(entry.name, item, `Unexpected item in completion list`);
@@ -799,7 +799,7 @@ namespace FourSlash {
}
public noItemsWithSameNameButDifferentKind(): void {
const completions = this.getCompletionListAtCaret();
const completions = this.getCompletionListAtCaret()!;
const uniqueItems = ts.createMap<string>();
for (const item of completions.entries) {
const uniqueItem = uniqueItems.get(item.name);
@@ -854,7 +854,7 @@ namespace FourSlash {
}
private verifyCompletionsWorker(options: FourSlashInterface.VerifyCompletionsOptions): void {
const actualCompletions = this.getCompletionListAtCaret({ ...options.preferences, triggerCharacter: options.triggerCharacter });
const actualCompletions = this.getCompletionListAtCaret({ ...options.preferences, triggerCharacter: options.triggerCharacter })!;
if (!actualCompletions) {
if (options.exact === undefined) return;
this.raiseError(`No completions at position '${this.currentCaretPosition}'.`);
@@ -877,7 +877,7 @@ namespace FourSlash {
if ("exact" in options) {
ts.Debug.assert(!("includes" in options) && !("excludes" in options));
if (options.exact === undefined) this.raiseError("Expected no completions");
if (options.exact === undefined) throw this.raiseError("Expected no completions");
this.verifyCompletionsAreExactly(actualCompletions.entries, toArray(options.exact));
}
else {
@@ -885,7 +885,7 @@ namespace FourSlash {
for (const include of toArray(options.includes)) {
const name = typeof include === "string" ? include : include.name;
const found = actualByName.get(name);
if (!found) this.raiseError(`No completion ${name} found`);
if (!found) throw this.raiseError(`No completion ${name} found`);
this.verifyCompletionEntry(found, include);
}
}
@@ -929,7 +929,7 @@ namespace FourSlash {
assert.equal(actual.isRecommended, isRecommended);
if (text) {
const actualDetails = this.getCompletionEntryDetails(actual.name, actual.source);
const actualDetails = this.getCompletionEntryDetails(actual.name, actual.source)!;
assert.equal(ts.displayPartsToString(actualDetails.displayParts), text);
assert.equal(ts.displayPartsToString(actualDetails.documentation), documentation || "");
// TODO: GH#23587
@@ -962,8 +962,7 @@ namespace FourSlash {
exact: expected,
isNewIdentifierLocation: options && options.isNewIdentifierLocation,
preferences: options,
// TODO: GH#20090
triggerCharacter: (options && options.triggerCharacter) as ts.CompletionsTriggerCharacter | undefined,
triggerCharacter: options && options.triggerCharacter,
});
}
@@ -989,7 +988,7 @@ namespace FourSlash {
* @param spanIndex the index of the range that the completion item's replacement text span should match
*/
public verifyCompletionListDoesNotContain(entryId: ts.Completions.CompletionEntryIdentifier, expectedText?: string, expectedDocumentation?: string, expectedKind?: string | { kind?: string, kindModifiers?: string }, spanIndex?: number, options?: FourSlashInterface.CompletionsAtOptions) {
let replacementSpan: ts.TextSpan;
let replacementSpan: ts.TextSpan | undefined;
if (spanIndex !== undefined) {
replacementSpan = this.getTextSpanForRangeAtIndex(spanIndex);
}
@@ -1022,7 +1021,7 @@ namespace FourSlash {
// then these symbols must meet the criterion for Not supposed to be in the list. So we
// raise an error
let error = `Completion list did contain '${JSON.stringify(entryId)}\'.`;
const details = this.getCompletionEntryDetails(filterCompletions[0].name);
const details = this.getCompletionEntryDetails(filterCompletions[0].name)!;
if (expectedText) {
error += "Expected text: " + expectedText + " to equal: " + ts.displayPartsToString(details.displayParts) + ".";
}
@@ -1045,7 +1044,7 @@ namespace FourSlash {
}
public verifyCompletionEntryDetails(entryName: string, expectedText: string, expectedDocumentation?: string, kind?: string, tags?: ts.JSDocTagInfo[]) {
const details = this.getCompletionEntryDetails(entryName);
const details = this.getCompletionEntryDetails(entryName)!;
assert(details, "no completion entry available");
@@ -1060,8 +1059,8 @@ namespace FourSlash {
}
if (tags !== undefined) {
assert.equal(details.tags.length, tags.length, this.messageAtLastKnownMarker("QuickInfo tags"));
ts.zipWith(tags, details.tags, (expectedTag, actualTag) => {
assert.equal(details.tags!.length, tags.length, this.messageAtLastKnownMarker("QuickInfo tags"));
ts.zipWith(tags, details.tags!, (expectedTag, actualTag) => {
assert.equal(actualTag.name, expectedTag.name);
assert.equal(actualTag.text, expectedTag.text, this.messageAtLastKnownMarker("QuickInfo tag " + actualTag.name));
});
@@ -1074,7 +1073,7 @@ namespace FourSlash {
private _checker: ts.TypeChecker;
private getProgram(): ts.Program {
return this._program || (this._program = this.languageService.getProgram());
return this._program || (this._program = this.languageService.getProgram()!); // TODO: GH#18217
}
private getChecker() {
@@ -1122,7 +1121,7 @@ namespace FourSlash {
public verifySymbolAtLocation(startRange: Range, declarationRanges: Range[]): void {
const node = this.goToAndGetNode(startRange);
const symbol = this.getChecker().getSymbolAtLocation(node);
const symbol = this.getChecker().getSymbolAtLocation(node)!;
if (!symbol) {
this.raiseError("Could not get symbol at location");
}
@@ -1153,14 +1152,14 @@ namespace FourSlash {
const startFile = this.activeFile.fileName;
for (const fileName of files) {
const searchFileNames = startFile === fileName ? [startFile] : [startFile, fileName];
const highlights = this.getDocumentHighlightsAtCurrentPosition(searchFileNames);
const highlights = this.getDocumentHighlightsAtCurrentPosition(searchFileNames)!;
if (!highlights.every(dh => ts.contains(searchFileNames, dh.fileName))) {
this.raiseError(`When asking for document highlights only in files ${searchFileNames}, got document highlights in ${unique(highlights, dh => dh.fileName)}`);
}
}
}
public verifyReferenceGroups(starts: ArrayOrSingle<string> | ArrayOrSingle<Range>, parts: ReadonlyArray<FourSlashInterface.ReferenceGroup> | undefined): void {
public verifyReferenceGroups(starts: ArrayOrSingle<string> | ArrayOrSingle<Range>, parts: ReadonlyArray<FourSlashInterface.ReferenceGroup>): void {
interface ReferenceGroupJson {
definition: string | { text: string, range: ts.TextSpan };
references: ts.ReferenceEntry[];
@@ -1220,7 +1219,7 @@ namespace FourSlash {
// Necessary to have this function since `findReferences` isn't implemented in `client.ts`
public verifyGetReferencesForServerTest(expected: ReadonlyArray<ts.ReferenceEntry>): void {
const refs = this.getReferencesAtCaret();
assert.deepEqual(refs, expected);
assert.deepEqual<ReadonlyArray<ts.ReferenceEntry> | undefined>(refs, expected);
}
public verifySingleReferenceGroup(definition: FourSlashInterface.ReferenceGroupDefinition, ranges?: Range[]) {
@@ -1274,7 +1273,7 @@ Actual: ${stringify(fullActual)}`);
}
public verifyDisplayPartsOfReferencedSymbol(expected: ts.SymbolDisplayPart[]) {
const referencedSymbols = this.findReferencesAtCaret();
const referencedSymbols = this.findReferencesAtCaret()!;
if (referencedSymbols.length === 0) {
this.raiseError("No referenced symbols found at current caret position");
@@ -1287,11 +1286,11 @@ Actual: ${stringify(fullActual)}`);
TestState.getDisplayPartsJson(expected), this.messageAtLastKnownMarker("referenced symbol definition display parts"));
}
private getCompletionListAtCaret(options?: ts.GetCompletionsAtPositionOptions): ts.CompletionInfo {
private getCompletionListAtCaret(options?: ts.GetCompletionsAtPositionOptions): ts.CompletionInfo | undefined {
return this.languageService.getCompletionsAtPosition(this.activeFile.fileName, this.currentCaretPosition, options);
}
private getCompletionEntryDetails(entryName: string, source?: string, preferences?: ts.UserPreferences): ts.CompletionEntryDetails {
private getCompletionEntryDetails(entryName: string, source?: string, preferences?: ts.UserPreferences): ts.CompletionEntryDetails | undefined {
return this.languageService.getCompletionEntryDetails(this.activeFile.fileName, this.currentCaretPosition, entryName, this.formatCodeSettings, source, preferences);
}
@@ -1366,14 +1365,14 @@ Actual: ${stringify(fullActual)}`);
tags: ts.JSDocTagInfo[]
) {
const actualQuickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition);
const actualQuickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition)!;
assert.equal(actualQuickInfo.kind, kind, this.messageAtLastKnownMarker("QuickInfo kind"));
assert.equal(actualQuickInfo.kindModifiers, kindModifiers, this.messageAtLastKnownMarker("QuickInfo kindModifiers"));
assert.equal(JSON.stringify(actualQuickInfo.textSpan), JSON.stringify(textSpan), this.messageAtLastKnownMarker("QuickInfo textSpan"));
assert.equal(TestState.getDisplayPartsJson(actualQuickInfo.displayParts), TestState.getDisplayPartsJson(displayParts), this.messageAtLastKnownMarker("QuickInfo displayParts"));
assert.equal(TestState.getDisplayPartsJson(actualQuickInfo.documentation), TestState.getDisplayPartsJson(documentation), this.messageAtLastKnownMarker("QuickInfo documentation"));
assert.equal(actualQuickInfo.tags.length, tags.length, this.messageAtLastKnownMarker("QuickInfo tags"));
ts.zipWith(tags, actualQuickInfo.tags, (expectedTag, actualTag) => {
assert.equal(actualQuickInfo.tags!.length, tags.length, this.messageAtLastKnownMarker("QuickInfo tags"));
ts.zipWith(tags, actualQuickInfo.tags!, (expectedTag, actualTag) => {
assert.equal(expectedTag.name, actualTag.name);
assert.equal(expectedTag.text, actualTag.text, this.messageAtLastKnownMarker("QuickInfo tag " + actualTag.name));
});
@@ -1481,10 +1480,10 @@ Actual: ${stringify(fullActual)}`);
}
private verifySignatureHelpWorker(options: FourSlashInterface.VerifySignatureHelpOptions) {
const help = this.getSignatureHelp();
const help = this.getSignatureHelp()!;
const selectedItem = help.items[help.selectedItemIndex];
// Argument index may exceed number of parameters
const currentParameter: ts.SignatureHelpParameter | undefined = selectedItem.parameters[help.argumentIndex];
const currentParameter = selectedItem.parameters[help.argumentIndex] as ts.SignatureHelpParameter | undefined;
assert.equal(help.items.length, options.overloadsCount || 1, this.assertionMessageAtLastKnownMarker("signature help overloads count"));
@@ -1539,7 +1538,7 @@ Actual: ${stringify(fullActual)}`);
}
}
private validate(name: string, expected: string, actual: string) {
private validate(name: string, expected: string | undefined, actual: string | undefined) {
if (expected && expected !== actual) {
this.raiseError("Expected " + name + " '" + expected + "'. Got '" + actual + "' instead.");
}
@@ -1601,19 +1600,19 @@ Actual: ${stringify(fullActual)}`);
let nextLine = 0;
let resultString = "";
let currentLine: string;
let previousSpanInfo: string;
let startColumn: number;
let length: number;
let previousSpanInfo: string | undefined;
let startColumn: number | undefined;
let length: number | undefined;
const prefixString = " >";
let pos = 0;
const addSpanInfoString = () => {
if (previousSpanInfo) {
resultString += currentLine;
let thisLineMarker = ts.repeatString(" ", startColumn) + ts.repeatString("~", length);
let thisLineMarker = ts.repeatString(" ", startColumn!) + ts.repeatString("~", length!);
thisLineMarker += ts.repeatString(" ", this.alignmentForExtraInfo - thisLineMarker.length - prefixString.length + 1);
resultString += thisLineMarker;
resultString += "=> Pos: (" + (pos - length) + " to " + (pos - 1) + ") ";
resultString += "=> Pos: (" + (pos - length!) + " to " + (pos - 1) + ") ";
resultString += " " + previousSpanInfo;
previousSpanInfo = undefined;
}
@@ -1634,12 +1633,12 @@ Actual: ${stringify(fullActual)}`);
if (previousSpanInfo && previousSpanInfo !== spanInfo) {
addSpanInfoString();
previousSpanInfo = spanInfo;
startColumn = startColumn + length;
startColumn = startColumn! + length!;
length = 1;
}
else {
previousSpanInfo = spanInfo;
length++;
length!++;
}
}
addSpanInfoString();
@@ -1660,7 +1659,7 @@ Actual: ${stringify(fullActual)}`);
Harness.Baseline.runBaseline(
baselineFile,
() => {
return this.baselineCurrentFileLocations(pos => this.getBreakpointStatementLocation(pos));
return this.baselineCurrentFileLocations(pos => this.getBreakpointStatementLocation(pos)!);
});
}
@@ -1693,10 +1692,10 @@ Actual: ${stringify(fullActual)}`);
if (emitOutput.emitSkipped) {
resultString += "Diagnostics:" + Harness.IO.newLine();
const diagnostics = ts.getPreEmitDiagnostics(this.languageService.getProgram());
const diagnostics = ts.getPreEmitDiagnostics(this.languageService.getProgram()!); // TODO: GH#18217
for (const diagnostic of diagnostics) {
if (!ts.isString(diagnostic.messageText)) {
let chainedMessage = diagnostic.messageText;
let chainedMessage: ts.DiagnosticMessageChain | undefined = diagnostic.messageText;
let indentation = " ";
while (chainedMessage) {
resultString += indentation + chainedMessage.messageText + Harness.IO.newLine();
@@ -1741,7 +1740,7 @@ Actual: ${stringify(fullActual)}`);
}
public printBreakpointLocation(pos: number) {
Harness.IO.log("\n**Pos: " + pos + " " + this.spanInfoToString(this.getBreakpointStatementLocation(pos), " "));
Harness.IO.log("\n**Pos: " + pos + " " + this.spanInfoToString(this.getBreakpointStatementLocation(pos)!, " "));
}
public printBreakpointAtCurrentLocation() {
@@ -1754,8 +1753,8 @@ Actual: ${stringify(fullActual)}`);
}
public printCurrentQuickInfo() {
const quickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition);
Harness.IO.log("Quick Info: " + quickInfo.displayParts.map(part => part.text).join(""));
const quickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition)!;
Harness.IO.log("Quick Info: " + quickInfo.displayParts!.map(part => part.text).join(""));
}
public printErrorList() {
@@ -1790,7 +1789,7 @@ Actual: ${stringify(fullActual)}`);
}
public printCurrentSignatureHelp() {
const help = this.getSignatureHelp();
const help = this.getSignatureHelp()!;
Harness.IO.log(stringify(help.items[help.selectedItemIndex]));
}
@@ -1803,7 +1802,7 @@ Actual: ${stringify(fullActual)}`);
this.printMembersOrCompletions(completions);
}
private printMembersOrCompletions(info: ts.CompletionInfo) {
private printMembersOrCompletions(info: ts.CompletionInfo | undefined) {
if (info === undefined) { return "No completion info."; }
const { entries } = info;
@@ -2087,7 +2086,7 @@ Actual: ${stringify(fullActual)}`);
}
public goToTypeDefinition(definitionIndex: number) {
const definitions = this.languageService.getTypeDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition);
const definitions = this.languageService.getTypeDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition)!;
if (!definitions || !definitions.length) {
this.raiseError("goToTypeDefinition failed - expected to find at least one definition location but got 0");
}
@@ -2130,7 +2129,7 @@ Actual: ${stringify(fullActual)}`);
}
public goToImplementation() {
const implementations = this.languageService.getImplementationAtPosition(this.activeFile.fileName, this.currentCaretPosition);
const implementations = this.languageService.getImplementationAtPosition(this.activeFile.fileName, this.currentCaretPosition)!;
if (!implementations || !implementations.length) {
this.raiseError("goToImplementation failed - expected to find at least one implementation location but got 0");
}
@@ -2145,7 +2144,7 @@ Actual: ${stringify(fullActual)}`);
public verifyRangesInImplementationList(markerName: string) {
this.goToMarker(markerName);
const implementations: ImplementationLocationInformation[] = this.languageService.getImplementationAtPosition(this.activeFile.fileName, this.currentCaretPosition);
const implementations: ImplementationLocationInformation[] = this.languageService.getImplementationAtPosition(this.activeFile.fileName, this.currentCaretPosition)!;
if (!implementations || !implementations.length) {
this.raiseError("verifyRangesInImplementationList failed - expected to find at least one implementation location but got 0");
}
@@ -2321,7 +2320,7 @@ Actual: ${stringify(fullActual)}`);
public verifyCurrentNameOrDottedNameSpanText(text: string) {
const span = this.languageService.getNameOrDottedNameSpan(this.activeFile.fileName, this.currentCaretPosition, this.currentCaretPosition);
if (!span) {
this.raiseError("verifyCurrentNameOrDottedNameSpanText\n" +
return this.raiseError("verifyCurrentNameOrDottedNameSpanText\n" +
"\tExpected: \"" + text + "\"\n" +
"\t Actual: undefined");
}
@@ -2343,12 +2342,12 @@ Actual: ${stringify(fullActual)}`);
this.testData.globalOptions[MetadataOptionNames.baselineFile],
() => {
return this.baselineCurrentFileLocations(pos =>
this.getNameOrDottedNameSpan(pos));
this.getNameOrDottedNameSpan(pos)!);
});
}
public printNameOrDottedNameSpans(pos: number) {
Harness.IO.log(this.spanInfoToString(this.getNameOrDottedNameSpan(pos), "**"));
Harness.IO.log(this.spanInfoToString(this.getNameOrDottedNameSpan(pos)!, "**"));
}
private verifyClassifications(expected: { classificationType: string; text: string; textSpan?: TextSpan }[], actual: ts.ClassifiedSpan[], sourceFileText: string) {
@@ -2407,7 +2406,7 @@ Actual: ${stringify(fullActual)}`);
);
assert.equal(
expected.join(","),
actual.fileNames.map(file => {
actual.fileNames!.map(file => {
return file.replace(this.basePath + "/", "");
}).join(",")
);
@@ -2482,18 +2481,19 @@ Actual: ${stringify(fullActual)}`);
public applyCodeActionFromCompletion(markerName: string, options: FourSlashInterface.VerifyCompletionActionOptions) {
this.goToMarker(markerName);
const details = this.getCompletionEntryDetails(options.name, options.source, options.preferences);
if (details.codeActions.length !== 1) {
this.raiseError(`Expected one code action, got ${details.codeActions.length}`);
const details = this.getCompletionEntryDetails(options.name, options.source, options.preferences)!;
const codeActions = details.codeActions!;
if (codeActions.length !== 1) {
this.raiseError(`Expected one code action, got ${codeActions.length}`);
}
if (details.codeActions[0].description !== options.description) {
this.raiseError(`Expected description to be:\n${options.description}\ngot:\n${details.codeActions[0].description}`);
if (codeActions[0].description !== options.description) {
this.raiseError(`Expected description to be:\n${options.description}\ngot:\n${codeActions[0].description}`);
}
this.applyCodeActions(details.codeActions);
this.applyCodeActions(codeActions);
this.verifyNewContent(options, ts.flatMap(details.codeActions, a => a.changes.map(c => c.fileName)));
this.verifyNewContent(options, ts.flatMap(codeActions, a => a.changes.map(c => c.fileName)));
}
public verifyRangeIs(expectedText: string, includeWhiteSpace?: boolean) {
@@ -2527,10 +2527,10 @@ Actual: ${stringify(fullActual)}`);
const fixWithId = ts.find(this.getCodeFixes(this.activeFile.fileName), a => a.fixId === fixId);
ts.Debug.assert(fixWithId !== undefined, "No available code fix has that group id.", () =>
`Expected '${fixId}'. Available action ids: ${ts.mapDefined(this.getCodeFixes(this.activeFile.fileName), a => a.fixId)}`);
ts.Debug.assertEqual(fixWithId.fixAllDescription, fixAllDescription);
ts.Debug.assertEqual(fixWithId!.fixAllDescription, fixAllDescription);
const { changes, commands } = this.languageService.getCombinedCodeFix({ type: "file", fileName: this.activeFile.fileName }, fixId, this.formatCodeSettings, ts.defaultPreferences);
assert.deepEqual(commands, expectedCommands);
assert.deepEqual<ReadonlyArray<{}> | undefined>(commands, expectedCommands);
assert(changes.every(c => c.fileName === this.activeFile.fileName), "TODO: support testing codefixes that touch multiple files");
this.applyChanges(changes);
this.verifyCurrentFileContent(newFileContent);
@@ -2601,7 +2601,7 @@ Actual: ${stringify(fullActual)}`);
}
}
else {
this.verifyRangeIs(options.newRangeContent, /*includeWhitespace*/ true);
this.verifyRangeIs(options.newRangeContent!, /*includeWhitespace*/ true);
}
}
@@ -2621,7 +2621,7 @@ Actual: ${stringify(fullActual)}`);
return;
}
return this.languageService.getCodeFixesAtPosition(fileName, diagnostic.start, diagnostic.start + diagnostic.length, [diagnostic.code], this.formatCodeSettings, preferences);
return this.languageService.getCodeFixesAtPosition(fileName, diagnostic.start!, diagnostic.start! + diagnostic.length!, [diagnostic.code], this.formatCodeSettings, preferences);
});
}
@@ -2665,7 +2665,7 @@ Actual: ${stringify(fullActual)}`);
}
const actualTextArray: string[] = [];
const scriptInfo = this.languageServiceAdapterHost.getScriptInfo(fileName);
const scriptInfo = this.languageServiceAdapterHost.getScriptInfo(fileName)!;
const originalContent = scriptInfo.content;
for (const codeFix of codeFixes) {
ts.Debug.assert(codeFix.changes.length === 1);
@@ -2688,7 +2688,7 @@ Actual: ${stringify(fullActual)}`);
public verifyDocCommentTemplate(expected: ts.TextInsertion | undefined) {
const name = "verifyDocCommentTemplate";
const actual = this.languageService.getDocCommentTemplateAtPosition(this.activeFile.fileName, this.currentCaretPosition);
const actual = this.languageService.getDocCommentTemplateAtPosition(this.activeFile.fileName, this.currentCaretPosition)!;
if (expected === undefined) {
if (actual) {
@@ -2727,7 +2727,7 @@ Actual: ${stringify(fullActual)}`);
const charCode = openBraceMap.get(openingBrace);
if (!charCode) {
this.raiseError(`Invalid openingBrace '${openingBrace}' specified.`);
throw this.raiseError(`Invalid openingBrace '${openingBrace}' specified.`);
}
const position = this.currentCaretPosition;
@@ -2899,7 +2899,7 @@ Actual: ${stringify(fullActual)}`);
const occurrences = this.getOccurrencesAtCurrentPosition();
if (!occurrences || occurrences.length === 0) {
this.raiseError("verifyOccurrencesAtPositionListContains failed - found 0 references, expected at least one.");
return this.raiseError("verifyOccurrencesAtPositionListContains failed - found 0 references, expected at least one.");
}
for (const occurrence of occurrences) {
@@ -3091,13 +3091,13 @@ Actual: ${stringify(fullActual)}`);
const action = ts.firstDefined(refactorsWithName, refactor => refactor.actions.find(a => a.name === actionName));
if (!action) {
this.raiseError(`The expected action: ${actionName} is not included in: ${ts.flatMap(refactorsWithName, r => r.actions.map(a => a.name))}`);
throw this.raiseError(`The expected action: ${actionName} is not included in: ${ts.flatMap(refactorsWithName, r => r.actions.map(a => a.name))}`);
}
if (action.description !== actionDescription) {
this.raiseError(`Expected action description to be ${JSON.stringify(actionDescription)}, got: ${JSON.stringify(action.description)}`);
}
const editInfo = this.languageService.getEditsForRefactor(this.activeFile.fileName, this.formatCodeSettings, range, refactorName, actionName, ts.defaultPreferences);
const editInfo = this.languageService.getEditsForRefactor(this.activeFile.fileName, this.formatCodeSettings, range, refactorName, actionName, ts.defaultPreferences)!;
for (const edit of editInfo.edits) {
this.applyEdits(edit.fileName, edit.textChanges, /*isFormattingEdit*/ false);
}
@@ -3144,12 +3144,12 @@ Actual: ${stringify(fullActual)}`);
public moveToNewFile(options: FourSlashInterface.MoveToNewFileOptions): void {
assert(this.getRanges().length === 1);
const range = this.getRanges()[0];
const refactor = ts.find(this.getApplicableRefactors(range, { allowTextChangesInNewFiles: true }), r => r.name === "Move to a new file");
const refactor = ts.find(this.getApplicableRefactors(range, { allowTextChangesInNewFiles: true }), r => r.name === "Move to a new file")!;
assert(refactor.actions.length === 1);
const action = ts.first(refactor.actions);
assert(action.name === "Move to a new file" && action.description === "Move to a new file");
const editInfo = this.languageService.getEditsForRefactor(this.activeFile.fileName, this.formatCodeSettings, range, refactor.name, action.name, ts.defaultPreferences);
const editInfo = this.languageService.getEditsForRefactor(this.activeFile.fileName, this.formatCodeSettings, range, refactor.name, action.name, ts.defaultPreferences)!;
for (const edit of editInfo.edits) {
const newContent = options.newFileContents[edit.fileName];
if (newContent === undefined) {
@@ -3190,7 +3190,7 @@ Actual: ${stringify(fullActual)}`);
this.raiseError(`The expected refactor: ${refactorNameToApply} is not available at the marker location.`);
}
const editInfo = this.languageService.getEditsForRefactor(this.activeFile.fileName, formattingOptions, markerPos, refactorNameToApply, actionName, ts.defaultPreferences);
const editInfo = this.languageService.getEditsForRefactor(this.activeFile.fileName, formattingOptions, markerPos, refactorNameToApply, actionName, ts.defaultPreferences)!;
for (const edit of editInfo.edits) {
this.applyEdits(edit.fileName, edit.textChanges, /*isFormattingEdit*/ false);
@@ -3260,7 +3260,7 @@ Actual: ${stringify(fullActual)}`);
const item = matchingItems[0];
if (documentation !== undefined || text !== undefined || entryId.source !== undefined) {
const details = this.getCompletionEntryDetails(item.name, item.source);
const details = this.getCompletionEntryDetails(item.name, item.source)!;
if (documentation !== undefined) {
eq(ts.displayPartsToString(details.documentation), documentation, "completion item documentation");
@@ -3348,11 +3348,11 @@ Actual: ${stringify(fullActual)}`);
private getTextSpanForRangeAtIndex(index: number): ts.TextSpan {
const ranges = this.getRanges();
if (ranges && ranges.length > index) {
if (ranges.length > index) {
return ts.createTextSpanFromRange(ranges[index]);
}
else {
this.raiseError("Supplied span index: " + index + " does not exist in range list of size: " + (ranges ? 0 : ranges.length));
throw this.raiseError("Supplied span index: " + index + " does not exist in range list of size: " + ranges.length);
}
}
@@ -3374,8 +3374,8 @@ Actual: ${stringify(fullActual)}`);
this.cancellationToken.resetCancelled();
}
private static textSpansEqual(a: ts.TextSpan, b: ts.TextSpan) {
return a && b && a.start === b.start && a.length === b.length;
private static textSpansEqual(a: ts.TextSpan | undefined, b: ts.TextSpan | undefined): boolean {
return !!a && !!b && a.start === b.start && a.length === b.length;
}
public getEditsForFileRename(options: FourSlashInterface.GetEditsForFileRenameOptions): void {
@@ -3393,7 +3393,7 @@ Actual: ${stringify(fullActual)}`);
}
export function runFourSlashTest(basePath: string, testType: FourSlashTestType, fileName: string) {
const content = Harness.IO.readFile(fileName);
const content = Harness.IO.readFile(fileName)!;
runFourSlashTestContent(basePath, testType, content, fileName);
}
@@ -3406,8 +3406,8 @@ Actual: ${stringify(fullActual)}`);
const testData = parseTestData(absoluteBasePath, content, absoluteFileName);
const state = new TestState(absoluteBasePath, testType, testData);
const output = ts.transpileModule(content, { reportDiagnostics: true });
if (output.diagnostics.length > 0) {
throw new Error(`Syntax error in ${absoluteBasePath}: ${output.diagnostics[0].messageText}`);
if (output.diagnostics!.length > 0) {
throw new Error(`Syntax error in ${absoluteBasePath}: ${output.diagnostics![0].messageText}`);
}
runCode(output.outputText, state);
}
@@ -3558,11 +3558,11 @@ ${code}
return Harness.getConfigNameFromFileName(file.fileName) !== undefined;
}
function getNonFileNameOptionInFileList(files: FourSlashFile[]): string {
function getNonFileNameOptionInFileList(files: FourSlashFile[]): string | undefined {
return ts.forEach(files, f => getNonFileNameOptionInObject(f.fileOptions));
}
function getNonFileNameOptionInObject(optionObject: { [s: string]: string }): string {
function getNonFileNameOptionInObject(optionObject: { [s: string]: string }): string | undefined {
for (const option in optionObject) {
if (option !== MetadataOptionNames.fileName) {
return option;
@@ -3582,7 +3582,7 @@ ${code}
throw new Error(errorMessage);
}
function recordObjectMarker(fileName: string, location: LocationInformation, text: string, markerMap: ts.Map<Marker>, markers: Marker[]): Marker {
function recordObjectMarker(fileName: string, location: LocationInformation, text: string, markerMap: ts.Map<Marker>, markers: Marker[]): Marker | undefined {
let markerValue: any;
try {
// Attempt to parse the marker value as JSON
@@ -3613,7 +3613,7 @@ ${code}
return marker;
}
function recordMarker(fileName: string, location: LocationInformation, name: string, markerMap: ts.Map<Marker>, markers: Marker[]): Marker {
function recordMarker(fileName: string, location: LocationInformation, name: string, markerMap: ts.Map<Marker>, markers: Marker[]): Marker | undefined {
const marker: Marker = {
fileName,
position: location.position
@@ -3642,7 +3642,7 @@ ${code}
let output = "";
/// The current marker (or maybe multi-line comment?) we're parsing, possibly
let openMarker: LocationInformation;
let openMarker: LocationInformation | undefined;
/// A stack of the open range markers that are still unclosed
const openRanges: RangeLocationInformation[] = [];
@@ -3663,7 +3663,7 @@ ${code}
let line = 1;
let column = 1;
const flush = (lastSafeCharIndex: number) => {
const flush = (lastSafeCharIndex: number | undefined) => {
output = output + content.substr(lastNormalCharPosition, lastSafeCharIndex === undefined ? undefined : lastSafeCharIndex - lastNormalCharPosition);
};
@@ -3690,7 +3690,7 @@ ${code}
// found a range end
const rangeStart = openRanges.pop();
if (!rangeStart) {
reportError(fileName, line, column, "Found range end with no matching start.");
throw reportError(fileName, line, column, "Found range end with no matching start.");
}
const range: Range = {
@@ -3733,8 +3733,8 @@ ${code}
// Object markers are only ever terminated by |} and have no content restrictions
if (previousChar === "|" && currentChar === "}") {
// Record the marker
const objectMarkerNameText = content.substring(openMarker.sourcePosition + 2, i - 1).trim();
const marker = recordObjectMarker(fileName, openMarker, objectMarkerNameText, markerMap, markers);
const objectMarkerNameText = content.substring(openMarker!.sourcePosition + 2, i - 1).trim();
const marker = recordObjectMarker(fileName, openMarker!, objectMarkerNameText, markerMap, markers);
if (openRanges.length > 0) {
openRanges[openRanges.length - 1].marker = marker;
@@ -3742,7 +3742,7 @@ ${code}
// Set the current start to point to the end of the current marker to ignore its text
lastNormalCharPosition = i + 1;
difference += i + 1 - openMarker.sourcePosition;
difference += i + 1 - openMarker!.sourcePosition;
// Reset the state
openMarker = undefined;
@@ -3754,17 +3754,17 @@ ${code}
if (previousChar === "*" && currentChar === "/") {
// Record the marker
// start + 2 to ignore the */, -1 on the end to ignore the * (/ is next)
const markerNameText = content.substring(openMarker.sourcePosition + 2, i - 1).trim();
const marker = recordMarker(fileName, openMarker, markerNameText, markerMap, markers);
const markerNameText = content.substring(openMarker!.sourcePosition + 2, i - 1).trim();
const marker = recordMarker(fileName, openMarker!, markerNameText, markerMap, markers);
if (openRanges.length > 0) {
openRanges[openRanges.length - 1].marker = marker;
}
// Set the current start to point to the end of the current marker to ignore its text
flush(openMarker.sourcePosition);
flush(openMarker!.sourcePosition);
lastNormalCharPosition = i + 1;
difference += i + 1 - openMarker.sourcePosition;
difference += i + 1 - openMarker!.sourcePosition;
// Reset the state
openMarker = undefined;
@@ -3865,7 +3865,7 @@ ${code}
return s.replace(/\s/g, "");
}
function findDuplicatedElement<T>(a: ReadonlyArray<T>, equal: (a: T, b: T) => boolean): T {
function findDuplicatedElement<T>(a: ReadonlyArray<T>, equal: (a: T, b: T) => boolean): T | undefined {
for (let i = 0; i < a.length; i++) {
for (let j = i + 1; j < a.length; j++) {
if (equal(a[i], a[j])) {
@@ -3889,7 +3889,7 @@ namespace FourSlashInterface {
return this.state.getMarkerNames();
}
public marker(name?: string): FourSlash.Marker {
public marker(name: string): FourSlash.Marker {
return this.state.getMarkerByName(name);
}
@@ -3936,7 +3936,7 @@ namespace FourSlashInterface {
public eachMarker(action: (marker: FourSlash.Marker, index: number) => void): void;
public eachMarker(a: ReadonlyArray<string> | ((marker: FourSlash.Marker, index: number) => void), b?: (marker: FourSlash.Marker, index: number) => void): void {
const markers = typeof a === "function" ? this.state.getMarkers() : a.map(m => this.state.getMarkerByName(m));
this.state.goToEachMarker(markers, typeof a === "function" ? a : b);
this.state.goToEachMarker(markers, typeof a === "function" ? a : b!);
}
@@ -4146,7 +4146,7 @@ namespace FourSlashInterface {
this.state.verifyQuickInfoString(expectedText, expectedDocumentation);
}
public quickInfoAt(markerName: string, expectedText?: string, expectedDocumentation?: string) {
public quickInfoAt(markerName: string, expectedText: string, expectedDocumentation?: string) {
this.state.verifyQuickInfoAt(markerName, expectedText, expectedDocumentation);
}
@@ -4765,7 +4765,7 @@ namespace FourSlashInterface {
readonly exact?: ArrayOrSingle<ExpectedCompletionEntry>;
readonly includes?: ArrayOrSingle<ExpectedCompletionEntry>;
readonly excludes?: ArrayOrSingle<string | { readonly name: string, readonly source: string }>;
readonly preferences: ts.UserPreferences;
readonly preferences?: ts.UserPreferences;
readonly triggerCharacter?: ts.CompletionsTriggerCharacter;
}
+53 -54
View File
@@ -148,7 +148,7 @@ namespace Utils {
path = "tests/" + path;
}
let content: string;
let content: string | undefined;
try {
content = Harness.IO.readFile(Harness.userSpecifiedRoot + path);
}
@@ -177,7 +177,7 @@ namespace Utils {
export const canonicalizeForHarness = ts.createGetCanonicalFileName(/*caseSensitive*/ false); // This is done so tests work on windows _and_ linux
export function assertInvariants(node: ts.Node, parent: ts.Node): void {
export function assertInvariants(node: ts.Node | undefined, parent: ts.Node | undefined): void {
if (node) {
assert.isFalse(node.pos < 0, "node.pos < 0");
assert.isFalse(node.end < 0, "node.end < 0");
@@ -504,11 +504,11 @@ namespace Harness {
newLine(): string;
getCurrentDirectory(): string;
useCaseSensitiveFileNames(): boolean;
resolvePath(path: string): string;
resolvePath(path: string): string | undefined;
getFileSize(path: string): number;
readFile(path: string): string | undefined;
writeFile(path: string, contents: string): void;
directoryName(path: string): string;
directoryName(path: string): string | undefined;
getDirectories(path: string): string[];
createDirectory(path: string): void;
fileExists(fileName: string): boolean;
@@ -525,7 +525,7 @@ namespace Harness {
getAccessibleFileSystemEntries(dirname: string): ts.FileSystemEntries;
tryEnableSourceMapsForHost?(): void;
getEnvironmentVariable?(name: string): string;
getMemoryUsage?(): number;
getMemoryUsage?(): number | undefined;
}
export let IO: IO;
@@ -564,9 +564,7 @@ namespace Harness {
return runner.enumerateTestFiles();
}
function listFiles(path: string, spec: RegExp, options?: { recursive?: boolean }) {
options = options || {};
function listFiles(path: string, spec: RegExp, options: { recursive?: boolean } = {}) {
function filesInFolder(folder: string): string[] {
let paths: string[] = [];
@@ -634,7 +632,7 @@ namespace Harness {
getCurrentDirectory: () => ts.sys.getCurrentDirectory(),
useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames,
resolvePath: (path: string) => ts.sys.resolvePath(path),
getFileSize: (path: string) => ts.sys.getFileSize(path),
getFileSize: (path: string) => ts.sys.getFileSize!(path),
readFile: path => ts.sys.readFile(path),
writeFile: (path, content) => ts.sys.writeFile(path, content),
directoryName,
@@ -692,7 +690,7 @@ namespace Harness {
}
}
public static combine(left: HttpHeaders | undefined, right: HttpHeaders | undefined): HttpHeaders {
public static combine(left: HttpHeaders | undefined, right: HttpHeaders | undefined): HttpHeaders | undefined {
if (!left && !right) return undefined;
const headers = new HttpHeaders();
if (left) left.forEach((value, key) => { headers.set(key, value); });
@@ -768,8 +766,8 @@ namespace Harness {
public static readResponseContent(xhr: XMLHttpRequest) {
if (typeof xhr.responseText === "string") {
return new HttpContent({
"Content-Type": xhr.getResponseHeader("Content-Type") || undefined,
"Content-Length": xhr.getResponseHeader("Content-Length") || undefined
"Content-Type": xhr.getResponseHeader("Content-Type") || undefined!, // TODO: GH#18217
"Content-Length": xhr.getResponseHeader("Content-Length") || undefined!, // TODO: GH#18217
}, xhr.responseText);
}
return undefined;
@@ -888,7 +886,7 @@ namespace Harness {
function getFileSize(path: string): number {
const response = send(HttpRequestMessage.head(new URL(path, serverRoot)));
return HttpResponseMessage.hasSuccessStatusCode(response) ? +response.headers.get("Content-Length").toString() : 0;
return HttpResponseMessage.hasSuccessStatusCode(response) ? +response.headers.get("Content-Length")!.toString() : 0;
}
function readFile(path: string): string | undefined {
@@ -998,7 +996,7 @@ namespace Harness {
}
}
if (Harness.IO.tryEnableSourceMapsForHost && /^development$/i.test(Harness.IO.getEnvironmentVariable("NODE_ENV"))) {
if (Harness.IO.tryEnableSourceMapsForHost && /^development$/i.test(Harness.IO.getEnvironmentVariable!("NODE_ENV"))) {
Harness.IO.tryEnableSourceMapsForHost();
}
@@ -1030,7 +1028,7 @@ namespace Harness {
*/
export class WriterAggregator {
public lines: string[] = [];
public currentLine = <string>undefined;
public currentLine: string = undefined!;
public Write(str: string) {
// out of memory usage concerns avoid using + or += if we're going to do any manipulation of this string later
@@ -1040,17 +1038,17 @@ namespace Harness {
public WriteLine(str: string) {
// out of memory usage concerns avoid using + or += if we're going to do any manipulation of this string later
this.lines.push([(this.currentLine || ""), str].join(""));
this.currentLine = undefined;
this.currentLine = undefined!;
}
public Close() {
if (this.currentLine !== undefined) { this.lines.push(this.currentLine); }
this.currentLine = undefined;
this.currentLine = undefined!;
}
public reset() {
this.lines = [];
this.currentLine = undefined;
this.currentLine = undefined!;
}
}
@@ -1077,20 +1075,20 @@ namespace Harness {
// Cache of lib files from "built/local"
let libFileNameSourceFileMap: ts.Map<ts.SourceFile> | undefined;
export function getDefaultLibrarySourceFile(fileName = defaultLibFileName): ts.SourceFile {
export function getDefaultLibrarySourceFile(fileName = defaultLibFileName): ts.SourceFile | undefined {
if (!isDefaultLibraryFile(fileName)) {
return undefined;
}
if (!libFileNameSourceFileMap) {
libFileNameSourceFileMap = ts.createMapFromTemplate({
[defaultLibFileName]: createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + "lib.es5.d.ts"), /*languageVersion*/ ts.ScriptTarget.Latest)
[defaultLibFileName]: createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + "lib.es5.d.ts")!, /*languageVersion*/ ts.ScriptTarget.Latest)
});
}
let sourceFile = libFileNameSourceFileMap.get(fileName);
if (!sourceFile) {
libFileNameSourceFileMap.set(fileName, sourceFile = createSourceFileAndAssertInvariants(fileName, IO.readFile(libFolder + fileName), ts.ScriptTarget.Latest));
libFileNameSourceFileMap.set(fileName, sourceFile = createSourceFileAndAssertInvariants(fileName, IO.readFile(libFolder + fileName)!, ts.ScriptTarget.Latest));
}
return sourceFile;
}
@@ -1206,10 +1204,10 @@ namespace Harness {
export function compileFiles(
inputFiles: TestFile[],
otherFiles: TestFile[],
harnessSettings: TestCaseParser.CompilerSettings,
compilerOptions: ts.CompilerOptions,
harnessSettings: TestCaseParser.CompilerSettings | undefined,
compilerOptions: ts.CompilerOptions | undefined,
// Current directory is needed for rwcRunner to be able to use currentDirectory defined in json file
currentDirectory: string): compiler.CompilationResult {
currentDirectory: string | undefined): compiler.CompilationResult {
const options: ts.CompilerOptions & HarnessOptions = compilerOptions ? ts.cloneCompilerOptions(compilerOptions) : { noResolve: false };
options.target = options.target || ts.ScriptTarget.ES3;
options.newLine = options.newLine || ts.NewLineKind.CarriageReturnLineFeed;
@@ -1225,7 +1223,7 @@ namespace Harness {
setCompilerOptionsFromHarnessSetting(harnessSettings, options);
}
if (options.rootDirs) {
options.rootDirs = ts.map(options.rootDirs, d => ts.getNormalizedAbsolutePath(d, currentDirectory));
options.rootDirs = ts.map(options.rootDirs, d => ts.getNormalizedAbsolutePath(d, currentDirectory!));
}
const useCaseSensitiveFileNames = options.useCaseSensitiveFileNames !== undefined ? options.useCaseSensitiveFileNames : true;
@@ -1253,7 +1251,7 @@ namespace Harness {
export interface DeclarationCompilationContext {
declInputFiles: TestFile[];
declOtherFiles: TestFile[];
harnessSettings: TestCaseParser.CompilerSettings & HarnessOptions;
harnessSettings: TestCaseParser.CompilerSettings & HarnessOptions | undefined;
options: ts.CompilerOptions;
currentDirectory: string;
}
@@ -1264,7 +1262,7 @@ namespace Harness {
harnessSettings: TestCaseParser.CompilerSettings & HarnessOptions,
options: ts.CompilerOptions,
// Current directory is needed for rwcRunner to be able to use currentDirectory defined in json file
currentDirectory: string): DeclarationCompilationContext | undefined {
currentDirectory: string | undefined): DeclarationCompilationContext | undefined {
if (options.declaration && result.diagnostics.length === 0) {
if (options.emitDeclarationOnly) {
@@ -1300,7 +1298,7 @@ namespace Harness {
}
function findResultCodeFile(fileName: string) {
const sourceFile = result.program.getSourceFile(fileName);
const sourceFile = result.program!.getSourceFile(fileName)!;
assert(sourceFile, "Program has no source file with name '" + fileName + "'");
// Is this file going to be emitted separately
let sourceFileName: string;
@@ -1308,7 +1306,7 @@ namespace Harness {
if (!outFile) {
if (options.outDir) {
let sourceFilePath = ts.getNormalizedAbsolutePath(sourceFile.fileName, result.vfs.cwd());
sourceFilePath = sourceFilePath.replace(result.program.getCommonSourceDirectory(), "");
sourceFilePath = sourceFilePath.replace(result.program!.getCommonSourceDirectory(), "");
sourceFileName = ts.combinePaths(options.outDir, sourceFilePath);
}
else {
@@ -1408,7 +1406,7 @@ namespace Harness {
// Filter down to the errors in the file
const fileErrors = diagnostics.filter((e): e is ts.DiagnosticWithLocation => {
const errFn = e.file;
return errFn && utils.removeTestPathPrefixes(errFn.fileName) === utils.removeTestPathPrefixes(inputFile.unitName);
return !!errFn && utils.removeTestPathPrefixes(errFn.fileName) === utils.removeTestPathPrefixes(inputFile.unitName);
});
@@ -1443,7 +1441,8 @@ namespace Harness {
}
// Emit this line from the original file
outputLines += (newLine() + " " + line);
fileErrors.forEach(err => {
fileErrors.forEach(errDiagnostic => {
const err = errDiagnostic as ts.TextSpan; // TODO: GH#18217
// Does any error start or continue on to this line? Emit squiggles
const end = ts.textSpanEnd(err);
if ((end >= thisLineStart) && ((err.start < nextLineStart) || (lineIndex === lines.length - 1))) {
@@ -1461,7 +1460,7 @@ namespace Harness {
// Just like above, we need to do a split on a string instead of on a regex
// because the JS engine does regexes wrong
outputErrorText(err);
outputErrorText(errDiagnostic);
markedErrorCount++;
}
}
@@ -1476,12 +1475,12 @@ namespace Harness {
}
const numLibraryDiagnostics = ts.countWhere(diagnostics, diagnostic => {
return diagnostic.file && (isDefaultLibraryFile(diagnostic.file.fileName) || isBuiltFile(diagnostic.file.fileName));
return !!diagnostic.file && (isDefaultLibraryFile(diagnostic.file.fileName) || isBuiltFile(diagnostic.file.fileName));
});
const numTest262HarnessDiagnostics = ts.countWhere(diagnostics, diagnostic => {
// Count an error generated from tests262-harness folder.This should only apply for test262
return diagnostic.file && diagnostic.file.fileName.indexOf("test262-harness") >= 0;
return !!diagnostic.file && diagnostic.file.fileName.indexOf("test262-harness") >= 0;
});
// Verify we didn't miss any errors in total
@@ -1489,7 +1488,7 @@ namespace Harness {
}
export function doErrorBaseline(baselinePath: string, inputFiles: ReadonlyArray<TestFile>, errors: ReadonlyArray<ts.Diagnostic>, pretty?: boolean) {
Baseline.runBaseline(baselinePath.replace(/\.tsx?$/, ".errors.txt"), (): string => {
Baseline.runBaseline(baselinePath.replace(/\.tsx?$/, ".errors.txt"), (): string | null => {
if (!errors || (errors.length === 0)) {
/* tslint:disable:no-null-keyword */
return null;
@@ -1519,7 +1518,7 @@ namespace Harness {
// Produce baselines. The first gives the types for all expressions.
// The second gives symbols for all identifiers.
let typesError: Error, symbolsError: Error;
let typesError: Error | undefined, symbolsError: Error | undefined;
try {
checkBaseLines(/*isSymbolBaseLine*/ false);
}
@@ -1567,7 +1566,7 @@ namespace Harness {
}
}
function generateBaseLine(isSymbolBaseline: boolean, skipBaseline?: boolean): string {
function generateBaseLine(isSymbolBaseline: boolean, skipBaseline?: boolean): string | null {
let result = "";
const gen = iterateBaseLine(isSymbolBaseline, skipBaseline);
for (let {done, value} = gen.next(); !done; { done, value } = gen.next()) {
@@ -1754,7 +1753,7 @@ namespace Harness {
resultName = sanitizeTestFilePath(resultName);
if (dupeCase.has(resultName)) {
// A different baseline filename should be manufactured if the names differ only in case, for windows compat
const count = 1 + dupeCase.get(resultName);
const count = 1 + dupeCase.get(resultName)!;
dupeCase.set(resultName, count);
resultName = `${resultName}.dupe${count}`;
}
@@ -1862,7 +1861,7 @@ namespace Harness {
export function extractCompilerSettings(content: string): CompilerSettings {
const opts: CompilerSettings = {};
let match: RegExpExecArray;
let match: RegExpExecArray | null;
/* tslint:disable:no-null-keyword */
while ((match = optionRegex.exec(content)) !== null) {
/* tslint:enable:no-null-keyword */
@@ -1875,8 +1874,8 @@ namespace Harness {
export interface TestCaseContent {
settings: CompilerSettings;
testUnitData: TestUnitData[];
tsConfig: ts.ParsedCommandLine;
tsConfigFileUnitData: TestUnitData;
tsConfig: ts.ParsedCommandLine | undefined;
tsConfigFileUnitData: TestUnitData | undefined;
}
/** Given a test file containing // @FileName directives, return an array of named units of code to be added to an existing compiler instance */
@@ -1887,7 +1886,7 @@ namespace Harness {
const lines = Utils.splitContentByNewlines(code);
// Stuff related to the subfile we're parsing
let currentFileContent: string;
let currentFileContent: string | undefined;
let currentFileOptions: any = {};
let currentFileName: any;
let refs: string[] = [];
@@ -1907,7 +1906,7 @@ namespace Harness {
if (currentFileName) {
// Store result file
const newTestFile = {
content: currentFileContent,
content: currentFileContent!, // TODO: GH#18217
name: currentFileName,
fileOptions: currentFileOptions,
originalFilePath: fileName,
@@ -1962,8 +1961,8 @@ namespace Harness {
};
// check if project has tsconfig.json in the list of files
let tsConfig: ts.ParsedCommandLine;
let tsConfigFileUnitData: TestUnitData;
let tsConfig: ts.ParsedCommandLine | undefined;
let tsConfigFileUnitData: TestUnitData | undefined;
for (let i = 0; i < testUnitData.length; i++) {
const data = testUnitData[i];
if (getConfigNameFromFileName(data.name)) {
@@ -2024,7 +2023,7 @@ namespace Harness {
}
const fileCache: { [idx: string]: boolean } = {};
function generateActual(generateContent: () => string): string {
function generateActual(generateContent: () => string | null): string | null {
const actual = generateContent();
@@ -2035,12 +2034,12 @@ namespace Harness {
return actual;
}
function compareToBaseline(actual: string, relativeFileName: string, opts: BaselineOptions) {
function compareToBaseline(actual: string | null, relativeFileName: string, opts: BaselineOptions | undefined) {
// actual is now either undefined (the generator had an error), null (no file requested),
// or some real output of the function
if (actual === undefined) {
// Nothing to do
return;
return undefined!; // TODO: GH#18217
}
const refFileName = referencePath(relativeFileName, opts && opts.Baselinefolder, opts && opts.Subfolder);
@@ -2053,7 +2052,7 @@ namespace Harness {
let expected = "<no content>";
if (IO.fileExists(refFileName)) {
expected = IO.readFile(refFileName);
expected = IO.readFile(refFileName)!; // TODO: GH#18217
}
return { expected, actual };
@@ -2069,7 +2068,7 @@ namespace Harness {
return;
}
const parentDirectory = IO.directoryName(dirName);
const parentDirectory = IO.directoryName(dirName)!; // TODO: GH#18217
if (parentDirectory !== "" && parentDirectory !== dirName) {
createDirectoryStructure(parentDirectory);
}
@@ -2078,7 +2077,7 @@ namespace Harness {
}
// Create folders if needed
createDirectoryStructure(IO.directoryName(actualFileName));
createDirectoryStructure(IO.directoryName(actualFileName)!); // TODO: GH#18217
// Delete the actual file in case it fails
if (IO.fileExists(actualFileName)) {
@@ -2097,14 +2096,14 @@ namespace Harness {
}
}
export function runBaseline(relativeFileName: string, generateContent: () => string, opts?: BaselineOptions): void {
export function runBaseline(relativeFileName: string, generateContent: () => string | null, opts?: BaselineOptions): void {
const actualFileName = localPath(relativeFileName, opts && opts.Baselinefolder, opts && opts.Subfolder);
const actual = generateActual(generateContent);
const comparison = compareToBaseline(actual, relativeFileName, opts);
writeComparison(comparison.expected, comparison.actual, relativeFileName, actualFileName);
}
export function runMultifileBaseline(relativeFileBase: string, extension: string, generateContent: () => IterableIterator<[string, string, number]> | IterableIterator<[string, string]>, opts?: BaselineOptions, referencedExtensions?: string[]): void {
export function runMultifileBaseline(relativeFileBase: string, extension: string, generateContent: () => IterableIterator<[string, string, number]> | IterableIterator<[string, string]> | null, opts?: BaselineOptions, referencedExtensions?: string[]): void {
const gen = generateContent();
const writtenFiles = ts.createMap<true>();
const errors: Error[] = [];
@@ -2175,7 +2174,7 @@ namespace Harness {
export function getDefaultLibraryFile(filePath: string, io: IO): Compiler.TestFile {
const libFile = userSpecifiedRoot + libFolder + ts.getBaseFileName(ts.normalizeSlashes(filePath));
return { unitName: libFile, content: io.readFile(libFile) };
return { unitName: libFile, content: io.readFile(libFile)! };
}
export function getConfigNameFromFileName(filename: string): "tsconfig.json" | "jsconfig.json" | undefined {
+16 -17
View File
@@ -7,7 +7,7 @@ namespace Harness.LanguageService {
export class ScriptInfo {
public version = 1;
public editRanges: { length: number; textChangeRange: ts.TextChangeRange; }[] = [];
private lineMap: number[] = undefined;
private lineMap: number[] | undefined;
constructor(public fileName: string, public content: string, public isRootFile: boolean) {
this.setContent(content);
@@ -95,7 +95,7 @@ namespace Harness.LanguageService {
return this.scriptSnapshot.getLength();
}
public getChangeRange(oldScript: ts.ScriptSnapshotShim): string {
public getChangeRange(oldScript: ts.ScriptSnapshotShim): string | undefined {
const range = this.scriptSnapshot.getChangeRange((oldScript as ScriptSnapshotProxy).scriptSnapshot);
return range && JSON.stringify(range);
}
@@ -146,7 +146,7 @@ namespace Harness.LanguageService {
return fileNames;
}
public getScriptInfo(fileName: string): ScriptInfo {
public getScriptInfo(fileName: string): ScriptInfo | undefined {
return this.scriptInfos.get(vpath.resolve(this.vfs.cwd(), fileName));
}
@@ -175,9 +175,8 @@ namespace Harness.LanguageService {
* @param col 0 based index
*/
public positionToLineAndCharacter(fileName: string, position: number): ts.LineAndCharacter {
const script: ScriptInfo = this.getScriptInfo(fileName);
const script: ScriptInfo = this.getScriptInfo(fileName)!;
assert.isOk(script);
return ts.computeLineAndCharacterOfPosition(script.getLineMap(), position);
}
}
@@ -185,7 +184,7 @@ namespace Harness.LanguageService {
/// Native adapter
class NativeLanguageServiceHost extends LanguageServiceAdapterHost implements ts.LanguageServiceHost, LanguageServiceAdapterHost {
isKnownTypesPackageName(name: string): boolean {
return this.typesRegistry && this.typesRegistry.has(name);
return !!this.typesRegistry && this.typesRegistry.has(name);
}
installPackage = ts.notImplemented;
@@ -206,7 +205,7 @@ namespace Harness.LanguageService {
return this.getFilenames().filter(ts.isAnySupportedFileExtension);
}
getScriptSnapshot(fileName: string): ts.IScriptSnapshot {
getScriptSnapshot(fileName: string): ts.IScriptSnapshot | undefined {
const script = this.getScriptInfo(fileName);
return script ? new ScriptSnapshot(script) : undefined;
}
@@ -215,7 +214,7 @@ namespace Harness.LanguageService {
getScriptVersion(fileName: string): string {
const script = this.getScriptInfo(fileName);
return script ? script.version.toString() : undefined;
return script ? script.version.toString() : undefined!; // TODO: GH#18217
}
directoryExists(dirName: string): boolean {
@@ -280,7 +279,7 @@ namespace Harness.LanguageService {
}
};
this.getModuleResolutionsForFile = (fileName) => {
const scriptInfo = this.getScriptInfo(fileName);
const scriptInfo = this.getScriptInfo(fileName)!;
const preprocessInfo = ts.preProcessFile(scriptInfo.content, /*readImportFiles*/ true);
const imports: ts.MapLike<string> = {};
for (const module of preprocessInfo.importedFiles) {
@@ -299,8 +298,8 @@ namespace Harness.LanguageService {
const settings = this.nativeHost.getCompilationSettings();
for (const typeReferenceDirective of preprocessInfo.typeReferenceDirectives) {
const resolutionInfo = ts.resolveTypeReferenceDirective(typeReferenceDirective.fileName, fileName, settings, moduleResolutionHost);
if (resolutionInfo.resolvedTypeReferenceDirective.resolvedFileName) {
resolutions[typeReferenceDirective.fileName] = resolutionInfo.resolvedTypeReferenceDirective;
if (resolutionInfo.resolvedTypeReferenceDirective!.resolvedFileName) {
resolutions[typeReferenceDirective.fileName] = resolutionInfo.resolvedTypeReferenceDirective!;
}
}
return JSON.stringify(resolutions);
@@ -313,7 +312,7 @@ namespace Harness.LanguageService {
}
getFilenames(): string[] { return this.nativeHost.getFilenames(); }
getScriptInfo(fileName: string): ScriptInfo { return this.nativeHost.getScriptInfo(fileName); }
getScriptInfo(fileName: string): ScriptInfo | undefined { return this.nativeHost.getScriptInfo(fileName); }
addScript(fileName: string, content: string, isRootFile: boolean): void { this.nativeHost.addScript(fileName, content, isRootFile); }
editScript(fileName: string, start: number, end: number, newText: string): void { this.nativeHost.editScript(fileName, start, end, newText); }
positionToLineAndCharacter(fileName: string, position: number): ts.LineAndCharacter { return this.nativeHost.positionToLineAndCharacter(fileName, position); }
@@ -325,7 +324,7 @@ namespace Harness.LanguageService {
getDefaultLibFileName(): string { return this.nativeHost.getDefaultLibFileName(); }
getScriptFileNames(): string { return JSON.stringify(this.nativeHost.getScriptFileNames()); }
getScriptSnapshot(fileName: string): ts.ScriptSnapshotShim {
const nativeScriptSnapshot = this.nativeHost.getScriptSnapshot(fileName);
const nativeScriptSnapshot = this.nativeHost.getScriptSnapshot(fileName)!; // TODO: GH#18217
return nativeScriptSnapshot && new ScriptSnapshotProxy(nativeScriptSnapshot);
}
getScriptKind(): ts.ScriptKind { return this.nativeHost.getScriptKind(); }
@@ -504,7 +503,7 @@ namespace Harness.LanguageService {
getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: ts.FormatCodeOptions): ts.TextChange[] {
return unwrapJSONCallResult(this.shim.getFormattingEditsAfterKeystroke(fileName, position, key, JSON.stringify(options)));
}
getDocCommentTemplateAtPosition(fileName: string, position: number): ts.TextInsertion | undefined {
getDocCommentTemplateAtPosition(fileName: string, position: number): ts.TextInsertion {
return unwrapJSONCallResult(this.shim.getDocCommentTemplateAtPosition(fileName, position));
}
isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean {
@@ -608,7 +607,7 @@ namespace Harness.LanguageService {
class SessionClientHost extends NativeLanguageServiceHost implements ts.server.SessionClientHost {
private client: ts.server.SessionClient;
constructor(cancellationToken: ts.HostCancellationToken, settings: ts.CompilerOptions) {
constructor(cancellationToken: ts.HostCancellationToken | undefined, settings: ts.CompilerOptions | undefined) {
super(cancellationToken, settings);
}
@@ -715,7 +714,7 @@ namespace Harness.LanguageService {
return true;
}
getLogFileName(): string {
getLogFileName(): string | undefined {
return undefined;
}
@@ -850,7 +849,7 @@ namespace Harness.LanguageService {
cancellationToken: ts.server.nullCancellationToken,
useSingleInferredProject: false,
useInferredProjectPerProjectRoot: false,
typingsInstaller: undefined,
typingsInstaller: undefined!, // TODO: GH#18217
byteLength: Utils.byteLength,
hrtime: process.hrtime,
logger: serverHost,
+38 -35
View File
@@ -68,10 +68,10 @@ interface IoLog {
}[];
directoriesRead: {
path: string,
extensions: ReadonlyArray<string>,
exclude: ReadonlyArray<string>,
include: ReadonlyArray<string>,
depth: number,
extensions: ReadonlyArray<string> | undefined,
exclude: ReadonlyArray<string> | undefined,
include: ReadonlyArray<string> | undefined,
depth: number | undefined,
result: ReadonlyArray<string>,
}[];
useCaseSensitiveFileNames?: boolean;
@@ -87,8 +87,8 @@ interface PlaybackControl {
}
namespace Playback {
let recordLog: IoLog;
let replayLog: IoLog;
let recordLog: IoLog | undefined;
let replayLog: IoLog | undefined;
let replayFilesRead: ts.Map<IoLogFile> | undefined;
let recordLogFileNameBase = "";
@@ -104,7 +104,7 @@ namespace Playback {
return lookup[s] = func(s);
});
run.reset = () => {
lookup = undefined;
lookup = undefined!; // TODO: GH#18217
};
return run;
@@ -148,11 +148,12 @@ namespace Playback {
}
}
for (const file of log.filesRead) {
if (file.result.contentsPath) {
const result = file.result!; // TODO: GH#18217
if (result.contentsPath) {
// `readFile` strips away a BOM (and actually reinerprets the file contents according to the correct encoding)
// - but this has the unfortunate sideeffect of removing the BOM from any outputs based on the file, so we readd it here.
file.result.contents = (file.result.bom || "") + host.readFile(ts.combinePaths(baseName, file.result.contentsPath));
delete file.result.contentsPath;
result.contents = (result.bom || "") + host.readFile(ts.combinePaths(baseName, result.contentsPath));
delete result.contentsPath;
}
}
return log;
@@ -188,21 +189,22 @@ namespace Playback {
}
if (log.filesRead) {
for (const file of log.filesRead) {
const { contents } = file.result;
const result = file.result!; // TODO: GH#18217
const { contents } = result;
if (contents !== undefined) {
file.result.contentsPath = ts.combinePaths("read", sanitizeTestFilePath(file.path));
writeFile(ts.combinePaths(baseTestName, file.result.contentsPath), contents);
result.contentsPath = ts.combinePaths("read", sanitizeTestFilePath(file.path));
writeFile(ts.combinePaths(baseTestName, result.contentsPath), contents);
const len = contents.length;
if (len >= 2 && contents.charCodeAt(0) === 0xfeff) {
file.result.bom = "\ufeff";
result.bom = "\ufeff";
}
if (len >= 2 && contents.charCodeAt(0) === 0xfffe) {
file.result.bom = "\ufffe";
result.bom = "\ufffe";
}
if (len >= 3 && contents.charCodeAt(0) === 0xefbb && contents.charCodeAt(1) === 0xbf) {
file.result.bom = "\uefbb\xbf";
result.bom = "\uefbb\xbf";
}
delete file.result.contents;
delete result.contents;
}
}
}
@@ -222,7 +224,7 @@ namespace Playback {
wrapper.startReplayFromData = log => {
replayLog = log;
// Remove non-found files from the log (shouldn't really need them, but we still record them for diagnostic purposes)
replayLog.filesRead = replayLog.filesRead.filter(f => f.result.contents !== undefined);
replayLog.filesRead = replayLog.filesRead.filter(f => f.result!.contents !== undefined);
replayFilesRead = ts.createMap();
for (const file of replayLog.filesRead) {
replayFilesRead.set(ts.normalizeSlashes(file.path).toLowerCase(), file);
@@ -244,7 +246,7 @@ namespace Playback {
};
wrapper.startReplayFromFile = logFn => {
wrapper.startReplayFromString(underlying.readFile(logFn));
wrapper.startReplayFromString(underlying.readFile(logFn)!);
};
wrapper.endRecord = () => {
if (recordLog !== undefined) {
@@ -267,24 +269,25 @@ namespace Playback {
}
const files = [];
for (const file of newLog.filesRead) {
if (file.result.contentsPath &&
Harness.isDefaultLibraryFile(file.result.contentsPath) &&
/\.[tj]s$/.test(file.result.contentsPath)) {
files.push(file.result.contentsPath);
const result = file.result!;
if (result.contentsPath &&
Harness.isDefaultLibraryFile(result.contentsPath) &&
/\.[tj]s$/.test(result.contentsPath)) {
files.push(result.contentsPath);
}
}
return { compilerOptions: ts.parseCommandLine(newLog.arguments).options, files };
}
wrapper.fileExists = recordReplay(wrapper.fileExists, underlying)(
path => callAndRecord(underlying.fileExists(path), recordLog.fileExists, { path }),
path => callAndRecord(underlying.fileExists(path), recordLog!.fileExists, { path }),
memoize(path => {
// If we read from the file, it must exist
if (findFileByPath(path, /*throwFileNotFoundError*/ false)) {
return true;
}
else {
return findResultByFields(replayLog.fileExists, { path }, /*defaultValue*/ false);
return findResultByFields(replayLog!.fileExists, { path }, /*defaultValue*/ false)!;
}
})
);
@@ -314,22 +317,22 @@ namespace Playback {
};
wrapper.resolvePath = recordReplay(wrapper.resolvePath, underlying)(
path => callAndRecord(underlying.resolvePath(path), recordLog.pathsResolved, { path }),
memoize(path => findResultByFields(replayLog.pathsResolved, { path }, !ts.isRootedDiskPath(ts.normalizeSlashes(path)) && replayLog.currentDirectory ? replayLog.currentDirectory + "/" + path : ts.normalizeSlashes(path))));
path => callAndRecord(underlying.resolvePath(path), recordLog!.pathsResolved, { path }),
memoize(path => findResultByFields(replayLog!.pathsResolved, { path }, !ts.isRootedDiskPath(ts.normalizeSlashes(path)) && replayLog!.currentDirectory ? replayLog!.currentDirectory + "/" + path : ts.normalizeSlashes(path))));
wrapper.readFile = recordReplay(wrapper.readFile, underlying)(
(path: string) => {
const result = underlying.readFile(path);
const logEntry = { path, codepage: 0, result: { contents: result, codepage: 0 } };
recordLog.filesRead.push(logEntry);
recordLog!.filesRead.push(logEntry);
return result;
},
memoize(path => findFileByPath(path, /*throwFileNotFoundError*/ true).contents));
memoize(path => findFileByPath(path, /*throwFileNotFoundError*/ true)!.contents));
wrapper.readDirectory = recordReplay(wrapper.readDirectory, underlying)(
(path, extensions, exclude, include, depth) => {
const result = (<ts.System>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<T>(logArray: { result?: T }[], expectedFields: {}, defaultValue?: T): T {
function findResultByFields<T>(logArray: { result?: T }[], expectedFields: {}, defaultValue?: T): T | undefined {
const predicate = (entry: { result?: T }) => {
return Object.getOwnPropertyNames(expectedFields).every((name) => (<any>entry)[name] === (<any>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;
}
+14 -12
View File
@@ -1,3 +1,5 @@
// tslint:disable no-unnecessary-type-assertion (TODO: tslint can't find node types)
if (typeof describe === "undefined") {
(global as any).describe = undefined; // If launched without mocha for parallel mode, we still need a global describe visible to satisfy the parsing of the unit tests
(global as any).it = undefined;
@@ -32,7 +34,7 @@ namespace Harness.Parallel.Host {
function perfdataFileName(target?: string) {
return `${perfdataFileNameFragment}${target ? `.${target}` : ""}.json`;
}
function readSavedPerfData(target?: string): {[testHash: string]: number} {
function readSavedPerfData(target?: string): {[testHash: string]: number} | undefined {
const perfDataContents = IO.readFile(perfdataFileName(target));
if (perfDataContents) {
return JSON.parse(perfDataContents);
@@ -73,7 +75,7 @@ namespace Harness.Parallel.Host {
setTimeout(() => startDelayed(perfData, totalCost), 0); // Do real startup on next tick, so all unit tests have been collected
}
function startDelayed(perfData: {[testHash: string]: number}, totalCost: number) {
function startDelayed(perfData: {[testHash: string]: number} | undefined, totalCost: number) {
initializeProgressBarsDependencies();
console.log(`Discovered ${tasks.length} unittest suites` + (newTasks.length ? ` and ${newTasks.length} new suites.` : "."));
console.log("Discovering runner-based tests...");
@@ -227,16 +229,16 @@ namespace Harness.Parallel.Host {
return;
}
// Send tasks in blocks if the tasks are small
const taskList = [tasks.pop()];
const taskList = [tasks.pop()!];
while (tasks.length && taskList.reduce((p, c) => p + c.size, 0) < chunkSize) {
taskList.push(tasks.pop());
taskList.push(tasks.pop()!);
}
child.currentTasks = taskList;
if (taskList.length === 1) {
child.send({ type: "test", payload: taskList[0] });
child.send({ type: "test", payload: taskList[0] } as ParallelHostMessage); // TODO: GH#18217
}
else {
child.send({ type: "batch", payload: taskList });
child.send({ type: "batch", payload: taskList } as ParallelHostMessage); // TODO: GH#18217
}
}
}
@@ -268,7 +270,7 @@ namespace Harness.Parallel.Host {
doneBatching[i] = true;
continue;
}
const task = tasks.pop();
const task = tasks.pop()!;
batches[i].push(task);
scheduledTotal += task.size;
}
@@ -293,7 +295,7 @@ namespace Harness.Parallel.Host {
worker.send({ type: "batch", payload });
}
else { // Out of batches, send off just one test
const payload = tasks.pop();
const payload = tasks.pop()!;
ts.Debug.assert(!!payload); // The reserve kept above should ensure there is always an initial task available, even in suboptimal scenarios
worker.currentTasks = [payload];
worker.send({ type: "test", payload });
@@ -302,7 +304,7 @@ namespace Harness.Parallel.Host {
}
else {
for (let i = 0; i < workerCount; i++) {
const task = tasks.pop();
const task = tasks.pop()!;
workers[i].currentTasks = [task];
workers[i].send({ type: "test", payload: task });
}
@@ -519,7 +521,7 @@ namespace Harness.Parallel.Host {
this._enabled = false;
}
}
update(index: number, percentComplete: number, color: string, title: string, titleColor?: string) {
update(index: number, percentComplete: number, color: string, title: string | undefined, titleColor?: string) {
percentComplete = minMax(percentComplete, 0, 1);
const progressBar = this._progressBars[index] || (this._progressBars[index] = { });
@@ -555,7 +557,7 @@ namespace Harness.Parallel.Host {
}
cursor.hide();
readline.moveCursor(process.stdout, -process.stdout.columns, -this._lineCount);
readline.moveCursor(process.stdout, -process.stdout.columns!, -this._lineCount);
let lineCount = 0;
const numProgressBars = this._progressBars.length;
for (let i = 0; i < numProgressBars; i++) {
@@ -564,7 +566,7 @@ namespace Harness.Parallel.Host {
process.stdout.write(this._progressBars[i].text + os.EOL);
}
else {
readline.moveCursor(process.stdout, -process.stdout.columns, +1);
readline.moveCursor(process.stdout, -process.stdout.columns!, +1);
}
lineCount++;
+17 -15
View File
@@ -1,3 +1,5 @@
// tslint:disable no-unnecessary-type-assertion (TODO: tslint can't find node types)
namespace Harness.Parallel.Worker {
let errors: ErrorInfo[] = [];
let passes: TestInfo[] = [];
@@ -35,7 +37,7 @@ namespace Harness.Parallel.Worker {
if (!testList) {
throw new Error("Tests must occur within a describe block");
}
testList.push({ name, callback, kind: "test" });
testList.push({ name, callback: callback!, kind: "test" });
}) as Mocha.ITestDefinition;
(global as any).it.skip = ts.noop;
}
@@ -43,18 +45,18 @@ namespace Harness.Parallel.Worker {
function setTimeoutAndExecute(timeout: number | undefined, f: () => void) {
if (timeout !== undefined) {
const timeoutMsg: ParallelTimeoutChangeMessage = { type: "timeout", payload: { duration: timeout } };
process.send(timeoutMsg);
process.send!(timeoutMsg);
}
f();
if (timeout !== undefined) {
// Reset timeout
const timeoutMsg: ParallelTimeoutChangeMessage = { type: "timeout", payload: { duration: "reset" } };
process.send(timeoutMsg);
process.send!(timeoutMsg);
}
}
function executeSuiteCallback(name: string, callback: MochaCallback) {
let timeout: number;
let timeout: number | undefined;
const fakeContext: Mocha.ISuiteCallbackContext = {
retries() { return this; },
slow() { return this; },
@@ -64,9 +66,9 @@ namespace Harness.Parallel.Worker {
},
};
namestack.push(name);
let beforeFunc: Callable;
let beforeFunc: Callable | undefined;
(before as any) = (cb: Callable) => beforeFunc = cb;
let afterFunc: Callable;
let afterFunc: Callable | undefined;
(after as any) = (cb: Callable) => afterFunc = cb;
const savedBeforeEach = beforeEachFunc;
(beforeEach as any) = (cb: Callable) => beforeEachFunc = cb;
@@ -127,13 +129,13 @@ namespace Harness.Parallel.Worker {
}
function executeTestCallback(name: string, callback: MochaCallback) {
let timeout: number;
let timeout: number | undefined;
const fakeContext: Mocha.ITestCallbackContext = {
skip() { return this; },
timeout(n: number) {
timeout = n;
const timeoutMsg: ParallelTimeoutChangeMessage = { type: "timeout", payload: { duration: timeout } };
process.send(timeoutMsg);
process.send!(timeoutMsg);
return this;
},
retries() { return this; },
@@ -164,7 +166,7 @@ namespace Harness.Parallel.Worker {
namestack.pop();
if (timeout !== undefined) {
const timeoutMsg: ParallelTimeoutChangeMessage = { type: "timeout", payload: { duration: "reset" } };
process.send(timeoutMsg);
process.send!(timeoutMsg);
}
}
passing++;
@@ -195,7 +197,7 @@ namespace Harness.Parallel.Worker {
namestack.pop();
if (timeout !== undefined) {
const timeoutMsg: ParallelTimeoutChangeMessage = { type: "timeout", payload: { duration: "reset" } };
process.send(timeoutMsg);
process.send!(timeoutMsg);
}
}
if (!completed) {
@@ -219,7 +221,7 @@ namespace Harness.Parallel.Worker {
console.error(data);
}
const message: ParallelResultMessage = { type: "result", payload: handleTest(runner, file) };
process.send(message);
process.send!(message);
break;
case "close":
process.exit(0);
@@ -239,16 +241,16 @@ namespace Harness.Parallel.Worker {
else {
message = { type: "progress", payload };
}
process.send(message);
process.send!(message);
}
break;
}
}
});
process.on("uncaughtException", error => {
const message: ParallelErrorMessage = { type: "error", payload: { error: error.message, stack: error.stack, name: [...namestack] } };
const message: ParallelErrorMessage = { type: "error", payload: { error: error.message, stack: error.stack!, name: [...namestack] } };
try {
process.send(message);
process.send!(message);
}
catch (e) {
console.error(error);
@@ -273,7 +275,7 @@ namespace Harness.Parallel.Worker {
if (!runners.has(runner)) {
runners.set(runner, createRunner(runner));
}
const instance = runners.get(runner);
const instance = runners.get(runner)!;
instance.tests = [file];
return { ...resetShimHarnessAndExecute(instance), runner, file };
}
+17 -17
View File
@@ -134,7 +134,7 @@ namespace project {
this.compilerOptions = createCompilerOptions(testCase, moduleKind);
this.sys = new fakes.System(vfs);
let configFileName: string;
let configFileName: string | undefined;
let inputFiles = testCase.inputFiles;
if (this.compilerOptions.project) {
// Parse project
@@ -145,7 +145,7 @@ namespace project {
configFileName = ts.findConfigFile("", path => this.sys.fileExists(path));
}
let errors: ts.Diagnostic[];
let errors: ts.Diagnostic[] | undefined;
const configFileSourceFiles: ts.SourceFile[] = [];
if (configFileName) {
const result = ts.readJsonConfigFile(configFileName, path => this.sys.readFile(path));
@@ -178,7 +178,7 @@ namespace project {
public static getConfigurations(testCaseFileName: string): ProjectTestConfiguration[] {
let testCase: ProjectRunnerTestCase & ts.CompilerOptions;
let testFileText: string;
let testFileText: string | undefined;
try {
testFileText = Harness.IO.readFile(testCaseFileName);
}
@@ -187,10 +187,10 @@ namespace project {
}
try {
testCase = <ProjectRunnerTestCase & ts.CompilerOptions>JSON.parse(testFileText);
testCase = <ProjectRunnerTestCase & ts.CompilerOptions>JSON.parse(testFileText!);
}
catch (e) {
assert(false, "Testcase: " + testCaseFileName + " does not contain valid json format: " + e.message);
throw assert(false, "Testcase: " + testCaseFileName + " does not contain valid json format: " + e.message);
}
const fs = vfs.createFromFileSystem(Harness.IO, /*ignoreCase*/ false);
@@ -209,12 +209,12 @@ namespace project {
const cwd = this.vfs.cwd();
const ignoreCase = this.vfs.ignoreCase;
const resolutionInfo: ProjectRunnerTestCaseResolutionInfo & ts.CompilerOptions = JSON.parse(JSON.stringify(this.testCase));
resolutionInfo.resolvedInputFiles = this.compilerResult.program.getSourceFiles()
resolutionInfo.resolvedInputFiles = this.compilerResult.program!.getSourceFiles()
.map(({ fileName: input }) => vpath.beneath(vfs.builtFolder, input, this.vfs.ignoreCase) || vpath.beneath(vfs.testLibFolder, input, this.vfs.ignoreCase) ? utils.removeTestPathPrefixes(input) :
vpath.isAbsolute(input) ? vpath.relative(cwd, input, ignoreCase) :
input);
resolutionInfo.emittedFiles = this.compilerResult.outputFiles
resolutionInfo.emittedFiles = this.compilerResult.outputFiles!
.map(output => output.meta.get("fileName") || output.file)
.map(output => utils.removeTestPathPrefixes(vpath.isAbsolute(output) ? vpath.relative(cwd, output, ignoreCase) : output));
@@ -234,7 +234,7 @@ namespace project {
if (this.testCase.baselineCheck) {
const errs: Error[] = [];
let nonSubfolderDiskFiles = 0;
for (const output of this.compilerResult.outputFiles) {
for (const output of this.compilerResult.outputFiles!) {
try {
// convert file name to rooted name
// if filename is not rooted - concat it with project root and then expand project root relative to current directory
@@ -252,7 +252,7 @@ namespace project {
}
const content = utils.removeTestPathPrefixes(output.text, /*retainTrailingDirectorySeparator*/ true);
Harness.Baseline.runBaseline(this.getBaselineFolder(this.compilerResult.moduleKind) + diskRelativeName, () => content);
Harness.Baseline.runBaseline(this.getBaselineFolder(this.compilerResult.moduleKind) + diskRelativeName, () => content as string | null); // TODO: GH#18217
}
catch (e) {
errs.push(e);
@@ -292,7 +292,7 @@ namespace project {
}
private cleanProjectUrl(url: string) {
let diskProjectPath = ts.normalizeSlashes(Harness.IO.resolvePath(this.testCase.projectRoot));
let diskProjectPath = ts.normalizeSlashes(Harness.IO.resolvePath(this.testCase.projectRoot)!);
let projectRootUrl = "file:///" + diskProjectPath;
const normalizedProjectRoot = ts.normalizeSlashes(this.testCase.projectRoot);
diskProjectPath = diskProjectPath.substr(0, diskProjectPath.lastIndexOf(normalizedProjectRoot));
@@ -362,10 +362,10 @@ namespace project {
rootFiles.unshift(sourceFile.fileName);
}
else if (!(compilerOptions.outFile || compilerOptions.out)) {
let emitOutputFilePathWithoutExtension: string;
let emitOutputFilePathWithoutExtension: string | undefined;
if (compilerOptions.outDir) {
let sourceFilePath = ts.getNormalizedAbsolutePath(sourceFile.fileName, compilerResult.program.getCurrentDirectory());
sourceFilePath = sourceFilePath.replace(compilerResult.program.getCommonSourceDirectory(), "");
let sourceFilePath = ts.getNormalizedAbsolutePath(sourceFile.fileName, compilerResult.program!.getCurrentDirectory());
sourceFilePath = sourceFilePath.replace(compilerResult.program!.getCommonSourceDirectory(), "");
emitOutputFilePathWithoutExtension = ts.removeFileExtension(ts.combinePaths(compilerOptions.outDir, sourceFilePath));
}
else {
@@ -380,8 +380,8 @@ namespace project {
}
}
else {
const outputDtsFileName = ts.removeFileExtension(compilerOptions.outFile || compilerOptions.out) + ts.Extension.Dts;
const outputDtsFile = findOutputDtsFile(outputDtsFileName);
const outputDtsFileName = ts.removeFileExtension(compilerOptions.outFile || compilerOptions.out!) + ts.Extension.Dts;
const outputDtsFile = findOutputDtsFile(outputDtsFileName)!;
if (!ts.contains(allInputFiles, outputDtsFile)) {
allInputFiles.unshift(outputDtsFile);
rootFiles.unshift(outputDtsFile.meta.get("fileName") || outputDtsFile.file);
@@ -395,8 +395,8 @@ namespace project {
});
// Dont allow config files since we are compiling existing source options
const compilerHost = new ProjectCompilerHost(_vfs, compilerResult.compilerOptions, this.testCaseJustName, this.testCase, compilerResult.moduleKind);
return this.compileProjectFiles(compilerResult.moduleKind, compilerResult.configFileSourceFiles, () => rootFiles, compilerHost, compilerResult.compilerOptions);
const compilerHost = new ProjectCompilerHost(_vfs, compilerResult.compilerOptions!, this.testCaseJustName, this.testCase, compilerResult.moduleKind);
return this.compileProjectFiles(compilerResult.moduleKind, compilerResult.configFileSourceFiles, () => rootFiles, compilerHost, compilerResult.compilerOptions!);
function findOutputDtsFile(fileName: string) {
return ts.forEach(compilerResult.outputFiles, outputFile => outputFile.meta.get("fileName") === fileName ? outputFile : undefined);
+8 -7
View File
@@ -65,7 +65,7 @@ function createRunner(kind: TestRunnerKind): RunnerBase {
case "dt":
return new DefinitelyTypedRunner();
}
ts.Debug.fail(`Unknown runner kind ${kind}`);
return ts.Debug.fail(`Unknown runner kind ${kind}`);
}
// users can define tests to run in mytest.config that will override cmd line args, otherwise use cmd line args (test.config), otherwise no options
@@ -76,10 +76,10 @@ const testconfigFileName = "test.config";
const customConfig = tryGetConfig(Harness.IO.args());
let testConfigContent =
customConfig && Harness.IO.fileExists(customConfig)
? Harness.IO.readFile(customConfig)
? Harness.IO.readFile(customConfig)!
: Harness.IO.fileExists(mytestconfigFileName)
? Harness.IO.readFile(mytestconfigFileName)
: Harness.IO.fileExists(testconfigFileName) ? Harness.IO.readFile(testconfigFileName) : "";
? Harness.IO.readFile(mytestconfigFileName)!
: Harness.IO.fileExists(testconfigFileName) ? Harness.IO.readFile(testconfigFileName)! : "";
let taskConfigsFolder: string;
let workerCount: number;
@@ -131,9 +131,9 @@ function handleTestConfig() {
(<any>Error).stackTraceLimit = Infinity;
stackTraceLimit = testConfig.stackTraceLimit;
}
else if ((+testConfig.stackTraceLimit | 0) > 0) {
(<any>Error).stackTraceLimit = +testConfig.stackTraceLimit | 0;
stackTraceLimit = +testConfig.stackTraceLimit | 0;
else if ((+testConfig.stackTraceLimit! | 0) > 0) {
(<any>Error).stackTraceLimit = +testConfig.stackTraceLimit! | 0;
stackTraceLimit = +testConfig.stackTraceLimit! | 0;
}
if (testConfig.listenForWork) {
return true;
@@ -222,6 +222,7 @@ function handleTestConfig() {
if (runUnitTests === undefined) {
runUnitTests = runners.length !== 1; // Don't run unit tests when running only one runner if unit tests were not explicitly asked for
}
return false;
}
function beginTests() {
+15 -15
View File
@@ -41,22 +41,22 @@ namespace RWC {
inputFiles = [];
otherFiles = [];
tsconfigFiles = [];
compilerResult = undefined;
compilerOptions = undefined;
currentDirectory = undefined;
compilerResult = undefined!;
compilerOptions = undefined!;
currentDirectory = undefined!;
// useCustomLibraryFile is a flag specified in the json object to indicate whether to use built/local/lib.d.ts
// or to use lib.d.ts inside the json object. If the flag is true, use the lib.d.ts inside json file
// otherwise use the lib.d.ts from built/local
useCustomLibraryFile = undefined;
useCustomLibraryFile = undefined!;
});
it("can compile", function(this: Mocha.ITestCallbackContext) {
this.timeout(800_000); // Allow long timeouts for RWC compilations
let opts: ts.ParsedCommandLine;
let opts!: ts.ParsedCommandLine;
const ioLog: IoLog = Playback.newStyleLogIntoOldStyleLog(JSON.parse(Harness.IO.readFile(`internal/cases/rwc/${jsonPath}/test.json`)), Harness.IO, `internal/cases/rwc/${baseName}`);
const ioLog: IoLog = Playback.newStyleLogIntoOldStyleLog(JSON.parse(Harness.IO.readFile(`internal/cases/rwc/${jsonPath}/test.json`)!), Harness.IO, `internal/cases/rwc/${baseName}`);
currentDirectory = ioLog.currentDirectory;
useCustomLibraryFile = ioLog.useCustomLibraryFile;
useCustomLibraryFile = !!ioLog.useCustomLibraryFile;
runWithIOLog(ioLog, () => {
opts = ts.parseCommandLine(ioLog.arguments, fileName => Harness.IO.readFile(fileName));
assert.equal(opts.errors.length, 0);
@@ -89,7 +89,7 @@ namespace RWC {
const uniqueNames = ts.createMap<true>();
for (const fileName of fileNames) {
// Must maintain order, build result list while checking map
const normalized = ts.normalizeSlashes(Harness.IO.resolvePath(fileName));
const normalized = ts.normalizeSlashes(Harness.IO.resolvePath(fileName)!);
if (!uniqueNames.has(normalized)) {
uniqueNames.set(normalized, true);
// Load the file
@@ -99,7 +99,7 @@ namespace RWC {
// Add files to compilation
for (const fileRead of ioLog.filesRead) {
const unitName = ts.normalizeSlashes(Harness.IO.resolvePath(fileRead.path));
const unitName = ts.normalizeSlashes(Harness.IO.resolvePath(fileRead.path)!);
if (!uniqueNames.has(unitName) && !Harness.isDefaultLibraryFile(fileRead.path)) {
uniqueNames.set(unitName, true);
otherFiles.push(getHarnessCompilerInputUnit(unitName));
@@ -134,13 +134,13 @@ namespace RWC {
compilerOptions = compilerResult.options;
function getHarnessCompilerInputUnit(fileName: string): Harness.Compiler.TestFile {
const unitName = ts.normalizeSlashes(Harness.IO.resolvePath(fileName));
const unitName = ts.normalizeSlashes(Harness.IO.resolvePath(fileName)!);
let content: string;
try {
content = Harness.IO.readFile(unitName);
content = Harness.IO.readFile(unitName)!;
}
catch (e) {
content = Harness.IO.readFile(fileName);
content = Harness.IO.readFile(fileName)!;
}
return { unitName, content };
}
@@ -196,11 +196,11 @@ namespace RWC {
}
const declContext = Harness.Compiler.prepareDeclarationCompilationContext(
inputFiles, otherFiles, compilerResult, /*harnessSettings*/ undefined, compilerOptions, currentDirectory
inputFiles, otherFiles, compilerResult, /*harnessSettings*/ undefined!, compilerOptions, currentDirectory // TODO: GH#18217
);
// Reset compilerResult before calling into `compileDeclarationFiles` so the memory from the original compilation can be freed
compilerResult = undefined;
const declFileCompilationResult = Harness.Compiler.compileDeclarationFiles(declContext);
compilerResult = undefined!;
const declFileCompilationResult = Harness.Compiler.compileDeclarationFiles(declContext)!;
return Harness.Compiler.iterateErrorBaseline(tsconfigFiles.concat(declFileCompilationResult.declInputFiles, declFileCompilationResult.declOtherFiles), declFileCompilationResult.declResult.diagnostics);
}, baselineOpts);
+15 -14
View File
@@ -19,16 +19,16 @@ namespace Harness.SourceMapRecorder {
interface SourceMapSpanWithDecodeErrors {
sourceMapSpan: ts.SourceMapSpan;
decodeErrors: string[];
decodeErrors: string[] | undefined;
}
namespace SourceMapDecoder {
let sourceMapMappings: string;
let sourceMapNames: string[];
let sourceMapNames: string[] | undefined;
let decodingIndex: number;
let prevNameIndex: number;
let decodeOfEncodedMapping: ts.SourceMapSpan;
let errorDecodeOfEncodedMapping: string;
let errorDecodeOfEncodedMapping: string | undefined;
export function initializeSourceMapDecoding(sourceMapData: ts.SourceMapData) {
sourceMapMappings = sourceMapData.sourceMapMappings;
@@ -88,7 +88,7 @@ namespace Harness.SourceMapRecorder {
for (; moreDigits; decodingIndex++) {
if (createErrorIfCondition(decodingIndex >= sourceMapMappings.length, "Error in decoding base64VLQFormatDecode, past the mapping string")) {
return;
return undefined!; // TODO: GH#18217
}
// 6 digit number
@@ -176,7 +176,7 @@ namespace Harness.SourceMapRecorder {
prevNameIndex += base64VLQFormatDecode();
decodeOfEncodedMapping.nameIndex = prevNameIndex;
// Incorrect nameIndex dont support this map
if (createErrorIfCondition(decodeOfEncodedMapping.nameIndex < 0 || decodeOfEncodedMapping.nameIndex >= sourceMapNames.length, "Invalid name index for the source map entry")) {
if (createErrorIfCondition(decodeOfEncodedMapping.nameIndex < 0 || decodeOfEncodedMapping.nameIndex >= sourceMapNames!.length, "Invalid name index for the source map entry")) {
return { error: errorDecodeOfEncodedMapping, sourceMapSpan: decodeOfEncodedMapping };
}
}
@@ -190,6 +190,7 @@ namespace Harness.SourceMapRecorder {
}
createErrorIfCondition(/*condition*/ true, "No encoded entry found");
return undefined!; // TODO: GH#18217
}
export function hasCompletedDecoding() {
@@ -204,7 +205,7 @@ namespace Harness.SourceMapRecorder {
namespace SourceMapSpanWriter {
let sourceMapRecorder: Compiler.WriterAggregator;
let sourceMapSources: string[];
let sourceMapNames: string[];
let sourceMapNames: string[] | undefined;
let jsFile: documents.TextDocument;
let jsLineMap: ReadonlyArray<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
@@ -345,7 +346,7 @@ namespace Harness.SourceMapRecorder {
return markerId;
}
let prevEmittedCol: number;
let prevEmittedCol!: number;
function iterateSpans(fn: (currentSpan: SourceMapSpanWithDecodeErrors, index: number) => void) {
prevEmittedCol = 1;
for (let i = 0; i < spansOnSingleLine.length; i++) {
@@ -361,7 +362,7 @@ namespace Harness.SourceMapRecorder {
}
}
function writeSourceMapMarker(currentSpan: SourceMapSpanWithDecodeErrors, index: number, endColumn = currentSpan.sourceMapSpan.emittedColumn, endContinues?: boolean) {
function writeSourceMapMarker(currentSpan: SourceMapSpanWithDecodeErrors, index: number, endColumn = currentSpan.sourceMapSpan.emittedColumn, endContinues = false) {
const markerId = getMarkerId(index);
markerIds.push(markerId);
@@ -421,7 +422,7 @@ namespace Harness.SourceMapRecorder {
const jsFileText = getTextOfLine(currentJsLine, jsLineMap, jsFile.text);
if (prevEmittedCol < jsFileText.length) {
// There is remaining text on this line that will be part of next source span so write marker that continues
writeSourceMapMarker(/*currentSpan*/ undefined, spansOnSingleLine.length, /*endColumn*/ jsFileText.length, /*endContinues*/ true);
writeSourceMapMarker(/*currentSpan*/ undefined!, spansOnSingleLine.length, /*endColumn*/ jsFileText.length, /*endContinues*/ true); // TODO: GH#18217
}
// Emit Source text
@@ -440,7 +441,7 @@ namespace Harness.SourceMapRecorder {
for (let i = 0; i < sourceMapDataList.length; i++) {
const sourceMapData = sourceMapDataList[i];
let prevSourceFile: ts.SourceFile;
let prevSourceFile: ts.SourceFile | undefined;
let currentFile: documents.TextDocument;
if (ts.endsWith(sourceMapData.sourceMapFile, ts.Extension.Dts)) {
if (sourceMapDataList.length > jsFiles.length) {
@@ -461,7 +462,7 @@ namespace Harness.SourceMapRecorder {
SourceMapSpanWriter.initializeSourceMapSpanWriter(sourceMapRecorder, sourceMapData, currentFile);
for (const decodedSourceMapping of sourceMapData.sourceMapDecodedMappings) {
const currentSourceFile = program.getSourceFile(sourceMapData.inputSourceFileNames[decodedSourceMapping.sourceIndex]);
const currentSourceFile = program.getSourceFile(sourceMapData.inputSourceFileNames[decodedSourceMapping.sourceIndex])!;
if (currentSourceFile !== prevSourceFile) {
SourceMapSpanWriter.recordNewSourceFileSpan(decodedSourceMapping, currentSourceFile.text);
prevSourceFile = currentSourceFile;
+6 -6
View File
@@ -8,7 +8,7 @@ class Test262BaselineRunner extends RunnerBase {
private static readonly helpersFilePath = "tests/cases/test262-harness/helpers.d.ts";
private static readonly helperFile: Harness.Compiler.TestFile = {
unitName: Test262BaselineRunner.helpersFilePath,
content: Harness.IO.readFile(Test262BaselineRunner.helpersFilePath),
content: Harness.IO.readFile(Test262BaselineRunner.helpersFilePath)!,
};
private static readonly testFileExtensionRegex = /\.js$/;
private static readonly options: ts.CompilerOptions = {
@@ -36,7 +36,7 @@ class Test262BaselineRunner extends RunnerBase {
};
before(() => {
const content = Harness.IO.readFile(filePath);
const content = Harness.IO.readFile(filePath)!;
const testFilename = ts.removeFileExtension(filePath).replace(/\//g, "_") + ".test";
const testCaseContent = Harness.TestCaseParser.makeUnitsFromTest(content, testFilename);
@@ -49,7 +49,7 @@ class Test262BaselineRunner extends RunnerBase {
testState = {
filename: testFilename,
inputFiles,
compilerResult: undefined,
compilerResult: undefined!, // TODO: GH#18217
};
testState.compilerResult = Harness.Compiler.compileFiles(
@@ -61,7 +61,7 @@ class Test262BaselineRunner extends RunnerBase {
});
after(() => {
testState = undefined;
testState = undefined!;
});
it("has the expected emitted code", () => {
@@ -83,13 +83,13 @@ class Test262BaselineRunner extends RunnerBase {
});
it("satisfies invariants", () => {
const sourceFile = testState.compilerResult.program.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename));
const sourceFile = testState.compilerResult.program!.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename));
Utils.assertInvariants(sourceFile, /*parent:*/ undefined);
});
it("has the expected AST", () => {
Harness.Baseline.runBaseline(testState.filename + ".AST.txt", () => {
const sourceFile = testState.compilerResult.program.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename));
const sourceFile = testState.compilerResult.program!.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename))!;
return Utils.sourceFileToJSON(sourceFile);
}, Test262BaselineRunner.baselineOptions);
});
+3 -3
View File
@@ -34,7 +34,7 @@ class TypeWriterWalker {
}
public *getSymbols(fileName: string): IterableIterator<TypeWriterSymbolResult> {
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<TypeWriterTypeResult> {
const sourceFile = this.program.getSourceFile(fileName);
const sourceFile = this.program.getSourceFile(fileName)!;
this.currentSourceFile = sourceFile;
const gen = this.visitNode(sourceFile, /*isSymbolWalk*/ false);
for (let {done, value} = gen.next(); !done; { done, value } = gen.next()) {
@@ -69,7 +69,7 @@ class TypeWriterWalker {
}
}
private writeTypeOrSymbol(node: ts.Node, isSymbolWalk: boolean): TypeWriterResult {
private writeTypeOrSymbol(node: ts.Node, isSymbolWalk: boolean): TypeWriterResult | undefined {
const actualPos = ts.skipTrivia(this.currentSourceFile.text, node.pos);
const lineAndCharacter = this.currentSourceFile.getLineAndCharacterOfPosition(actualPos);
const sourceText = ts.getSourceTextOfNodeFromSourceFile(this.currentSourceFile, node);
+1 -1
View File
@@ -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));
};
}
@@ -10,21 +10,21 @@ namespace ts {
`;
it("can cancel signature help mid-request", () => {
verifyOperationCancelledAfter(file, 4, service => // Two calls are top-level in services, one is the root type, and the second should be for the parameter type
service.getSignatureHelpItems("file.ts", file.lastIndexOf("f")),
service.getSignatureHelpItems("file.ts", file.lastIndexOf("f"))!,
r => assert.exists(r.items[0])
);
});
it("can cancel find all references mid-request", () => {
verifyOperationCancelledAfter(file, 3, service => // Two calls are top-level in services, one is the root type
service.findReferences("file.ts", file.lastIndexOf("o")),
service.findReferences("file.ts", file.lastIndexOf("o"))!,
r => assert.exists(r[0].definition)
);
});
it("can cancel quick info mid-request", () => {
verifyOperationCancelledAfter(file, 1, service => // The LS doesn't do any top-level checks on the token for quickinfo, so the first check is within the checker
service.getQuickInfoAtPosition("file.ts", file.lastIndexOf("o")),
service.getQuickInfoAtPosition("file.ts", file.lastIndexOf("o"))!,
r => assert.exists(r.displayParts)
);
});
@@ -52,7 +52,7 @@ namespace ts {
placeOpenBraceOnNewLineForControlBlocks: false,
};
verifyOperationCancelledAfter(file, 1, service => // The LS doesn't do any top-level checks on the token for completion entry details, so the first check is within the checker
service.getCompletionEntryDetails("file.ts", file.lastIndexOf("f"), "foo", options, /*content*/ undefined, {}),
service.getCompletionEntryDetails("file.ts", file.lastIndexOf("f"), "foo", options, /*content*/ undefined, {})!,
r => assert.exists(r.displayParts)
);
});
+3 -3
View File
@@ -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) {
@@ -11,7 +11,7 @@ namespace ts {
assertTypeAcquisitionWithJsonNode(json, configFileName, expectedResult);
}
function verifyAcquisition(actualTypeAcquisition: TypeAcquisition, expectedResult: ExpectedResult) {
function verifyAcquisition(actualTypeAcquisition: TypeAcquisition | undefined, expectedResult: ExpectedResult) {
const parsedTypeAcquisition = JSON.stringify(actualTypeAcquisition);
const expectedTypeAcquisition = JSON.stringify(expectedResult.typeAcquisition);
assert.equal(parsedTypeAcquisition, expectedTypeAcquisition);
@@ -120,7 +120,7 @@ namespace ts {
file: undefined,
start: 0,
length: 0,
messageText: undefined
messageText: undefined!, // TODO: GH#18217
}
]
});
@@ -215,7 +215,7 @@ namespace ts {
file: undefined,
start: 0,
length: 0,
messageText: undefined
messageText: undefined!, // TODO: GH#18217
}
]
});
+1 -1
View File
@@ -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),
};
+7 -6
View File
@@ -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 => <string>e.messageText).sort();
const sortedErrors = result.errors!.map(e => <string>e.messageText).sort();
assert.deepEqual(sortedErrors, expectedErrors.sort(), "unexpected errors");
});
}
@@ -27,13 +27,14 @@ namespace ts {
const expectedRange = t.ranges.get("extracted");
if (expectedRange) {
let pos: number, end: number;
if (isArray(result.targetRange.range)) {
pos = result.targetRange.range[0].getStart(f);
end = lastOrUndefined(result.targetRange.range).getEnd();
const targetRange = result.targetRange!;
if (isArray(targetRange.range)) {
pos = targetRange.range[0].getStart(f);
end = last(targetRange.range).getEnd();
}
else {
pos = result.targetRange.range.getStart(f);
end = result.targetRange.range.getEnd();
pos = targetRange.range.getStart(f);
end = targetRange.range.getEnd();
}
assert.equal(pos, expectedRange.pos, "incorrect pos of range");
assert.equal(end, expectedRange.end, "incorrect end of range");
+11 -11
View File
@@ -34,7 +34,7 @@ namespace ts {
const name = s === e
? source.charCodeAt(saved + 1) === CharacterCodes.hash ? "selection" : "extracted"
: source.substring(s, e);
activeRanges.push({ name, pos: text.length, end: undefined });
activeRanges.push({ name, pos: text.length, end: undefined! }); // TODO: GH#18217
lastPos = pos;
continue;
}
@@ -45,7 +45,7 @@ namespace ts {
else if (source.charCodeAt(pos) === CharacterCodes.bar && source.charCodeAt(pos + 1) === CharacterCodes.closeBracket) {
text += source.substring(lastPos, pos);
activeRanges[activeRanges.length - 1].end = text.length;
const range = activeRanges.pop();
const range = activeRanges.pop()!;
if (range.name in ranges) {
throw new Error(`Duplicate name of range ${range.name}`);
}
@@ -100,7 +100,7 @@ namespace ts {
export function testExtractSymbol(caption: string, text: string, baselineFolder: string, description: DiagnosticMessage, includeLib?: boolean) {
const t = extractTest(text);
const selectionRange = t.ranges.get("selection");
const selectionRange = t.ranges.get("selection")!;
if (!selectionRange) {
throw new Error(`Test ${caption} does not specify selection range`);
}
@@ -118,7 +118,7 @@ namespace ts {
return;
}
const sourceFile = program.getSourceFile(path);
const sourceFile = program.getSourceFile(path)!;
const context: RefactorContext = {
cancellationToken: { throwIfCancellationRequested: noop, isCancellationRequested: returnFalse },
program,
@@ -131,15 +131,15 @@ namespace ts {
};
const rangeToExtract = refactor.extractSymbol.getRangeToExtract(sourceFile, createTextSpanFromRange(selectionRange));
assert.equal(rangeToExtract.errors, undefined, rangeToExtract.errors && "Range error: " + rangeToExtract.errors[0].messageText);
const infos = refactor.extractSymbol.getAvailableActions(context);
const actions = find(infos, info => info.description === description.message).actions;
const infos = refactor.extractSymbol.getAvailableActions(context)!;
const actions = find(infos, info => info.description === description.message)!.actions;
Harness.Baseline.runBaseline(`${baselineFolder}/${caption}${extension}`, () => {
const data: string[] = [];
data.push(`// ==ORIGINAL==`);
data.push(text.replace("[#|", "/*[#|*/").replace("|]", "/*|]*/"));
for (const action of actions) {
const { renameLocation, edits } = refactor.extractSymbol.getEditsForAction(context, action.name);
const { renameLocation, edits } = refactor.extractSymbol.getEditsForAction(context, action.name)!;
assert.lengthOf(edits, 1);
data.push(`// ==SCOPE::${action.description}==`);
const newText = textChanges.applyChanges(sourceFile.text, edits[0].textChanges);
@@ -157,7 +157,7 @@ namespace ts {
const host = projectSystem.createServerHost(includeLib ? [f, projectSystem.libFile] : [f]); // libFile is expensive to parse repeatedly - only test when required
const projectService = projectSystem.createProjectService(host);
projectService.openClientFile(f.path);
const program = projectService.inferredProjects[0].getLanguageService().getProgram();
const program = projectService.inferredProjects[0].getLanguageService().getProgram()!;
return program;
}
@@ -181,8 +181,8 @@ namespace ts {
const host = projectSystem.createServerHost([f, projectSystem.libFile]);
const projectService = projectSystem.createProjectService(host);
projectService.openClientFile(f.path);
const program = projectService.inferredProjects[0].getLanguageService().getProgram();
const sourceFile = program.getSourceFile(f.path);
const program = projectService.inferredProjects[0].getLanguageService().getProgram()!;
const sourceFile = program.getSourceFile(f.path)!;
const context: RefactorContext = {
cancellationToken: { throwIfCancellationRequested: noop, isCancellationRequested: returnFalse },
program,
@@ -195,7 +195,7 @@ namespace ts {
};
const rangeToExtract = refactor.extractSymbol.getRangeToExtract(sourceFile, createTextSpanFromRange(selectionRange));
assert.isUndefined(rangeToExtract.errors, rangeToExtract.errors && "Range error: " + rangeToExtract.errors[0].messageText);
const infos = refactor.extractSymbol.getAvailableActions(context);
const infos = refactor.extractSymbol.getAvailableActions(context)!;
assert.isUndefined(find(infos, info => info.description === description.message));
});
}
+1 -1
View File
@@ -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("");
}
+4 -4
View File
@@ -10,7 +10,7 @@ namespace ts {
assert.isTrue(typeAndDiagnostics && typeAndDiagnostics.diagnostics.length === 0, "no errors issued");
Harness.Baseline.runBaseline("JSDocParsing/TypeExpressions.parsesCorrectly." + name + ".json",
() => Utils.sourceFileToJSON(typeAndDiagnostics.jsDocTypeExpression.type));
() => Utils.sourceFileToJSON(typeAndDiagnostics!.jsDocTypeExpression.type));
});
}
@@ -89,7 +89,7 @@ namespace ts {
describe("DocComments", () => {
function parsesCorrectly(name: string, content: string) {
it(name, () => {
const comment = parseIsolatedJSDocComment(content);
const comment = parseIsolatedJSDocComment(content)!;
if (!comment) {
Debug.fail("Comment failed to parse entirely");
}
@@ -320,7 +320,7 @@ namespace ts {
assert.equal(root.kind, SyntaxKind.SourceFile);
const first = root.getFirstToken();
assert.isDefined(first);
assert.equal(first.kind, SyntaxKind.VarKeyword);
assert.equal(first!.kind, SyntaxKind.VarKeyword);
});
});
describe("getLastToken", () => {
@@ -329,7 +329,7 @@ namespace ts {
assert.isDefined(root);
const last = root.getLastToken();
assert.isDefined(last);
assert.equal(last.kind, SyntaxKind.EndOfFileToken);
assert.equal(last!.kind, SyntaxKind.EndOfFileToken);
});
});
});
+9 -12
View File
@@ -1,7 +1,7 @@
/// <reference path="..\harness.ts" />
namespace ts {
export function checkResolvedModule(expected: ResolvedModuleFull, actual: ResolvedModuleFull): boolean {
export function checkResolvedModule(expected: ResolvedModuleFull | undefined, actual: ResolvedModuleFull): boolean {
if (!expected === !actual) {
if (expected) {
assert.isTrue(expected.resolvedFileName === actual.resolvedFileName, `'resolvedFileName': expected '${expected.resolvedFileName}' to be equal to '${actual.resolvedFileName}'`);
@@ -71,7 +71,7 @@ namespace ts {
return file && file.content;
}
function realpath(path: string): string {
return map.get(path).name;
return map.get(path)!.name;
}
}
@@ -332,7 +332,7 @@ namespace ts {
getSourceFile: (fileName: string, languageVersion: ScriptTarget) => {
const path = normalizePath(combinePaths(currentDirectory, fileName));
const file = files.get(path);
return file && createSourceFile(fileName, file, languageVersion);
return file ? createSourceFile(fileName, file, languageVersion) : undefined;
},
getDefaultLibFileName: () => "lib.d.ts",
writeFile: notImplemented,
@@ -420,7 +420,7 @@ export = C;
}
const path = getCanonicalFileName(normalizePath(combinePaths(currentDirectory, fileName)));
const file = files.get(path);
return file && createSourceFile(fileName, file, languageVersion);
return file ? createSourceFile(fileName, file, languageVersion) : undefined;
},
getDefaultLibFileName: () => "lib.d.ts",
writeFile: notImplemented,
@@ -975,9 +975,9 @@ import b = require("./moduleB");
function test(typesRoot: string, typeDirective: string, primary: boolean, initialFile: File, targetFile: File, ...otherFiles: File[]) {
const host = createModuleResolutionHost(/*hasDirectoryExists*/ false, ...[initialFile, targetFile].concat(...otherFiles));
const result = resolveTypeReferenceDirective(typeDirective, initialFile.name, { typeRoots: [typesRoot] }, host);
assert(result.resolvedTypeReferenceDirective.resolvedFileName !== undefined, "expected type directive to be resolved");
assert.equal(result.resolvedTypeReferenceDirective.resolvedFileName, targetFile.name, "unexpected result of type reference resolution");
assert.equal(result.resolvedTypeReferenceDirective.primary, primary, "unexpected 'primary' value");
assert(result.resolvedTypeReferenceDirective!.resolvedFileName !== undefined, "expected type directive to be resolved");
assert.equal(result.resolvedTypeReferenceDirective!.resolvedFileName, targetFile.name, "unexpected result of type reference resolution");
assert.equal(result.resolvedTypeReferenceDirective!.primary, primary, "unexpected 'primary' value");
}
it("Can be resolved from primary location", () => {
@@ -1111,10 +1111,7 @@ import b = require("./moduleB");
getNewLine: () => "\r\n",
useCaseSensitiveFileNames: () => false,
readFile: fileName => fileName === file.fileName ? file.text : undefined,
resolveModuleNames() {
assert(false, "resolveModuleNames should not be called");
return undefined;
}
resolveModuleNames: notImplemented,
};
createProgram([f.name], {}, compilerHost);
});
@@ -1145,7 +1142,7 @@ import b = require("./moduleB");
readFile: fileName => fileName === file.fileName ? file.text : undefined,
resolveModuleNames(moduleNames: string[], _containingFile: string) {
assert.deepEqual(moduleNames, ["fs"]);
return [undefined];
return [undefined!]; // TODO: GH#18217
}
};
createProgram([f.name], {}, compilerHost);
+6 -6
View File
@@ -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);
}
});
});
+1 -1
View File
@@ -77,7 +77,7 @@ namespace ts {
}
}
const vfsys = new vfs.FileSystem(false, { files: { "/lib.d.ts": TestFSWithWatch.libFile.content! } });
const vfsys = new vfs.FileSystem(false, { files: { "/lib.d.ts": TestFSWithWatch.libFile.content } });
files.forEach((v, k) => {
vfsys.mkdirpSync(getDirectoryPath(k));
vfsys.writeFileSync(k, v);
+1 -1
View File
@@ -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", () => {
+15 -15
View File
@@ -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 = <ProgramWithSourceTexts>createProgram(rootNames, options, host);
program.sourceTexts = texts;
program.host = host;
@@ -165,10 +165,10 @@ namespace ts {
export function updateProgram(oldProgram: ProgramWithSourceTexts, rootNames: ReadonlyArray<string>, 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 = <ProgramWithSourceTexts>createProgram(rootNames, options, host, oldProgram);
program.sourceTexts = newTexts;
program.host = host;
@@ -191,16 +191,16 @@ namespace ts {
return false;
}
function checkCache<T>(caption: string, program: Program, fileName: string, expectedContent: Map<T>, getCache: (f: SourceFile) => Map<T>, entryChecker: (expected: T, original: T) => boolean): void {
function checkCache<T>(caption: string, program: Program, fileName: string, expectedContent: Map<T> | undefined, getCache: (f: SourceFile) => Map<T> | 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<ResolvedModule>): void {
function checkResolvedModulesCache(program: Program, fileName: string, expectedContent: Map<ResolvedModule | undefined> | undefined): void {
checkCache("resolved modules", program, fileName, expectedContent, f => f.resolvedModules, checkResolvedModule);
}
function checkResolvedTypeDirectivesCache(program: Program, fileName: string, expectedContent: Map<ResolvedTypeReferenceDirective>): void {
function checkResolvedTypeDirectivesCache(program: Program, fileName: string, expectedContent: Map<ResolvedTypeReferenceDirective> | 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);
}
@@ -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);
}
});
@@ -321,7 +321,7 @@ describe("PatternMatcher", () => {
});
function assertSegmentMatch(candidate: string, pattern: string, expected: ts.PatternMatch | undefined): void {
assert.deepEqual(ts.createPatternMatcher(pattern).getMatchForLastSegmentOfPattern(candidate), expected);
assert.deepEqual(ts.createPatternMatcher(pattern)!.getMatchForLastSegmentOfPattern(candidate), expected);
}
function assertInvalidPattern(pattern: string) {
@@ -329,7 +329,7 @@ describe("PatternMatcher", () => {
}
function assertFullMatch(dottedContainer: string, candidate: string, pattern: string, expected: ts.PatternMatch | undefined): void {
assert.deepEqual(ts.createPatternMatcher(pattern).getFullMatch(dottedContainer.split("."), candidate), expected);
assert.deepEqual(ts.createPatternMatcher(pattern)!.getFullMatch(dottedContainer.split("."), candidate), expected);
}
function spanListToSubstrings(identifier: string, spans: ts.TextSpan[]) {
+8 -8
View File
@@ -12,7 +12,7 @@ namespace ts.server {
write(s): void { lastWrittenToHost = s; },
readFile: () => undefined,
writeFile: noop,
resolvePath(): string { return void 0; },
resolvePath(): string { return undefined!; }, // TODO: GH#18217
fileExists: () => false,
directoryExists: () => false,
getDirectories: () => [],
@@ -47,7 +47,7 @@ namespace ts.server {
cancellationToken: nullCancellationToken,
useSingleInferredProject: false,
useInferredProjectPerProjectRoot: false,
typingsInstaller: undefined,
typingsInstaller: undefined!, // TODO: GH#18217
byteLength: Utils.byteLength,
hrtime: process.hrtime,
logger: projectSystem.nullLogger,
@@ -81,7 +81,7 @@ namespace ts.server {
seq: 0,
type: "request",
arguments: {
file: undefined
file: undefined! // TODO: GH#18217
}
};
@@ -441,7 +441,7 @@ namespace ts.server {
lastSent: protocol.Message;
private exceptionRaisingHandler(_request: protocol.Request): { response?: any, responseRequired: boolean } {
f1();
return;
return Debug.fail(); // unreachable, throw to make compiler happy
function f1() {
throw new Error("myMessage");
}
@@ -453,7 +453,7 @@ namespace ts.server {
cancellationToken: nullCancellationToken,
useSingleInferredProject: false,
useInferredProjectPerProjectRoot: false,
typingsInstaller: undefined,
typingsInstaller: undefined!, // TODO: GH#18217
byteLength: Utils.byteLength,
hrtime: process.hrtime,
logger: projectSystem.nullLogger,
@@ -500,7 +500,7 @@ namespace ts.server {
cancellationToken: nullCancellationToken,
useSingleInferredProject: false,
useInferredProjectPerProjectRoot: false,
typingsInstaller: undefined,
typingsInstaller: undefined!, // TODO: GH#18217
byteLength: Utils.byteLength,
hrtime: process.hrtime,
logger: projectSystem.nullLogger,
@@ -568,7 +568,7 @@ namespace ts.server {
cancellationToken: nullCancellationToken,
useSingleInferredProject: false,
useInferredProjectPerProjectRoot: false,
typingsInstaller: undefined,
typingsInstaller: undefined!, // TODO: GH#18217
byteLength: Utils.byteLength,
hrtime: process.hrtime,
logger: projectSystem.nullLogger,
@@ -604,7 +604,7 @@ namespace ts.server {
consumeQueue() {
while (this.queue.length > 0) {
const elem = this.queue.pop();
const elem = this.queue.pop()!;
this.handleRequest(elem);
}
}
+2 -2
View File
@@ -8,8 +8,8 @@ namespace ts {
unitName: "main.ts",
content: source
}], [], {}, {}, "/");
const file = result.program.getSourceFile("main.ts");
const checker = result.program.getTypeChecker();
const file = result.program!.getSourceFile("main.ts")!;
const checker = result.program!.getTypeChecker();
verifier(file, checker);
});
}
+5 -5
View File
@@ -8,9 +8,9 @@
namespace ts {
describe("textChanges", () => {
function findChild(name: string, n: Node) {
return find(n);
return find(n)!;
function find(node: Node): Node {
function find(node: Node): Node | undefined {
if (isDeclaration(node) && node.name && isIdentifier(node.name) && node.name.escapedText === name) {
return node;
}
@@ -88,7 +88,7 @@ namespace M
}
}`;
runSingleFileTest("extractMethodLike", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
const statements = (<FunctionDeclaration>findChild("foo", sourceFile)).body.statements.slice(1);
const statements = (<FunctionDeclaration>findChild("foo", sourceFile)).body!.statements.slice(1);
const newFunction = createFunctionDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
@@ -105,11 +105,11 @@ namespace M
// replace statements with return statement
const newStatement = createReturn(
createCall(
/*expression*/ newFunction.name,
/*expression*/ newFunction.name!,
/*typeArguments*/ undefined,
/*argumentsArray*/ emptyArray
));
changeTracker.replaceNodeRange(sourceFile, statements[0], lastOrUndefined(statements), newStatement, { suffix: newLineCharacter });
changeTracker.replaceNodeRange(sourceFile, statements[0], last(statements), newStatement, { suffix: newLineCharacter });
});
}
{
+2 -2
View File
@@ -139,7 +139,7 @@ namespace ts {
return (sourceFile: SourceFile) => {
const result = getMutableClone(sourceFile);
result.statements = createNodeArray([
createClassDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, "Foo", /*typeParameters*/ undefined, /*heritageClauses*/ undefined, /*members*/ undefined),
createClassDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, "Foo", /*typeParameters*/ undefined, /*heritageClauses*/ undefined, /*members*/ undefined!), // TODO: GH#18217
createModuleDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createIdentifier("Foo"), createModuleBlock([createEmptyStatement()]))
]);
return result;
@@ -266,7 +266,7 @@ namespace ts {
function baselineDeclarationTransform(text: string, opts: TranspileOptions) {
const fs = vfs.createFromFileSystem(Harness.IO, /*caseSensitive*/ true, { documents: [new documents.TextDocument("/.src/index.ts", text)] });
const host = new fakes.CompilerHost(fs, opts.compilerOptions);
const program = createProgram(["/.src/index.ts"], opts.compilerOptions, host);
const program = createProgram(["/.src/index.ts"], opts.compilerOptions!, host);
program.emit(program.getSourceFiles()[1], (p, s, bom) => host.writeFile(p, s, bom), /*cancellationToken*/ undefined, /*onlyDts*/ true, opts.transformers);
return fs.readFileSync("/.src/index.d.ts").toString();
}
+5 -5
View File
@@ -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!);
});
});
+13 -13
View File
@@ -171,7 +171,7 @@ namespace ts.tscWatch {
assert.equal(host.exitCode, expectedExitCode);
}
function getDiagnosticOfFileFrom(file: SourceFile, text: string, start: number, length: number, message: DiagnosticMessage): Diagnostic {
function getDiagnosticOfFileFrom(file: SourceFile | undefined, text: string, start: number | undefined, length: number | undefined, message: DiagnosticMessage): Diagnostic {
return {
file,
start,
@@ -205,7 +205,7 @@ namespace ts.tscWatch {
function getUnknownCompilerOption(program: Program, configFile: File, option: string) {
const quotedOption = `"${option}"`;
return getDiagnosticOfFile(program.getCompilerOptions().configFile, configFile.content.indexOf(quotedOption), quotedOption.length, Diagnostics.Unknown_compiler_option_0, option);
return getDiagnosticOfFile(program.getCompilerOptions().configFile!, configFile.content.indexOf(quotedOption), quotedOption.length, Diagnostics.Unknown_compiler_option_0, option);
}
function getDiagnosticOfFileFromProgram(program: Program, filePath: string, start: number, length: number, message: DiagnosticMessage, ..._args: (string | number)[]): Diagnostic {
@@ -215,7 +215,7 @@ namespace ts.tscWatch {
text = formatStringFromArgs(text, arguments, 5);
}
return getDiagnosticOfFileFrom(program.getSourceFileByPath(toPath(filePath, program.getCurrentDirectory(), s => s.toLowerCase())),
return getDiagnosticOfFileFrom(program.getSourceFileByPath(toPath(filePath, program.getCurrentDirectory(), s => s.toLowerCase()))!,
text, start, length, message);
}
@@ -1101,8 +1101,8 @@ namespace ts.tscWatch {
const host = createWatchedSystem(files);
const watch = createWatchOfConfigFile(configFile.path, host);
const errors = () => [
getDiagnosticOfFile(watch().getCompilerOptions().configFile, configFile.content.indexOf('"allowJs"'), '"allowJs"'.length, Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", "declaration"),
getDiagnosticOfFile(watch().getCompilerOptions().configFile, configFile.content.indexOf('"declaration"'), '"declaration"'.length, Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", "declaration")
getDiagnosticOfFile(watch().getCompilerOptions().configFile!, configFile.content.indexOf('"allowJs"'), '"allowJs"'.length, Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", "declaration"),
getDiagnosticOfFile(watch().getCompilerOptions().configFile!, configFile.content.indexOf('"declaration"'), '"declaration"'.length, Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", "declaration")
];
const intialErrors = errors();
checkOutputErrorsInitial(host, intialErrors);
@@ -1112,8 +1112,8 @@ namespace ts.tscWatch {
host.runQueuedTimeoutCallbacks();
const nowErrors = errors();
checkOutputErrorsIncremental(host, nowErrors);
assert.equal(nowErrors[0].start, intialErrors[0].start - configFileContentComment.length);
assert.equal(nowErrors[1].start, intialErrors[1].start - configFileContentComment.length);
assert.equal(nowErrors[0].start, intialErrors[0].start! - configFileContentComment.length);
assert.equal(nowErrors[1].start, intialErrors[1].start! - configFileContentComment.length);
});
it("should not trigger recompilation because of program emit", () => {
@@ -1409,7 +1409,7 @@ namespace ts.tscWatch {
}
function getFile(fileName: string) {
return find(files, file => file.path === fileName);
return find(files, file => file.path === fileName)!;
}
function verifyAffectedAllFiles() {
@@ -2252,7 +2252,7 @@ declare module "fs" {
const disableConsoleClear = options.diagnostics || options.extendedDiagnostics || options.preserveWatchOutput;
const host = createWatchedSystem(files);
createWatchOfFilesAndCompilerOptions([file.path], host, options);
checkOutputErrorsInitial(host, emptyArray, disableConsoleClear, options.extendedDiagnostics && [
checkOutputErrorsInitial(host, emptyArray, disableConsoleClear, options.extendedDiagnostics ? [
"Current directory: / CaseSensitiveFileNames: false\n",
"Synchronizing program\n",
"CreatingProgramWith::\n",
@@ -2260,21 +2260,21 @@ declare module "fs" {
" options: {\"extendedDiagnostics\":true}\n",
"FileWatcher:: Added:: WatchInfo: f.ts 250 Source file\n",
"FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 250 Source file\n"
]);
] : undefined);
file.content = "//";
host.reloadFS(files);
host.runQueuedTimeoutCallbacks();
checkOutputErrorsIncremental(host, emptyArray, disableConsoleClear, options.extendedDiagnostics && [
checkOutputErrorsIncremental(host, emptyArray, disableConsoleClear, options.extendedDiagnostics ? [
"FileWatcher:: Triggered with /f.ts1:: WatchInfo: f.ts 250 Source file\n",
"Scheduling update\n",
"Elapsed:: 0ms FileWatcher:: Triggered with /f.ts1:: WatchInfo: f.ts 250 Source file\n"
], options.extendedDiagnostics && [
] : undefined, options.extendedDiagnostics ? [
"Synchronizing program\n",
"CreatingProgramWith::\n",
" roots: [\"f.ts\"]\n",
" options: {\"extendedDiagnostics\":true}\n"
]);
] : undefined);
}
it("without --diagnostics or --extendedDiagnostics", () => {
+6 -5
View File
@@ -135,11 +135,12 @@ namespace ts {
const parsed = parseConfigFileTextToJson("/apath/tsconfig.json", "invalid");
assert.deepEqual(parsed.config, { invalid: undefined });
const expected = createCompilerDiagnostic(Diagnostics._0_expected, "{");
assert.equal(parsed.error.messageText, expected.messageText);
assert.equal(parsed.error.category, expected.category);
assert.equal(parsed.error.code, expected.code);
assert.equal(parsed.error.start, 0);
assert.equal(parsed.error.length, "invalid".length);
const error = parsed.error!;
assert.equal(error.messageText, expected.messageText);
assert.equal(error.category, expected.category);
assert.equal(error.code, expected.code);
assert.equal(error.start, 0);
assert.equal(error.length, "invalid".length);
});
it("returns object when users correctly specify library", () => {
+80 -84
View File
@@ -58,7 +58,7 @@ namespace ts.projectSystem {
msg: noop,
startGroup: noop,
endGroup: noop,
getLogFileName: (): string => undefined
getLogFileName: () => undefined,
};
export class TestTypingsInstaller extends TI.TypingsInstaller implements server.ITypingsInstaller {
@@ -189,7 +189,7 @@ namespace ts.projectSystem {
}
getEvent<T extends server.ProjectServiceEvent>(eventName: T["eventName"]): T["data"] {
let eventData: T["data"];
let eventData: T["data"] | undefined;
filterMutate(this.events, e => {
if (e.eventName === eventName) {
if (eventData !== undefined) {
@@ -200,8 +200,7 @@ namespace ts.projectSystem {
}
return true;
});
assert.isDefined(eventData);
return eventData;
return Debug.assertDefined(eventData);
}
hasZeroEvent<T extends server.ProjectServiceEvent>(eventName: T["eventName"]) {
@@ -216,7 +215,7 @@ namespace ts.projectSystem {
assertProjectInfoTelemetryEvent(partial: Partial<server.ProjectInfoTelemetryEventData>, configFile = "/tsconfig.json"): void {
assert.deepEqual<server.ProjectInfoTelemetryEventData>(this.getEvent<server.ProjectInfoTelemetryEvent>(server.ProjectInfoTelemetryEvent), {
projectId: sys.createSHA256Hash(configFile),
projectId: sys.createSHA256Hash!(configFile),
fileStats: fileStats({ ts: 1 }),
compilerOptions: {},
extends: false,
@@ -294,7 +293,7 @@ namespace ts.projectSystem {
cancellationToken: server.nullCancellationToken,
useSingleInferredProject: false,
useInferredProjectPerProjectRoot: false,
typingsInstaller: undefined,
typingsInstaller: undefined!, // TODO: GH#18217
byteLength: Utils.byteLength,
hrtime: process.hrtime,
logger: opts.logger || nullLogger,
@@ -336,7 +335,7 @@ namespace ts.projectSystem {
const cancellationToken = parameters.cancellationToken || server.nullCancellationToken;
const logger = parameters.logger || nullLogger;
const useSingleInferredProject = parameters.useSingleInferredProject !== undefined ? parameters.useSingleInferredProject : false;
return new TestProjectService(host, logger, cancellationToken, useSingleInferredProject, parameters.typingsInstaller, parameters.eventHandler, options);
return new TestProjectService(host, logger, cancellationToken, useSingleInferredProject, parameters.typingsInstaller!, parameters.eventHandler!, options); // TODO: GH#18217
}
export function checkNumberOfConfiguredProjects(projectService: server.ProjectService, expected: number) {
@@ -404,7 +403,7 @@ namespace ts.projectSystem {
}
function checkOpenFiles(projectService: server.ProjectService, expectedFiles: File[]) {
checkArray("Open files", arrayFrom(projectService.openFiles.keys(), path => projectService.getScriptInfoForPath(path as Path).fileName), expectedFiles.map(file => file.path));
checkArray("Open files", arrayFrom(projectService.openFiles.keys(), path => projectService.getScriptInfoForPath(path as Path)!.fileName), expectedFiles.map(file => file.path));
}
function textSpanFromSubstring(str: string, substring: string): TextSpan {
@@ -420,7 +419,7 @@ namespace ts.projectSystem {
* setRequestToCancel();
*/
export class TestServerCancellationToken implements server.ServerCancellationToken {
private currentId = -1;
private currentId: number | undefined = -1;
private requestToCancel = -1;
private isCancellationRequestedCount = 0;
@@ -708,7 +707,7 @@ namespace ts.projectSystem {
projectService.checkNumberOfProjects({ inferredProjects: 2, configuredProjects: 1 });
assert.isTrue(projectService.inferredProjects[0].isOrphan());
checkProjectActualFiles(projectService.inferredProjects[1], [commonFile2.path, libFile.path]);
checkProjectActualFiles(projectService.configuredProjects.get(configFile.path), [libFile.path, commonFile1.path, configFile.path]);
checkProjectActualFiles(projectService.configuredProjects.get(configFile.path)!, [libFile.path, commonFile1.path, configFile.path]);
checkWatchedFiles(host, watchedFiles);
@@ -1106,15 +1105,15 @@ namespace ts.projectSystem {
const projectService = createProjectService(host);
projectService.openExternalProject({ rootFiles: toExternalFiles([file1.path]), options: {}, projectFileName: proj1name });
const proj1 = projectService.findProject(proj1name);
const proj1 = projectService.findProject(proj1name)!;
assert.isTrue(proj1.languageServiceEnabled);
projectService.openExternalProject({ rootFiles: toExternalFiles([file2.path]), options: {}, projectFileName: proj2name });
const proj2 = projectService.findProject(proj2name);
const proj2 = projectService.findProject(proj2name)!;
assert.isTrue(proj2.languageServiceEnabled);
projectService.openExternalProject({ rootFiles: toExternalFiles([file3.path]), options: {}, projectFileName: proj3name });
const proj3 = projectService.findProject(proj3name);
const proj3 = projectService.findProject(proj3name)!;
assert.isFalse(proj3.languageServiceEnabled);
});
@@ -1182,7 +1181,7 @@ namespace ts.projectSystem {
const projectService = createProjectService(host, { useSingleInferredProject: true });
projectService.openClientFile(file1.path);
checkNumberOfConfiguredProjects(projectService, 1);
const project = projectService.configuredProjects.get(configFile.path);
const project = projectService.configuredProjects.get(configFile.path)!;
assert.isTrue(project.hasOpenRef()); // file1
projectService.closeClientFile(file1.path);
@@ -1216,7 +1215,7 @@ namespace ts.projectSystem {
const projectService = createProjectService(host, { useSingleInferredProject: true });
projectService.openClientFile(file1.path);
checkNumberOfConfiguredProjects(projectService, 1);
const project = projectService.configuredProjects.get(configFile.path);
const project = projectService.configuredProjects.get(configFile.path)!;
assert.isTrue(project.hasOpenRef()); // file1
projectService.closeClientFile(file1.path);
@@ -1489,13 +1488,13 @@ namespace ts.projectSystem {
service.checkNumberOfProjects({ externalProjects: 1 });
checkProjectActualFiles(service.externalProjects[0], [f1.path, f2.path, libFile.path]);
const completions1 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 2, defaultPreferences);
const completions1 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 2, defaultPreferences)!;
// should contain completions for string
assert.isTrue(completions1.entries.some(e => e.name === "charAt"), "should contain 'charAt'");
assert.isFalse(completions1.entries.some(e => e.name === "toExponential"), "should not contain 'toExponential'");
service.closeClientFile(f2.path);
const completions2 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 2, defaultPreferences);
const completions2 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 2, defaultPreferences)!;
// should contain completions for string
assert.isFalse(completions2.entries.some(e => e.name === "charAt"), "should not contain 'charAt'");
assert.isTrue(completions2.entries.some(e => e.name === "toExponential"), "should contain 'toExponential'");
@@ -1521,13 +1520,13 @@ namespace ts.projectSystem {
service.checkNumberOfProjects({ externalProjects: 1 });
checkProjectActualFiles(service.externalProjects[0], [f1.path, f2.path, libFile.path]);
const completions1 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 0, defaultPreferences);
const completions1 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 0, defaultPreferences)!;
assert.isTrue(completions1.entries.some(e => e.name === "somelongname"), "should contain 'somelongname'");
service.closeClientFile(f2.path);
const completions2 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 0, defaultPreferences);
const completions2 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 0, defaultPreferences)!;
assert.isFalse(completions2.entries.some(e => e.name === "somelongname"), "should not contain 'somelongname'");
const sf2 = service.externalProjects[0].getLanguageService().getProgram().getSourceFile(f2.path);
const sf2 = service.externalProjects[0].getLanguageService().getProgram()!.getSourceFile(f2.path)!;
assert.equal(sf2.text, "");
});
@@ -2048,8 +2047,8 @@ namespace ts.projectSystem {
const projectService = createProjectService(host);
projectService.applyChangesInOpenFiles([tsFile], [], []);
const projs = projectService.synchronizeProjectList([]);
projectService.findProject(projs[0].info.projectName).getLanguageService().getNavigationBarItems(tsFile.fileName);
projectService.synchronizeProjectList([projs[0].info]);
projectService.findProject(projs[0].info!.projectName)!.getLanguageService().getNavigationBarItems(tsFile.fileName);
projectService.synchronizeProjectList([projs[0].info!]);
projectService.applyChangesInOpenFiles([jsFile], [], []);
});
@@ -2333,7 +2332,7 @@ namespace ts.projectSystem {
const project = projectService.externalProjects[0];
const scriptInfo = project.getScriptInfo(file1.path);
const scriptInfo = project.getScriptInfo(file1.path)!;
const snap = scriptInfo.getSnapshot();
const actualText = getSnapshotText(snap);
assert.equal(actualText, "", `expected content to be empty string, got "${actualText}"`);
@@ -2341,12 +2340,12 @@ namespace ts.projectSystem {
projectService.openClientFile(file1.path, `var x = 1;`);
project.updateGraph();
const quickInfo = project.getLanguageService().getQuickInfoAtPosition(file1.path, 4);
const quickInfo = project.getLanguageService().getQuickInfoAtPosition(file1.path, 4)!;
assert.equal(quickInfo.kind, ScriptElementKind.variableElement);
projectService.closeClientFile(file1.path);
const scriptInfo2 = project.getScriptInfo(file1.path);
const scriptInfo2 = project.getScriptInfo(file1.path)!;
const actualText2 = getSnapshotText(scriptInfo2.getSnapshot());
assert.equal(actualText2, "", `expected content to be empty string, got "${actualText2}"`);
});
@@ -2391,7 +2390,7 @@ namespace ts.projectSystem {
projectService.openClientFile(file1.path);
projectService.inferredProjects[0].getLanguageService(/*ensureSynchronized*/ false).getOutliningSpans(file1.path);
projectService.setCompilerOptionsForInferredProjects({ target: ScriptTarget.ES5, allowJs: true });
projectService.getScriptInfo(file1.path).editContent(0, 0, " ");
projectService.getScriptInfo(file1.path)!.editContent(0, 0, " ");
projectService.inferredProjects[0].getLanguageService(/*ensureSynchronized*/ false).getOutliningSpans(file1.path);
projectService.closeClientFile(file1.path);
});
@@ -2418,9 +2417,9 @@ namespace ts.projectSystem {
projectService.openClientFile(file2.path);
checkNumberOfProjects(projectService, { configuredProjects: 1 });
const project1 = projectService.configuredProjects.get(tsconfig1.path);
const project1 = projectService.configuredProjects.get(tsconfig1.path)!;
assert.isTrue(project1.hasOpenRef(), "Has open ref count in project1 - 1"); // file2
assert.equal(project1.getScriptInfo(file2.path).containingProjects.length, 1, "containing projects count");
assert.equal(project1.getScriptInfo(file2.path)!.containingProjects.length, 1, "containing projects count");
assert.isFalse(project1.isClosed());
projectService.openClientFile(file1.path);
@@ -2429,12 +2428,12 @@ namespace ts.projectSystem {
assert.strictEqual(projectService.configuredProjects.get(tsconfig1.path), project1);
assert.isFalse(project1.isClosed());
const project2 = projectService.configuredProjects.get(tsconfig2.path);
const project2 = projectService.configuredProjects.get(tsconfig2.path)!;
assert.isTrue(project2.hasOpenRef(), "Has open ref count in project2 - 2"); // file1
assert.isFalse(project2.isClosed());
assert.equal(project1.getScriptInfo(file1.path).containingProjects.length, 2, `${file1.path} containing projects count`);
assert.equal(project1.getScriptInfo(file2.path).containingProjects.length, 1, `${file2.path} containing projects count`);
assert.equal(project1.getScriptInfo(file1.path)!.containingProjects.length, 2, `${file1.path} containing projects count`);
assert.equal(project1.getScriptInfo(file2.path)!.containingProjects.length, 1, `${file2.path} containing projects count`);
projectService.closeClientFile(file2.path);
checkNumberOfProjects(projectService, { configuredProjects: 2 });
@@ -2494,10 +2493,10 @@ namespace ts.projectSystem {
projectService.openClientFile(file3.path);
projectService.openClientFile(file4.path);
const infos = files.map(file => projectService.getScriptInfoForPath(file.path as Path));
const infos = files.map(file => projectService.getScriptInfoForPath(file.path as Path)!);
checkOpenFiles(projectService, files);
checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 2 });
const configProject1 = projectService.configuredProjects.get(configFile.path);
const configProject1 = projectService.configuredProjects.get(configFile.path)!;
assert.isTrue(configProject1.hasOpenRef()); // file1 and file3
checkProjectActualFiles(configProject1, [file1.path, file3.path, configFile.path]);
const inferredProject1 = projectService.inferredProjects[0];
@@ -2568,7 +2567,7 @@ namespace ts.projectSystem {
function verifyConfiguredProjectStateAfterUpdate(hasOpenRef: boolean, inferredProjects: number) {
checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects });
const configProject2 = projectService.configuredProjects.get(configFile.path);
const configProject2 = projectService.configuredProjects.get(configFile.path)!;
assert.strictEqual(configProject2, configProject1);
checkProjectActualFiles(configProject2, [file1.path, file2.path, file3.path, configFile.path]);
assert.equal(configProject2.hasOpenRef(), hasOpenRef);
@@ -2607,7 +2606,7 @@ namespace ts.projectSystem {
projectService.openClientFile(file3.path);
checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 1 });
const configuredProject = projectService.configuredProjects.get(configFile.path);
const configuredProject = projectService.configuredProjects.get(configFile.path)!;
assert.isTrue(configuredProject.hasOpenRef()); // file1 and file3
checkProjectActualFiles(configuredProject, [file1.path, file3.path, configFile.path]);
const inferredProject1 = projectService.inferredProjects[0];
@@ -2709,7 +2708,7 @@ namespace ts.projectSystem {
const projectService = createProjectService(host);
projectService.openClientFile(f1.path);
projectService.checkNumberOfProjects({ configuredProjects: 1 });
const project = projectService.configuredProjects.get(config.path);
const project = projectService.configuredProjects.get(config.path)!;
assert.isTrue(project.hasOpenRef()); // f1
assert.isFalse(project.isClosed());
@@ -2721,7 +2720,7 @@ namespace ts.projectSystem {
for (const f of [f1, f2, f3]) {
// All the script infos should be present and contain the project since it is still alive.
const scriptInfo = projectService.getScriptInfoForNormalizedPath(server.toNormalizedPath(f.path));
const scriptInfo = projectService.getScriptInfoForNormalizedPath(server.toNormalizedPath(f.path))!;
assert.equal(scriptInfo.containingProjects.length, 1, `expect 1 containing projects for '${f.path}'`);
assert.equal(scriptInfo.containingProjects[0], project, `expect configured project to be the only containing project for '${f.path}'`);
}
@@ -2764,7 +2763,7 @@ namespace ts.projectSystem {
host.getFileSize = (filePath: string) =>
filePath === f2.path ? server.maxProgramSizeForNonTsFiles + 1 : originalGetFileSize.call(host, filePath);
let lastEvent: server.ProjectLanguageServiceStateEvent;
let lastEvent!: server.ProjectLanguageServiceStateEvent;
const session = createSession(host, {
canUseEvents: true,
eventHandler: e => {
@@ -2816,7 +2815,7 @@ namespace ts.projectSystem {
const originalGetFileSize = host.getFileSize;
host.getFileSize = (filePath: string) =>
filePath === f2.path ? server.maxProgramSizeForNonTsFiles + 1 : originalGetFileSize.call(host, filePath);
let lastEvent: server.ProjectLanguageServiceStateEvent;
let lastEvent!: server.ProjectLanguageServiceStateEvent;
const session = createSession(host, {
canUseEvents: true,
eventHandler: e => {
@@ -2906,7 +2905,7 @@ namespace ts.projectSystem {
host.reloadFS([libFile, site]);
host.checkTimeoutQueueLengthAndRun(1);
knownProjects = projectService.synchronizeProjectList(map(knownProjects, proj => proj.info));
knownProjects = projectService.synchronizeProjectList(map(knownProjects, proj => proj.info!)); // TODO: GH#18217 GH#20039
checkNumberOfProjects(projectService, { configuredProjects: 0, externalProjects: 0, inferredProjects: 0 });
externalProject.rootFiles.length = 1;
@@ -2979,7 +2978,7 @@ namespace ts.projectSystem {
const projectService = createProjectService(host);
projectService.openClientFile(file1.path);
checkNumberOfProjects(projectService, { configuredProjects: 1 });
const project = projectService.configuredProjects.get(configFile.path);
const project = projectService.configuredProjects.get(configFile.path)!;
assert.isDefined(project);
checkProjectActualFiles(project, map(files, file => file.path));
checkWatchedFiles(host, mapDefined(files, file => file === file1 ? undefined : file.path));
@@ -3040,7 +3039,7 @@ namespace ts.projectSystem {
const projectService = createProjectService(host);
projectService.openClientFile(file1.path);
checkNumberOfProjects(projectService, { configuredProjects: 1 });
const project = projectService.configuredProjects.get(configFile.path);
const project = projectService.configuredProjects.get(configFile.path)!;
assert.isDefined(project);
checkProjectActualFiles(project, [file1.path, libFile.path, module1.path, module2.path, configFile.path]);
checkWatchedFiles(host, [libFile.path, module1.path, module2.path, configFile.path]);
@@ -3145,7 +3144,7 @@ namespace ts.projectSystem {
});
const projectService = session.getProjectService();
const configuredProject = projectService.configuredProjects.get(config.path);
const configuredProject = projectService.configuredProjects.get(config.path)!;
verifyConfiguredProject();
// open files/file1 = should not create another project
@@ -3296,7 +3295,7 @@ namespace ts.projectSystem {
const host = createServerHost(files);
const service = createProjectService(host);
service.openClientFile(file1.path);
checkProjectActualFiles(service.configuredProjects.get(config.path), [file1.path, file2.path, libFile.path, config.path]);
checkProjectActualFiles(service.configuredProjects.get(config.path)!, [file1.path, file2.path, libFile.path, config.path]);
const configContent2 = JSON.stringify({
files: ["src/file1.ts"]
@@ -3305,19 +3304,18 @@ namespace ts.projectSystem {
host.reloadFS(files);
host.runQueuedTimeoutCallbacks();
checkProjectActualFiles(service.configuredProjects.get(config.path), [file1.path, libFile.path, config.path]);
checkProjectActualFiles(service.configuredProjects.get(config.path)!, [file1.path, libFile.path, config.path]);
verifyFile2InfoIsOrphan();
file2.content += "export let z = 10;";
host.reloadFS(files);
host.runQueuedTimeoutCallbacks();
checkProjectActualFiles(service.configuredProjects.get(config.path), [file1.path, libFile.path, config.path]);
checkProjectActualFiles(service.configuredProjects.get(config.path)!, [file1.path, libFile.path, config.path]);
verifyFile2InfoIsOrphan();
function verifyFile2InfoIsOrphan() {
const info = service.getScriptInfoForPath(file2.path as Path);
assert.isDefined(info);
const info = Debug.assertDefined(service.getScriptInfoForPath(file2.path as Path));
assert.equal(info.containingProjects.length, 0);
}
});
@@ -3339,7 +3337,7 @@ namespace ts.projectSystem {
},
startGroup: noop,
endGroup: noop,
getLogFileName: (): string => undefined
getLogFileName: () => undefined
};
return {
errorLogger,
@@ -3362,7 +3360,7 @@ namespace ts.projectSystem {
projectService.openClientFile(file1.path);
projectService.checkNumberOfProjects({ configuredProjects: 1 });
const project = projectService.findProject(corruptedConfig.path);
const project = projectService.findProject(corruptedConfig.path)!;
checkProjectRootFiles(project, [file1.path]);
});
@@ -3904,7 +3902,7 @@ namespace ts.projectSystem {
const projectService = createProjectService(host);
projectService.openClientFile(f.path);
projectService.checkNumberOfProjects({ configuredProjects: 1 });
const project = projectService.configuredProjects.get(config.path);
const project = projectService.configuredProjects.get(config.path)!;
assert.isTrue(project.hasOpenRef()); // f
projectService.closeClientFile(f.path);
@@ -4053,7 +4051,7 @@ namespace ts.projectSystem {
// force to load the content of the file
p.updateGraph();
const scriptInfo = p.getScriptInfo(f.path);
const scriptInfo = p.getScriptInfo(f.path)!;
checkSnapLength(scriptInfo.getSnapshot(), f.content.length);
// open project and replace its content with empty string
@@ -4137,7 +4135,7 @@ namespace ts.projectSystem {
function verifyProject() {
assert.isDefined(service.configuredProjects.get(configFile.path));
const project = service.configuredProjects.get(configFile.path);
const project = service.configuredProjects.get(configFile.path)!;
checkProjectActualFiles(project, files.map(f => f.path));
}
});
@@ -5037,7 +5035,7 @@ namespace ts.projectSystem {
// verify content
const projectServiice = session.getProjectService();
const snap1 = projectServiice.getScriptInfo(f1.path).getSnapshot();
const snap1 = projectServiice.getScriptInfo(f1.path)!.getSnapshot();
assert.equal(getSnapshotText(snap1), tmp.content, "content should be equal to the content of temp file");
// reload from original file file
@@ -5049,7 +5047,7 @@ namespace ts.projectSystem {
});
// verify content
const snap2 = projectServiice.getScriptInfo(f1.path).getSnapshot();
const snap2 = projectServiice.getScriptInfo(f1.path)!.getSnapshot();
assert.equal(getSnapshotText(snap2), f1.content, "content should be equal to the content of original file");
});
@@ -5074,7 +5072,7 @@ namespace ts.projectSystem {
const projectService = session.getProjectService();
checkNumberOfProjects(projectService, { inferredProjects: 1 });
const info = projectService.getScriptInfo(f1.path);
const info = projectService.getScriptInfo(f1.path)!;
assert.isDefined(info);
checkScriptInfoContents(openContent, "contents set during open request");
@@ -5647,8 +5645,7 @@ namespace ts.projectSystem {
function verifyConfiguredProject(host: TestServerHost, projectService: TestProjectService, orphanInferredProject?: boolean) {
projectService.checkNumberOfProjects({ configuredProjects: 1, inferredProjects: orphanInferredProject ? 1 : 0 });
const project = projectService.configuredProjects.get(tsconfig.path);
assert.isDefined(project);
const project = Debug.assertDefined(projectService.configuredProjects.get(tsconfig.path));
if (orphanInferredProject) {
const inferredProject = projectService.inferredProjects[0];
@@ -6240,7 +6237,7 @@ namespace ts.projectSystem {
const calledMap = createMultiMap<[U, V, W, X]>();
const cb = (<any>host)[prop].bind(host);
(<any>host)[prop] = (f: string, arg1?: U, arg2?: V, arg3?: W, arg4?: X) => {
calledMap.add(f, [arg1, arg2, arg3, arg4]);
calledMap.add(f, [arg1!, arg2!, arg3!, arg4!]); // TODO: GH#18217
return cb(f, arg1, arg2, arg3, arg4);
};
return calledMap;
@@ -6495,7 +6492,7 @@ namespace ts.projectSystem {
assert.isDefined(configFileName, `should find config`);
checkNumberOfConfiguredProjects(projectService, 1);
const project = projectService.configuredProjects.get(tsconfigFile.path);
const project = projectService.configuredProjects.get(tsconfigFile.path)!;
checkProjectActualFiles(project, map(projectFiles, f => f.path));
const callsTrackingHost = createCallsTrackingHost(host);
@@ -6504,8 +6501,8 @@ namespace ts.projectSystem {
const getDefinitionRequest = makeSessionRequest<protocol.FileLocationRequestArgs>(protocol.CommandTypes.Definition, {
file: clientFile.path,
position: clientFile.content.indexOf("/vessel") + 1,
line: undefined,
offset: undefined
line: undefined!, // TODO: GH#18217
offset: undefined! // TODO: GH#18217
});
const response = session.executeCommand(getDefinitionRequest).response as server.protocol.FileSpan[];
assert.equal(response[0].file, moduleFile.path, "Should go to definition of vessel: response: " + JSON.stringify(response));
@@ -6581,11 +6578,11 @@ namespace ts.projectSystem {
const projectService = createProjectService(host);
const canonicalConfigPath = toCanonical(tsconfigFile.path);
const { configFileName } = projectService.openClientFile(file1.path);
assert.equal(configFileName, tsconfigFile.path, `should find config`);
assert.equal(configFileName, tsconfigFile.path as server.NormalizedPath, `should find config`); // tslint:disable-line no-unnecessary-type-assertion (TODO: GH#18217)
checkNumberOfConfiguredProjects(projectService, 1);
const watchingRecursiveDirectories = [`${canonicalFrontendDir}/src`, canonicalFrontendDir].concat(getNodeModuleDirectories(getDirectoryPath(canonicalFrontendDir)));
const project = projectService.configuredProjects.get(canonicalConfigPath);
const project = projectService.configuredProjects.get(canonicalConfigPath)!;
verifyProjectAndWatchedDirectories();
const callsTrackingHost = createCallsTrackingHost(host);
@@ -6664,7 +6661,7 @@ namespace ts.projectSystem {
const service = createProjectService(host);
service.openClientFile(file1.path);
const project = service.configuredProjects.get(tsconfig.path);
const project = service.configuredProjects.get(tsconfig.path)!;
checkProjectActualFiles(project, files.map(f => f.path));
assert.deepEqual(project.getLanguageService().getSemanticDiagnostics(file1.path).map(diag => diag.messageText), ["Cannot find module 'debug'."]);
assert.deepEqual(project.getLanguageService().getSemanticDiagnostics(file2.path).map(diag => diag.messageText), ["Cannot find module 'debug'."]);
@@ -6736,7 +6733,7 @@ namespace ts.projectSystem {
const host = createServerHost(projectFiles.concat(otherFiles));
const projectService = createProjectService(host);
const { configFileName } = projectService.openClientFile(app.path);
assert.equal(configFileName, tsconfigJson.path, `should find config`);
assert.equal(configFileName, tsconfigJson.path as server.NormalizedPath, `should find config`); // TODO: GH#18217
const recursiveWatchedDirectories: string[] = [appFolder].concat(getNodeModuleDirectories(getDirectoryPath(appFolder)));
verifyProject();
@@ -6815,7 +6812,7 @@ namespace ts.projectSystem {
});
const lodashIndexPath = root + "/a/b/node_modules/@types/lodash/index.d.ts";
projectFiles.push(find(filesAndFoldersToAdd, f => f.path === lodashIndexPath));
projectFiles.push(find(filesAndFoldersToAdd, f => f.path === lodashIndexPath)!);
// we would now not have failed lookup in the parent of appFolder since lodash is available
recursiveWatchedDirectories.length = 1;
// npm installation complete, timeout after reload fs
@@ -6836,7 +6833,7 @@ namespace ts.projectSystem {
function verifyProject() {
checkNumberOfConfiguredProjects(projectService, 1);
const project = projectService.configuredProjects.get(tsconfigJson.path);
const project = projectService.configuredProjects.get(tsconfigJson.path)!;
const projectFilePaths = map(projectFiles, f => f.path);
checkProjectActualFiles(project, projectFilePaths);
@@ -6872,7 +6869,7 @@ namespace ts.projectSystem {
const service = createProjectService(host);
service.openClientFile(app.path);
const project = service.configuredProjects.get(tsconfig.path);
const project = service.configuredProjects.get(tsconfig.path)!;
checkProjectActualFiles(project, files.map(f => f.path));
assert.deepEqual(project.getLanguageService().getSemanticDiagnostics(app.path).map(diag => diag.messageText), ["Cannot find module 'debug'."]);
@@ -7071,7 +7068,7 @@ namespace ts.projectSystem {
content: JSON.stringify(configObj || { compilerOptions: {} })
};
const files = [file1Consumer1, moduleFile1, file1Consumer2, moduleFile2, ...additionalFiles, globalFile3, libFile, configFile];
const files: File[] = [file1Consumer1, moduleFile1, file1Consumer2, moduleFile2, ...additionalFiles, globalFile3, libFile, configFile];
const filesToReload = firstReloadFileList && getFiles(firstReloadFileList) || files;
const host = createServerHost([filesToReload[0], configFile]);
@@ -7097,7 +7094,7 @@ namespace ts.projectSystem {
}
function getFile(fileName: string) {
return find(files, file => file.path === fileName);
return find(files, file => file.path === fileName)!;
}
function verifyNoProjectsUpdatedInBackgroundEvent(filesToReload?: File[]) {
@@ -7345,7 +7342,7 @@ namespace ts.projectSystem {
const projectService = session.getProjectService();
verifyInitialOpen(file1);
checkNumberOfProjects(projectService, { configuredProjects: 1 });
const project = projectService.configuredProjects.get(configFile.path);
const project = projectService.configuredProjects.get(configFile.path)!;
verifyProject();
if (limitHit) {
(project as ResolutionCacheHost).maxNumberOfFilesToIterateForInvalidation = 1;
@@ -7521,7 +7518,7 @@ namespace ts.projectSystem {
const host = createServerHost(files, { useWindowsStylePaths: true });
const projectService = createProjectService(host);
projectService.openClientFile(file1.path);
const project = projectService.configuredProjects.get(configFile.path);
const project = projectService.configuredProjects.get(configFile.path)!;
assert.isDefined(project);
const winsowsStyleLibFilePath = "c:/" + libFile.path.substring(1);
checkProjectActualFiles(project, files.map(f => f === libFile ? winsowsStyleLibFilePath : f.path));
@@ -7849,7 +7846,7 @@ new C();`
function verifyProjectWithResolvedModule(session: TestSession) {
const projectService = session.getProjectService();
const project = projectService.configuredProjects.get(recognizerDateTimeTsconfigPath);
const project = projectService.configuredProjects.get(recognizerDateTimeTsconfigPath)!;
checkProjectActualFiles(project, filesInProjectWithResolvedModule);
verifyWatchedFilesAndDirectories(session.host, filesInProjectWithResolvedModule, watchedDirectoriesWithResolvedModule);
verifyErrors(session, []);
@@ -7857,7 +7854,7 @@ new C();`
function verifyProjectWithUnresolvedModule(session: TestSession) {
const projectService = session.getProjectService();
const project = projectService.configuredProjects.get(recognizerDateTimeTsconfigPath);
const project = projectService.configuredProjects.get(recognizerDateTimeTsconfigPath)!;
checkProjectActualFiles(project, filesInProjectWithUnresolvedModule);
verifyWatchedFilesAndDirectories(session.host, filesInProjectWithUnresolvedModule, watchedDirectoriesWithUnresolvedModule);
const startOffset = recognizersDateTimeSrcFile.content.indexOf('"') + 1;
@@ -8358,8 +8355,7 @@ new C();`
const projectService = createProjectService(host);
projectService.openClientFile(index.path);
const project = projectService.configuredProjects.get(configFile.path);
assert.isDefined(project);
const project = Debug.assertDefined(projectService.configuredProjects.get(configFile.path));
verifyProjectAndCompletions();
// Add file2
@@ -8377,7 +8373,7 @@ new C();`
verifyProjectAndCompletions();
function verifyProjectAndCompletions() {
const completions = project.getLanguageService().getCompletionsAtPosition(index.path, completionPosition, { includeExternalModuleExports: false, includeInsertTextCompletions: false });
const completions = project.getLanguageService().getCompletionsAtPosition(index.path, completionPosition, { includeExternalModuleExports: false, includeInsertTextCompletions: false })!;
checkArray("Completion Entries", completions.entries.map(e => e.name), expectedCompletions);
checkWatchedDirectories(host, emptyArray, /*recursive*/ true);
@@ -8443,7 +8439,7 @@ new C();`
};
function getProject(service: TestProjectService) {
return service.configuredProjects.get(configFile.path);
return service.configuredProjects.get(configFile.path)!;
}
function checkProject(service: TestProjectService, moduleIsOrphan: boolean) {
@@ -8451,7 +8447,7 @@ new C();`
const project = getProject(service);
project.getLanguageService();
checkProjectActualFiles(project, [file.path, libFile.path, configFile.path, ...(moduleIsOrphan ? [] : [moduleFile.path])]);
const moduleInfo = service.getScriptInfo(moduleFile.path);
const moduleInfo = service.getScriptInfo(moduleFile.path)!;
assert.isDefined(moduleInfo);
assert.equal(moduleInfo.isOrphan(), moduleIsOrphan);
const key = service.documentRegistry.getKeyForCompilationSettings(project.getCompilationSettings());
@@ -8467,13 +8463,13 @@ new C();`
}
function changeFileToNotImportModule(service: TestProjectService) {
const info = service.getScriptInfo(file.path);
const info = service.getScriptInfo(file.path)!;
service.applyChangesToFile(info, [{ span: { start: 0, length: importModuleContent.length }, newText: "" }]);
checkProject(service, /*moduleIsOrphan*/ true);
}
function changeFileToImportModule(service: TestProjectService) {
const info = service.getScriptInfo(file.path);
const info = service.getScriptInfo(file.path)!;
service.applyChangesToFile(info, [{ span: { start: 0, length: 0 }, newText: importModuleContent }]);
checkProject(service, /*moduleIsOrphan*/ false);
}
@@ -8482,7 +8478,7 @@ new C();`
const { service } = createServiceAndHost();
const project = getProject(service);
const moduleInfo = service.getScriptInfo(moduleFile.path);
const moduleInfo = service.getScriptInfo(moduleFile.path)!;
const sourceFile = moduleInfo.cacheSourceFile.sourceFile;
assert.equal(project.getSourceFile(moduleInfo.path), sourceFile);
@@ -8500,7 +8496,7 @@ new C();`
const { host, service } = createServiceAndHost();
const project = getProject(service);
const moduleInfo = service.getScriptInfo(moduleFile.path);
const moduleInfo = service.getScriptInfo(moduleFile.path)!;
const sourceFile = moduleInfo.cacheSourceFile.sourceFile;
assert.equal(project.getSourceFile(moduleInfo.path), sourceFile);
+8 -8
View File
@@ -1447,7 +1447,7 @@ namespace ts.projectSystem {
commander: { typingLocation: commander.path, version: Semver.parse("1.3.0-next.0") }
});
const registry = createTypesRegistry("node", "commander");
registry.get("node")[`ts${versionMajorMinor}`] = "1.3.0-next.1";
registry.get("node")![`ts${versionMajorMinor}`] = "1.3.0-next.1";
const logger = trackingLogger();
const result = JsTyping.discoverTypings(host, logger.log, [app.path], getDirectoryPath(<Path>app.path), emptySafeList, cache, { enable: true }, ["http", "commander"], registry);
assert.deepEqual(logger.finish(), [
@@ -1535,8 +1535,8 @@ namespace ts.projectSystem {
content: "export let x: number"
};
const host = createServerHost([f1, packageFile, packageLockFile]);
let beginEvent: server.BeginInstallTypes;
let endEvent: server.EndInstallTypes;
let beginEvent!: server.BeginInstallTypes;
let endEvent!: server.EndInstallTypes;
const installer = new (class extends Installer {
constructor() {
super(host, { globalTypingsCacheLocation: cachePath, typesRegistry: createTypesRegistry("commander") });
@@ -1583,8 +1583,8 @@ namespace ts.projectSystem {
};
const cachePath = "/a/cache/";
const host = createServerHost([f1, packageFile]);
let beginEvent: server.BeginInstallTypes;
let endEvent: server.EndInstallTypes;
let beginEvent: server.BeginInstallTypes | undefined;
let endEvent: server.EndInstallTypes | undefined;
const installer: Installer = new (class extends Installer {
constructor() {
super(host, { globalTypingsCacheLocation: cachePath, typesRegistry: createTypesRegistry("commander") });
@@ -1611,8 +1611,8 @@ namespace ts.projectSystem {
assert.isTrue(!!beginEvent);
assert.isTrue(!!endEvent);
assert.isTrue(beginEvent.eventId === endEvent.eventId);
assert.isFalse(endEvent.installSuccess);
assert.isTrue(beginEvent!.eventId === endEvent!.eventId);
assert.isFalse(endEvent!.installSuccess);
checkNumberOfProjects(projectService, { inferredProjects: 1 });
checkProjectActualFiles(projectService.inferredProjects[0], [f1.path]);
});
@@ -1651,7 +1651,7 @@ namespace ts.projectSystem {
const appPath = "/a/b/app.js" as Path;
const foooPath = "/a/b/node_modules/fooo/index.d.ts";
function verifyResolvedModuleOfFooo(project: server.Project) {
const foooResolution = project.getLanguageService().getProgram().getSourceFileByPath(appPath).resolvedModules.get("fooo");
const foooResolution = project.getLanguageService().getProgram()!.getSourceFileByPath(appPath)!.resolvedModules!.get("fooo")!;
assert.equal(foooResolution.resolvedFileName, foooPath);
return foooResolution;
}
+16 -16
View File
@@ -46,7 +46,7 @@ var q:Point=<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)", () => {
+3 -3
View File
@@ -3,8 +3,8 @@
*/
namespace utils {
const testPathPrefixRegExp = /(?:(file:\/{3})|\/)\.(ts|lib|src)\//g;
export function removeTestPathPrefixes(text: string, retainTrailingDirectorySeparator?: boolean) {
return text !== undefined ? text.replace(testPathPrefixRegExp, (_, scheme) => scheme || (retainTrailingDirectorySeparator ? "/" : "")) : undefined;
export function removeTestPathPrefixes(text: string, retainTrailingDirectorySeparator?: boolean): string {
return text !== undefined ? text.replace(testPathPrefixRegExp, (_, scheme) => scheme || (retainTrailingDirectorySeparator ? "/" : "")) : undefined!; // TODO: GH#18217
}
/**
@@ -49,7 +49,7 @@ namespace utils {
}
function guessIndentation(lines: string[]) {
let indentation: number;
let indentation: number | undefined;
for (const line of lines) {
for (let i = 0; i < line.length && (indentation === undefined || i < indentation); i++) {
if (!ts.isWhiteSpaceLike(line.charCodeAt(i))) {
+5 -5
View File
@@ -935,7 +935,7 @@ namespace vfs {
this._applyFilesWorker(value.files, path, deferred);
}
else {
deferred.push([value as Symlink | Link | Mount, path]);
deferred.push([value, path]);
}
}
}
@@ -998,7 +998,7 @@ namespace vfs {
directoryExists(path: string): boolean;
fileExists(path: string): boolean;
getFileSize(path: string): number;
readFile(path: string): string;
readFile(path: string): string | undefined;
getWorkspaceRoot(): string;
}
@@ -1020,7 +1020,7 @@ namespace vfs {
}
},
readFileSync(path: string): Buffer {
return Buffer.from(host.readFile(path), "utf8");
return Buffer.from(host.readFile(path)!, "utf8"); // TODO: GH#18217
}
};
}
@@ -1241,7 +1241,7 @@ namespace vfs {
ctimeMs: number; // status change time
birthtimeMs: number; // creation time
nlink: number; // number of hard links
symlink?: string;
symlink: string;
shadowRoot?: SymlinkInode;
meta?: collections.Metadata;
}
@@ -1262,7 +1262,7 @@ namespace vfs {
realpath: string;
basename: string;
parent: DirectoryInode | undefined;
links: collections.SortedMap<string, Inode> | undefined;
links: collections.SortedMap<string, Inode>;
node: Inode | undefined;
}
+17 -17
View File
@@ -179,7 +179,7 @@ interface Array<T> {}`
verifyMapSize(caption, actual, arrayFrom(expectedKeys.keys()));
expectedKeys.forEach((count, name) => {
assert.isTrue(actual.has(name), `${caption}: expected to contain ${name}, actual keys: ${arrayFrom(actual.keys())}`);
assert.equal(actual.get(name).length, count, `${caption}: Expected to be have ${count} entries for ${name}. Actual entry: ${JSON.stringify(actual.get(name))}`);
assert.equal(actual.get(name)!.length, count, `${caption}: Expected to be have ${count} entries for ${name}. Actual entry: ${JSON.stringify(actual.get(name))}`);
});
}
@@ -322,7 +322,7 @@ interface Array<T> {}`
readonly watchedFiles = createMultiMap<TestFileWatcher>();
private readonly executingFilePath: string;
private readonly currentDirectory: string;
private readonly dynamicPriorityWatchFile: HostWatchFile;
private readonly dynamicPriorityWatchFile: HostWatchFile | undefined;
private readonly customRecursiveWatchDirectory: HostWatchDirectory | undefined;
constructor(public withSafeList: boolean, public useCaseSensitiveFileNames: boolean, executingFilePath: string, currentDirectory: string, fileOrFolderorSymLinkList: ReadonlyArray<FileOrFolderOrSymLink>, public readonly newLine = "\n", public readonly useWindowsStylePath?: boolean, private readonly environmentVariables?: Map<string>) {
@@ -465,7 +465,7 @@ interface Array<T> {}`
else {
currentEntry.content = content;
currentEntry.modifiedTime = this.now();
this.fs.get(getDirectoryPath(currentEntry.path)).modifiedTime = this.now();
this.fs.get(getDirectoryPath(currentEntry.path))!.modifiedTime = this.now();
if (options && options.invokeDirectoryWatcherInsteadOfFileChanged) {
this.invokeDirectoryWatcher(getDirectoryPath(currentEntry.fullPath), currentEntry.fullPath);
}
@@ -570,7 +570,7 @@ interface Array<T> {}`
this.invokeDirectoryWatcher(folder.fullPath, fileOrDirectory.fullPath);
}
private removeFileOrFolder(fileOrDirectory: FsFile | FsFolder | FsSymLink, isRemovableLeafFolder: (folder: FsFolder) => boolean, isRenaming?: boolean) {
private removeFileOrFolder(fileOrDirectory: FsFile | FsFolder | FsSymLink, isRemovableLeafFolder: (folder: FsFolder) => boolean, isRenaming = false) {
const basePath = getDirectoryPath(fileOrDirectory.path);
const baseFolder = this.fs.get(basePath) as FsFolder;
if (basePath !== fileOrDirectory.path) {
@@ -621,15 +621,15 @@ interface Array<T> {}`
// For overriding the methods
invokeWatchedDirectoriesCallback(folderFullPath: string, relativePath: string) {
invokeWatcherCallbacks(this.watchedDirectories.get(this.toPath(folderFullPath)), cb => this.directoryCallback(cb, relativePath));
invokeWatcherCallbacks(this.watchedDirectories.get(this.toPath(folderFullPath))!, cb => this.directoryCallback(cb, relativePath));
}
invokeWatchedDirectoriesRecursiveCallback(folderFullPath: string, relativePath: string) {
invokeWatcherCallbacks(this.watchedDirectoriesRecursive.get(this.toPath(folderFullPath)), cb => this.directoryCallback(cb, relativePath));
invokeWatcherCallbacks(this.watchedDirectoriesRecursive.get(this.toPath(folderFullPath))!, cb => this.directoryCallback(cb, relativePath));
}
invokeFileWatcher(fileFullPath: string, eventKind: FileWatcherEventKind, useFileNameInCallback?: boolean) {
invokeWatcherCallbacks(this.watchedFiles.get(this.toPath(fileFullPath)), ({ cb, fileName }) => cb(useFileNameInCallback ? fileName : fileFullPath, eventKind));
invokeWatcherCallbacks(this.watchedFiles.get(this.toPath(fileFullPath))!, ({ cb, fileName }) => cb(useFileNameInCallback ? fileName : fileFullPath, eventKind));
}
private getRelativePathToDirectory(directoryFullPath: string, fileFullPath: string) {
@@ -687,11 +687,11 @@ interface Array<T> {}`
private toFsFolder(path: string): FsFolder {
const fsFolder = this.toFsEntry(path) as FsFolder;
fsFolder.entries = [] as SortedArray<FSEntry>;
fsFolder.entries = [] as FSEntry[] as SortedArray<FSEntry>; // https://github.com/Microsoft/TypeScript/issues/19873
return fsFolder;
}
private getRealFsEntry<T extends FSEntry>(isFsEntry: (fsEntry: FSEntry) => fsEntry is T, path: Path, fsEntry = this.fs.get(path)): T | undefined {
private getRealFsEntry<T extends FSEntry>(isFsEntry: (fsEntry: FSEntry) => fsEntry is T, path: Path, fsEntry = this.fs.get(path)!): T | undefined {
if (isFsEntry(fsEntry)) {
return fsEntry;
}
@@ -737,21 +737,21 @@ interface Array<T> {}`
getModifiedTime(s: string) {
const path = this.toFullPath(s);
const fsEntry = this.fs.get(path);
return fsEntry && fsEntry.modifiedTime;
return (fsEntry && fsEntry.modifiedTime)!; // TODO: GH#18217
}
readFile(s: string): string {
readFile(s: string): string | undefined {
const fsEntry = this.getRealFile(this.toFullPath(s));
return fsEntry ? fsEntry.content : undefined;
}
getFileSize(s: string) {
const path = this.toFullPath(s);
const entry = this.fs.get(path);
const entry = this.fs.get(path)!;
if (isFsFile(entry)) {
return entry.fileSize ? entry.fileSize : entry.content.length;
}
return undefined;
return undefined!; // TODO: GH#18217
}
directoryExists(s: string) {
@@ -812,7 +812,7 @@ interface Array<T> {}`
}
createSHA256Hash(s: string): string {
return sys.createSHA256Hash(s);
return sys.createSHA256Hash!(s);
}
watchFile(fileName: string, cb: FileWatcherCallback, pollingInterval: number) {
@@ -925,7 +925,7 @@ interface Array<T> {}`
}
const dirFullPath = this.realpath(getDirectoryPath(fullPath));
const realFullPath = combinePaths(dirFullPath, getBaseFileName(fullPath));
const fsEntry = this.fs.get(this.toPath(realFullPath));
const fsEntry = this.fs.get(this.toPath(realFullPath))!;
if (isFsSymLink(fsEntry)) {
return this.realpath(fsEntry.symLink);
}
@@ -934,7 +934,7 @@ interface Array<T> {}`
}
readonly exitMessage = "System Exit";
exitCode: number;
exitCode: number | undefined;
readonly resolvePath = (s: string) => s;
readonly getExecutingFilePath = () => this.executingFilePath;
readonly getCurrentDirectory = () => this.currentDirectory;
@@ -943,7 +943,7 @@ interface Array<T> {}`
throw new Error(this.exitMessage);
}
getEnvironmentVariable(name: string) {
return this.environmentVariables && this.environmentVariables.get(name);
return this.environmentVariables && this.environmentVariables.get(name) || "";
}
}
}
@@ -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
};
+52 -52
View File
@@ -50,7 +50,7 @@ namespace ts.server {
private getLineMap(fileName: string): number[] {
let lineMap = this.lineMaps.get(fileName);
if (!lineMap) {
lineMap = computeLineStarts(getSnapshotText(this.host.getScriptSnapshot(fileName)));
lineMap = computeLineStarts(getSnapshotText(this.host.getScriptSnapshot(fileName)!));
this.lineMaps.set(fileName, lineMap);
}
return lineMap;
@@ -89,10 +89,9 @@ namespace ts.server {
private processResponse<T extends protocol.Response>(request: protocol.Request): T {
let foundResponseMessage = false;
let lastMessage: string;
let response: T;
let response!: T;
while (!foundResponseMessage) {
lastMessage = this.messages.shift();
const lastMessage = this.messages.shift()!;
Debug.assert(!!lastMessage, "Did not receive any responses.");
const responseBody = extractMessage(lastMessage);
try {
@@ -133,7 +132,7 @@ namespace ts.server {
changeFile(fileName: string, start: number, end: number, insertString: string): void {
// clear the line map after an edit
this.lineMaps.set(fileName, undefined);
this.lineMaps.set(fileName, undefined!); // TODO: GH#18217
const args: protocol.ChangeRequestArgs = { ...this.createFileLocationRequestArgsWithEndLineAndOffset(fileName, start, end), insertString };
this.processRequest(CommandNames.Change, args);
@@ -149,14 +148,15 @@ namespace ts.server {
const request = this.processRequest<protocol.QuickInfoRequest>(CommandNames.Quickinfo, args);
const response = this.processResponse<protocol.QuickInfoResponse>(request);
const body = response.body!; // TODO: GH#18217
return {
kind: response.body.kind,
kindModifiers: response.body.kindModifiers,
textSpan: this.decodeSpan(response.body, fileName),
displayParts: [{ kind: "text", text: response.body.displayString }],
documentation: [{ kind: "text", text: response.body.documentation }],
tags: response.body.tags
kind: body.kind,
kindModifiers: body.kindModifiers,
textSpan: this.decodeSpan(body, fileName),
displayParts: [{ kind: "text", text: body.displayString }],
documentation: [{ kind: "text", text: body.documentation }],
tags: body.tags
};
}
@@ -167,8 +167,8 @@ namespace ts.server {
const response = this.processResponse<protocol.ProjectInfoResponse>(request);
return {
configFileName: response.body.configFileName,
fileNames: response.body.fileNames
configFileName: response.body!.configFileName, // TODO: GH#18217
fileNames: response.body!.fileNames
};
}
@@ -183,7 +183,7 @@ namespace ts.server {
isGlobalCompletion: false,
isMemberCompletion: false,
isNewIdentifierLocation: false,
entries: response.body.map<CompletionEntry>(entry => {
entries: response.body!.map<CompletionEntry>(entry => { // TODO: GH#18217
if (entry.replacementSpan !== undefined) {
const { name, kind, kindModifiers, sortText, replacementSpan, hasAction, source, isRecommended } = entry;
// TODO: GH#241
@@ -201,10 +201,9 @@ namespace ts.server {
const request = this.processRequest<protocol.CompletionDetailsRequest>(CommandNames.CompletionDetails, args);
const response = this.processResponse<protocol.CompletionDetailsResponse>(request);
Debug.assert(response.body.length === 1, "Unexpected length of completion details response body.");
const convertedCodeActions = map(response.body[0].codeActions, ({ description, changes }) => ({ description, changes: this.convertChanges(changes, fileName) }));
return { ...response.body[0], codeActions: convertedCodeActions };
Debug.assert(response.body!.length === 1, "Unexpected length of completion details response body.");
const convertedCodeActions = map(response.body![0].codeActions, ({ description, changes }) => ({ description, changes: this.convertChanges(changes, fileName) }));
return { ...response.body![0], codeActions: convertedCodeActions };
}
getCompletionEntrySymbol(_fileName: string, _position: number, _entryName: string): Symbol {
@@ -220,14 +219,14 @@ namespace ts.server {
const request = this.processRequest<protocol.NavtoRequest>(CommandNames.Navto, args);
const response = this.processResponse<protocol.NavtoResponse>(request);
return response.body.map(entry => ({
return response.body!.map(entry => ({ // TODO: GH#18217
name: entry.name,
containerName: entry.containerName || "",
containerKind: entry.containerKind || ScriptElementKind.unknown,
kind: entry.kind,
kindModifiers: entry.kindModifiers,
matchKind: entry.matchKind,
isCaseSensitive: entry.isCaseSensitive,
kindModifiers: entry.kindModifiers!, // TODO: GH#18217
matchKind: entry.matchKind!, // TODO: GH#18217
isCaseSensitive: entry.isCaseSensitive!, // TODO: GH#18217
fileName: entry.file,
textSpan: this.decodeSpan(entry),
}));
@@ -241,11 +240,11 @@ namespace ts.server {
const request = this.processRequest<protocol.FormatRequest>(CommandNames.Format, args);
const response = this.processResponse<protocol.FormatResponse>(request);
return response.body.map(entry => this.convertCodeEditsToTextChange(file, entry));
return response.body!.map(entry => this.convertCodeEditsToTextChange(file, entry)); // TODO: GH#18217
}
getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions): TextChange[] {
return this.getFormattingEditsForRange(fileName, 0, this.host.getScriptSnapshot(fileName).getLength(), options);
return this.getFormattingEditsForRange(fileName, 0, this.host.getScriptSnapshot(fileName)!.getLength(), options);
}
getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, _options: FormatCodeOptions): TextChange[] {
@@ -255,7 +254,7 @@ namespace ts.server {
const request = this.processRequest<protocol.FormatOnKeyRequest>(CommandNames.Formatonkey, args);
const response = this.processResponse<protocol.FormatResponse>(request);
return response.body.map(entry => this.convertCodeEditsToTextChange(fileName, entry));
return response.body!.map(entry => this.convertCodeEditsToTextChange(fileName, entry)); // TODO: GH#18217
}
getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] {
@@ -264,7 +263,7 @@ namespace ts.server {
const request = this.processRequest<protocol.DefinitionRequest>(CommandNames.Definition, args);
const response = this.processResponse<protocol.DefinitionResponse>(request);
return response.body.map(entry => ({
return response.body!.map(entry => ({ // TODO: GH#18217
containerKind: ScriptElementKind.unknown,
containerName: "",
fileName: entry.file,
@@ -281,7 +280,7 @@ namespace ts.server {
const response = this.processResponse<protocol.DefinitionInfoAndBoundSpanReponse>(request);
return {
definitions: response.body.definitions.map(entry => ({
definitions: response.body!.definitions.map(entry => ({ // TODO: GH#18217
containerKind: ScriptElementKind.unknown,
containerName: "",
fileName: entry.file,
@@ -289,7 +288,7 @@ namespace ts.server {
kind: ScriptElementKind.unknown,
name: ""
})),
textSpan: this.decodeSpan(response.body.textSpan, request.arguments.file)
textSpan: this.decodeSpan(response.body!.textSpan, request.arguments.file)
};
}
@@ -299,7 +298,7 @@ namespace ts.server {
const request = this.processRequest<protocol.TypeDefinitionRequest>(CommandNames.TypeDefinition, args);
const response = this.processResponse<protocol.TypeDefinitionResponse>(request);
return response.body.map(entry => ({
return response.body!.map(entry => ({ // TODO: GH#18217
containerKind: ScriptElementKind.unknown,
containerName: "",
fileName: entry.file,
@@ -315,7 +314,7 @@ namespace ts.server {
const request = this.processRequest<protocol.ImplementationRequest>(CommandNames.Implementation, args);
const response = this.processResponse<protocol.ImplementationResponse>(request);
return response.body.map(entry => ({
return response.body!.map(entry => ({ // TODO: GH#18217
fileName: entry.file,
textSpan: this.decodeSpan(entry),
kind: ScriptElementKind.unknown,
@@ -334,7 +333,7 @@ namespace ts.server {
const request = this.processRequest<protocol.ReferencesRequest>(CommandNames.References, args);
const response = this.processResponse<protocol.ReferencesResponse>(request);
return response.body.refs.map(entry => ({
return response.body!.refs.map(entry => ({ // TODO: GH#18217
fileName: entry.file,
textSpan: this.decodeSpan(entry),
isWriteAccess: entry.isWriteAccess,
@@ -349,7 +348,7 @@ namespace ts.server {
getSyntacticDiagnostics(file: string): DiagnosticWithLocation[] {
return this.getDiagnostics(file, CommandNames.SyntacticDiagnosticsSync);
}
getSemanticDiagnostics(file: string): DiagnosticWithLocation[] {
getSemanticDiagnostics(file: string): Diagnostic[] {
return this.getDiagnostics(file, CommandNames.SemanticDiagnosticsSync);
}
getSuggestionDiagnostics(file: string): DiagnosticWithLocation[] {
@@ -364,7 +363,7 @@ namespace ts.server {
const category = firstDefined(Object.keys(DiagnosticCategory), id =>
isString(id) && entry.category === id.toLowerCase() ? (<any>DiagnosticCategory)[id] : undefined);
return {
file: undefined,
file: undefined!, // TODO: GH#18217
start: entry.start,
length: entry.length,
messageText: entry.message,
@@ -384,8 +383,9 @@ namespace ts.server {
const request = this.processRequest<protocol.RenameRequest>(CommandNames.Rename, args);
const response = this.processResponse<protocol.RenameResponse>(request);
const body = response.body!; // TODO: GH#18217
const locations: RenameLocation[] = [];
for (const entry of response.body.locs) {
for (const entry of body.locs) {
const fileName = entry.file;
for (const loc of entry.locs) {
locations.push({ textSpan: this.decodeSpan(loc, fileName), fileName });
@@ -393,17 +393,17 @@ namespace ts.server {
}
return this.lastRenameEntry = {
canRename: response.body.info.canRename,
displayName: response.body.info.displayName,
fullDisplayName: response.body.info.fullDisplayName,
kind: response.body.info.kind,
kindModifiers: response.body.info.kindModifiers,
localizedErrorMessage: response.body.info.localizedErrorMessage,
canRename: body.info.canRename,
displayName: body.info.displayName,
fullDisplayName: body.info.fullDisplayName,
kind: body.info.kind,
kindModifiers: body.info.kindModifiers,
localizedErrorMessage: body.info.localizedErrorMessage,
triggerSpan: createTextSpanFromBounds(position, position),
fileName,
position,
findInStrings,
findInComments,
findInStrings: !!findInStrings,
findInComments: !!findInComments,
locations,
};
}
@@ -420,7 +420,7 @@ namespace ts.server {
return this.lastRenameEntry.locations;
}
private decodeNavigationBarItems(items: protocol.NavigationBarItem[], fileName: string, lineMap: number[]): NavigationBarItem[] {
private decodeNavigationBarItems(items: protocol.NavigationBarItem[] | undefined, fileName: string, lineMap: number[]): NavigationBarItem[] {
if (!items) {
return [];
}
@@ -460,7 +460,7 @@ namespace ts.server {
const response = this.processResponse<protocol.NavTreeResponse>(request);
const lineMap = this.getLineMap(file);
return this.decodeNavigationTree(response.body, file, lineMap);
return this.decodeNavigationTree(response.body!, file, lineMap); // TODO: GH#18217
}
private decodeSpan(span: protocol.TextSpan & { file: string }): TextSpan;
@@ -488,7 +488,7 @@ namespace ts.server {
const response = this.processResponse<protocol.SignatureHelpResponse>(request);
if (!response.body) {
return undefined;
return undefined!; // TODO: GH#18217
}
const { items, applicableSpan: encodedApplicableSpan, selectedItemIndex, argumentIndex, argumentCount } = response.body;
@@ -504,7 +504,7 @@ namespace ts.server {
const request = this.processRequest<protocol.OccurrencesRequest>(CommandNames.Occurrences, args);
const response = this.processResponse<protocol.OccurrencesResponse>(request);
return response.body.map(entry => ({
return response.body!.map(entry => ({ // TODO: GH#18217
fileName: entry.file,
textSpan: this.decodeSpan(entry),
isWriteAccess: entry.isWriteAccess,
@@ -518,7 +518,7 @@ namespace ts.server {
const request = this.processRequest<protocol.DocumentHighlightsRequest>(CommandNames.DocumentHighlights, args);
const response = this.processResponse<protocol.DocumentHighlightsResponse>(request);
return response.body.map(item => ({
return response.body!.map(item => ({ // TODO: GH#18217
fileName: item.file,
highlightSpans: item.highlightSpans.map(span => ({
textSpan: this.decodeSpan(span, item.file),
@@ -531,7 +531,7 @@ namespace ts.server {
const request = this.processRequest<protocol.OutliningSpansRequest>(CommandNames.GetOutliningSpans, { file });
const response = this.processResponse<protocol.OutliningSpansResponse>(request);
return response.body.map<OutliningSpan>(item => ({
return response.body!.map<OutliningSpan>(item => ({
textSpan: this.decodeSpan(item.textSpan, file),
hintSpan: this.decodeSpan(item.hintSpan, file),
bannerText: item.bannerText,
@@ -562,7 +562,7 @@ namespace ts.server {
const request = this.processRequest<protocol.CodeFixRequest>(CommandNames.GetCodeFixes, args);
const response = this.processResponse<protocol.CodeFixResponse>(request);
return response.body.map<CodeFixAction>(({ fixName, description, changes, commands, fixId, fixAllDescription }) =>
return response.body!.map<CodeFixAction>(({ fixName, description, changes, commands, fixId, fixAllDescription }) => // TODO: GH#18217
({ fixName, description, changes: this.convertChanges(changes, file), commands: commands as CodeActionCommand[], fixId, fixAllDescription }));
}
@@ -598,7 +598,7 @@ namespace ts.server {
const request = this.processRequest<protocol.GetApplicableRefactorsRequest>(CommandNames.GetApplicableRefactors, args);
const response = this.processResponse<protocol.GetApplicableRefactorsResponse>(request);
return response.body;
return response.body!; // TODO: GH#18217
}
getEditsForRefactor(
@@ -624,7 +624,7 @@ namespace ts.server {
const renameFilename: string | undefined = response.body.renameFilename;
let renameLocation: number | undefined;
if (renameFilename !== undefined) {
renameLocation = this.lineOffsetToPosition(renameFilename, response.body.renameLocation);
renameLocation = this.lineOffsetToPosition(renameFilename, response.body.renameLocation!); // TODO: GH#18217
}
return {
@@ -672,7 +672,7 @@ namespace ts.server {
const request = this.processRequest<protocol.BraceRequest>(CommandNames.Brace, args);
const response = this.processResponse<protocol.BraceResponse>(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 {
+66 -66
View File
@@ -71,7 +71,7 @@ namespace ts.server {
}
export interface ProjectInfoTypeAcquisitionData {
readonly enable: boolean;
readonly enable: boolean | undefined;
// Actual values of include/exclude entries are scrubbed.
readonly include: boolean;
readonly exclude: boolean;
@@ -225,13 +225,13 @@ namespace ts.server {
interface FilePropertyReader<T> {
getFileName(f: T): string;
getScriptKind(f: T, extraFileExtensions?: FileExtensionInfo[]): ScriptKind;
hasMixedContent(f: T, extraFileExtensions: FileExtensionInfo[]): boolean;
hasMixedContent(f: T, extraFileExtensions: FileExtensionInfo[] | undefined): boolean;
}
const fileNamePropertyReader: FilePropertyReader<string> = {
getFileName: x => x,
getScriptKind: (fileName, extraFileExtensions) => {
let result: ScriptKind;
let result: ScriptKind | undefined;
if (extraFileExtensions) {
const fileExtension = getAnyExtensionFromPath(fileName);
if (fileExtension) {
@@ -244,18 +244,18 @@ namespace ts.server {
});
}
}
return result;
return result!; // TODO: GH#18217
},
hasMixedContent: (fileName, extraFileExtensions) => some(extraFileExtensions, ext => ext.isMixedContent && fileExtensionIs(fileName, ext.extension)),
};
const externalFilePropertyReader: FilePropertyReader<protocol.ExternalFile> = {
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<T extends Project>(projectName: string, projects: T[]): T {
function findProjectByName<T extends Project>(projectName: string, projects: T[]): T | undefined {
for (const proj of projects) {
if (proj.getProjectName() === projectName) {
return proj;
@@ -374,7 +374,7 @@ namespace ts.server {
/**
* Open files: with value being project root path, and key being Path of the file that is open
*/
readonly openFiles = createMap<NormalizedPath>();
readonly openFiles = createMap<NormalizedPath | undefined>();
/**
* Map of open files that are opened without complete path but have projectRoot as current directory
*/
@@ -413,7 +413,7 @@ namespace ts.server {
public readonly useSingleInferredProject: boolean;
public readonly useInferredProjectPerProjectRoot: boolean;
public readonly typingsInstaller: ITypingsInstaller;
private readonly globalCacheLocationDirectoryPath: Path;
private readonly globalCacheLocationDirectoryPath: Path | undefined;
public readonly throttleWaitMilliseconds?: number;
private readonly eventHandler?: ProjectServiceEventHandler;
private readonly suppressDiagnosticEvents?: boolean;
@@ -453,8 +453,9 @@ namespace ts.server {
}
this.currentDirectory = toNormalizedPath(this.host.getCurrentDirectory());
this.toCanonicalFileName = createGetCanonicalFileName(this.host.useCaseSensitiveFileNames);
this.globalCacheLocationDirectoryPath = this.typingsInstaller.globalTypingsCacheLocation &&
ensureTrailingDirectorySeparator(this.toPath(this.typingsInstaller.globalTypingsCacheLocation));
this.globalCacheLocationDirectoryPath = this.typingsInstaller.globalTypingsCacheLocation
? ensureTrailingDirectorySeparator(this.toPath(this.typingsInstaller.globalTypingsCacheLocation))
: undefined;
this.throttledOperations = new ThrottledOperations(this.host, this.logger);
if (this.typesMapLocation) {
@@ -498,15 +499,14 @@ namespace ts.server {
/*@internal*/
setDocument(key: DocumentRegistryBucketKey, path: Path, sourceFile: SourceFile) {
const info = this.getScriptInfoForPath(path);
Debug.assert(!!info);
const info = Debug.assertDefined(this.getScriptInfoForPath(path));
info.cacheSourceFile = { key, sourceFile };
}
/*@internal*/
getDocument(key: DocumentRegistryBucketKey, path: Path) {
getDocument(key: DocumentRegistryBucketKey, path: Path): SourceFile | undefined {
const info = this.getScriptInfoForPath(path);
return info && info.cacheSourceFile && info.cacheSourceFile.key === key && info.cacheSourceFile.sourceFile;
return info && info.cacheSourceFile && info.cacheSourceFile.key === key ? info.cacheSourceFile.sourceFile : undefined;
}
/* @internal */
@@ -533,7 +533,7 @@ namespace ts.server {
private loadTypesMap() {
try {
const fileContent = this.host.readFile(this.typesMapLocation);
const fileContent = this.host.readFile(this.typesMapLocation!); // TODO: GH#18217
if (fileContent === undefined) {
this.logger.info(`Provided types map file "${this.typesMapLocation}" doesn't exist`);
return;
@@ -623,7 +623,7 @@ namespace ts.server {
const event: ProjectsUpdatedInBackgroundEvent = {
eventName: ProjectsUpdatedInBackgroundEvent,
data: {
openFiles: arrayFrom(this.openFiles.keys(), path => this.getScriptInfoForPath(path as Path).fileName)
openFiles: arrayFrom(this.openFiles.keys(), path => this.getScriptInfoForPath(path as Path)!.fileName)
}
};
this.eventHandler(event);
@@ -673,7 +673,7 @@ namespace ts.server {
project.projectRootPath === canonicalProjectRootPath :
!project.projectRootPath || !this.compilerOptionsForInferredProjectsPerProjectRoot.has(project.projectRootPath)) {
project.setCompilerOptions(compilerOptions);
project.compileOnSaveEnabled = compilerOptions.compileOnSave;
project.compileOnSaveEnabled = compilerOptions.compileOnSave!;
project.markAsDirty();
this.delayUpdateProjectGraph(project);
}
@@ -692,7 +692,7 @@ namespace ts.server {
return this.findExternalProjectByProjectName(projectName) || this.findConfiguredProjectByProjectName(toNormalizedPath(projectName));
}
getDefaultProjectForFile(fileName: NormalizedPath, ensureProject: boolean) {
getDefaultProjectForFile(fileName: NormalizedPath, ensureProject: boolean): Project | undefined {
let scriptInfo = this.getScriptInfoForNormalizedPath(fileName);
if (ensureProject && (!scriptInfo || scriptInfo.isOrphan())) {
this.ensureProjectStructuresUptoDate();
@@ -702,7 +702,7 @@ namespace ts.server {
}
return scriptInfo.getDefaultProject();
}
return scriptInfo && !scriptInfo.isOrphan() && scriptInfo.getDefaultProject();
return scriptInfo && !scriptInfo.isOrphan() ? scriptInfo.getDefaultProject() : undefined;
}
getScriptInfoEnsuringProjectsUptoDate(uncheckedFileName: string) {
@@ -810,7 +810,7 @@ namespace ts.server {
/** Gets the config file existence info for the configured project */
/*@internal*/
getConfigFileExistenceInfo(project: ConfiguredProject) {
return this.configFileExistenceInfoCache.get(project.canonicalConfigFilePath);
return this.configFileExistenceInfoCache.get(project.canonicalConfigFilePath)!;
}
private onConfigChangedForConfiguredProject(project: ConfiguredProject, eventKind: FileWatcherEventKind) {
@@ -846,7 +846,7 @@ namespace ts.server {
private onConfigFileChangeForOpenScriptInfo(configFileName: NormalizedPath, eventKind: FileWatcherEventKind) {
// This callback is called only if we dont have config file project for this config file
const canonicalConfigPath = normalizedPathToPath(configFileName, this.currentDirectory, this.toCanonicalFileName);
const configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigPath);
const configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigPath)!;
configFileExistenceInfo.exists = (eventKind !== FileWatcherEventKind.Deleted);
this.logConfigFileWatchUpdate(configFileName, canonicalConfigPath, configFileExistenceInfo, ConfigFileWatcherStatus.ReloadingFiles);
@@ -975,7 +975,7 @@ namespace ts.server {
if (ensureProjectsForOpenFiles) {
// collect orphaned files and assign them to inferred project just like we treat open of a file
this.openFiles.forEach((projectRootPath, path) => {
const info = this.getScriptInfoForPath(path as Path);
const info = this.getScriptInfoForPath(path as Path)!;
// collect all orphaned script infos from open files
if (info.isOrphan()) {
this.assignOrphanScriptInfoToInferredProject(info, projectRootPath);
@@ -1001,7 +1001,7 @@ namespace ts.server {
this.filenameToScriptInfo.delete(info.path);
const realpath = info.getRealpathIfDifferent();
if (realpath) {
this.realpathToScriptInfos.remove(realpath, info);
this.realpathToScriptInfos!.remove(realpath, info); // TODO: GH#18217
}
}
@@ -1091,7 +1091,7 @@ namespace ts.server {
const inferredRoots: string[] = [];
const otherFiles: string[] = [];
configFileExistenceInfo.openFilesImpactedByConfigFile.forEach((isRootOfInferredProject, key) => {
const info = this.getScriptInfoForPath(key as Path);
const info = this.getScriptInfoForPath(key as Path)!;
(isRootOfInferredProject ? inferredRoots : otherFiles).push(info.fileName);
});
@@ -1235,7 +1235,7 @@ namespace ts.server {
const projectRootPath = this.openFiles.get(info.path);
let searchPath = asNormalizedPath(getDirectoryPath(info.fileName));
const isSearchPathInProjectRoot = () => containsPath(projectRootPath, searchPath, this.currentDirectory, !this.host.useCaseSensitiveFileNames);
const isSearchPathInProjectRoot = () => containsPath(projectRootPath!, searchPath, this.currentDirectory, !this.host.useCaseSensitiveFileNames);
// If projectRootPath doesnt contain info.path, then do normal search for config file
const anySearchPathOk = !projectRootPath || !isSearchPathInProjectRoot();
@@ -1310,7 +1310,7 @@ namespace ts.server {
this.logger.info("Open files: ");
this.openFiles.forEach((projectRootPath, path) => {
const info = this.getScriptInfoForPath(path as Path);
const info = this.getScriptInfoForPath(path as Path)!;
this.logger.info(`\tFileName: ${info.fileName} ProjectRootPath: ${projectRootPath}`);
if (writeProjectFileNames) {
this.logger.info(`\t\tProjects: ${info.containingProjects.map(p => p.getProjectName())}`);
@@ -1337,7 +1337,7 @@ namespace ts.server {
private convertConfigFileContentToProjectOptions(configFilename: string, cachedDirectoryStructureHost: CachedDirectoryStructureHost) {
configFilename = normalizePath(configFilename);
const configFileContent = this.host.readFile(configFilename);
const configFileContent = this.host.readFile(configFilename)!; // TODO: GH#18217
const result = parseJsonText(configFilename, configFileContent);
if (!result.endOfFileToken) {
@@ -1366,7 +1366,7 @@ namespace ts.server {
configHasFilesProperty: parsedCommandLine.raw.files !== undefined,
configHasIncludeProperty: parsedCommandLine.raw.include !== undefined,
configHasExcludeProperty: parsedCommandLine.raw.exclude !== undefined,
wildcardDirectories: createMapFromTemplate(parsedCommandLine.wildcardDirectories),
wildcardDirectories: createMapFromTemplate(parsedCommandLine.wildcardDirectories!), // TODO: GH#18217
typeAcquisition: parsedCommandLine.typeAcquisition,
compileOnSave: parsedCommandLine.compileOnSave,
projectReferences: parsedCommandLine.projectReferences
@@ -1376,7 +1376,7 @@ namespace ts.server {
}
/** Get a filename if the language service exceeds the maximum allowed program size; otherwise returns undefined. */
private getFilenameForExceededTotalSizeLimitForNonTsFiles<T>(name: string, options: CompilerOptions, fileNames: T[], propertyReader: FilePropertyReader<T>): string | undefined {
private getFilenameForExceededTotalSizeLimitForNonTsFiles<T>(name: string, options: CompilerOptions | undefined, fileNames: T[], propertyReader: FilePropertyReader<T>): string | undefined {
if (options && options.disableSizeLimit || !this.host.getFileSize) {
return;
}
@@ -1414,7 +1414,7 @@ namespace ts.server {
function getTop5LargestFiles({ propertyReader, hasTypeScriptFileExtension, host }: { propertyReader: FilePropertyReader<any>, hasTypeScriptFileExtension: (filename: string) => boolean, host: ServerHost }) {
return fileNames.map(f => propertyReader.getFileName(f))
.filter(name => hasTypeScriptFileExtension(name))
.map(name => ({ name, size: host.getFileSize(name) }))
.map(name => ({ name, size: host.getFileSize!(name) })) // TODO: GH#18217
.sort((a, b) => b.size - a.size)
.slice(0, 5);
}
@@ -1469,7 +1469,7 @@ namespace ts.server {
return "other";
}
const configFilePath = project instanceof ConfiguredProject && project.getConfigFilePath();
const configFilePath = project instanceof ConfiguredProject ? project.getConfigFilePath() : undefined!; // TODO: GH#18217
return getBaseConfigFileName(configFilePath) || "other";
}
@@ -1490,16 +1490,16 @@ namespace ts.server {
}
private createConfiguredProject(configFileName: NormalizedPath) {
const cachedDirectoryStructureHost = createCachedDirectoryStructureHost(this.host, this.host.getCurrentDirectory(), this.host.useCaseSensitiveFileNames);
const cachedDirectoryStructureHost = createCachedDirectoryStructureHost(this.host, this.host.getCurrentDirectory(), this.host.useCaseSensitiveFileNames)!; // TODO: GH#18217
const { projectOptions, configFileErrors, configFileSpecs } = this.convertConfigFileContentToProjectOptions(configFileName, cachedDirectoryStructureHost);
this.logger.info(`Opened configuration file ${configFileName}`);
const lastFileExceededProgramSize = this.getFilenameForExceededTotalSizeLimitForNonTsFiles(configFileName, projectOptions.compilerOptions, projectOptions.files, fileNamePropertyReader);
const lastFileExceededProgramSize = this.getFilenameForExceededTotalSizeLimitForNonTsFiles(configFileName, projectOptions.compilerOptions, projectOptions.files!, fileNamePropertyReader); // TODO: GH#18217
const project = new ConfiguredProject(
configFileName,
this,
this.documentRegistry,
projectOptions.configHasFilesProperty,
projectOptions.compilerOptions,
projectOptions.compilerOptions!, // TODO: GH#18217
lastFileExceededProgramSize,
projectOptions.compileOnSave === undefined ? false : projectOptions.compileOnSave,
cachedDirectoryStructureHost,
@@ -1516,12 +1516,12 @@ namespace ts.server {
project
);
if (!lastFileExceededProgramSize) {
project.watchWildcards(projectOptions.wildcardDirectories);
project.watchWildcards(projectOptions.wildcardDirectories!); // TODO: GH#18217
}
project.setProjectErrors(configFileErrors);
const filesToAdd = projectOptions.files.concat(project.getExternalFiles());
this.addFilesToNonInferredProjectAndUpdateGraph(project, filesToAdd, fileNamePropertyReader, projectOptions.typeAcquisition);
const filesToAdd = projectOptions.files!.concat(project.getExternalFiles());
this.addFilesToNonInferredProjectAndUpdateGraph(project, filesToAdd, fileNamePropertyReader, projectOptions.typeAcquisition!); // TODO: GH#18217
this.configuredProjects.set(project.canonicalConfigFilePath, project);
this.setConfigFileExistenceByNewConfiguredProject(project);
this.sendProjectTelemetry(configFileName, project, projectOptions);
@@ -1541,7 +1541,7 @@ namespace ts.server {
// Use the project's fileExists so that it can use caching instead of reaching to disk for the query
if (!isDynamic && !project.fileExists(newRootFile)) {
path = normalizedPathToPath(normalizedPath, this.currentDirectory, this.toCanonicalFileName);
const existingValue = projectRootFilesMap.get(path);
const existingValue = projectRootFilesMap.get(path)!;
if (isScriptInfo(existingValue)) {
project.removeFile(existingValue, /*fileExists*/ false, /*detachFromProject*/ true);
}
@@ -1551,7 +1551,7 @@ namespace ts.server {
else {
const scriptKind = propertyReader.getScriptKind(f, this.hostConfiguration.extraFileExtensions);
const hasMixedContent = propertyReader.hasMixedContent(f, this.hostConfiguration.extraFileExtensions);
scriptInfo = this.getOrCreateScriptInfoNotOpenedByClientForNormalizedPath(normalizedPath, project.currentDirectory, scriptKind, hasMixedContent, project.directoryStructureHost);
scriptInfo = this.getOrCreateScriptInfoNotOpenedByClientForNormalizedPath(normalizedPath, project.currentDirectory, scriptKind, hasMixedContent, project.directoryStructureHost)!; // TODO: GH#18217
path = scriptInfo.path;
// If this script info is not already a root add it
if (!project.isRoot(scriptInfo)) {
@@ -1586,7 +1586,7 @@ namespace ts.server {
project.markAsDirty();
}
private updateNonInferredProject<T>(project: ExternalProject | ConfiguredProject, newUncheckedFiles: T[], propertyReader: FilePropertyReader<T>, newOptions: CompilerOptions, newTypeAcquisition: TypeAcquisition, compileOnSave: boolean) {
private updateNonInferredProject<T>(project: ExternalProject | ConfiguredProject, newUncheckedFiles: T[], propertyReader: FilePropertyReader<T>, newOptions: CompilerOptions, newTypeAcquisition: TypeAcquisition, compileOnSave: boolean | undefined) {
project.setCompilerOptions(newOptions);
// VS only set the CompileOnSaveEnabled option in the request if the option was changed recently
// therefore if it is undefined, it should not be updated.
@@ -1601,7 +1601,7 @@ namespace ts.server {
*/
/*@internal*/
reloadFileNamesOfConfiguredProject(project: ConfiguredProject): boolean {
const configFileSpecs = project.configFileSpecs;
const configFileSpecs = project.configFileSpecs!; // TODO: GH#18217
const configFileName = project.getConfigFilePath();
const fileNamesResult = getFileNamesFromConfigSpecs(configFileSpecs, getDirectoryPath(configFileName), project.getCompilationSettings(), project.getCachedDirectoryStructureHost(), this.hostConfiguration.extraFileExtensions);
project.updateErrorOnNoInputFiles(fileNamesResult.fileNames.length !== 0);
@@ -1629,16 +1629,16 @@ namespace ts.server {
project.configFileSpecs = configFileSpecs;
project.setProjectErrors(configFileErrors);
project.updateReferences(projectOptions.projectReferences);
const lastFileExceededProgramSize = this.getFilenameForExceededTotalSizeLimitForNonTsFiles(project.canonicalConfigFilePath, projectOptions.compilerOptions, projectOptions.files, fileNamePropertyReader);
const lastFileExceededProgramSize = this.getFilenameForExceededTotalSizeLimitForNonTsFiles(project.canonicalConfigFilePath, projectOptions.compilerOptions, projectOptions.files!, fileNamePropertyReader); // TODO: GH#18217
if (lastFileExceededProgramSize) {
project.disableLanguageService(lastFileExceededProgramSize);
project.stopWatchingWildCards();
}
else {
project.enableLanguageService();
project.watchWildcards(projectOptions.wildcardDirectories);
project.watchWildcards(projectOptions.wildcardDirectories!); // TODO: GH#18217
}
this.updateNonInferredProject(project, projectOptions.files, fileNamePropertyReader, projectOptions.compilerOptions, projectOptions.typeAcquisition, projectOptions.compileOnSave);
this.updateNonInferredProject(project, projectOptions.files!, fileNamePropertyReader, projectOptions.compilerOptions!, projectOptions.typeAcquisition!, projectOptions.compileOnSave!); // TODO: GH#18217
this.sendConfigFileDiagEvent(project, configFileName);
}
@@ -1671,7 +1671,7 @@ namespace ts.server {
// we don't have an explicit root path, so we should try to find an inferred project
// that more closely contains the file.
let bestMatch: InferredProject;
let bestMatch: InferredProject | undefined;
for (const project of this.inferredProjects) {
// ignore single inferred projects (handled elsewhere)
if (!project.projectRootPath) continue;
@@ -1679,7 +1679,7 @@ namespace ts.server {
if (!containsPath(project.projectRootPath, info.path, this.host.getCurrentDirectory(), !this.host.useCaseSensitiveFileNames)) continue;
// ignore inferred projects that are higher up in the project root.
// TODO(rbuckton): Should we add the file as a root to these as well?
if (bestMatch && bestMatch.projectRootPath.length > project.projectRootPath.length) continue;
if (bestMatch && bestMatch.projectRootPath!.length > project.projectRootPath.length) continue;
bestMatch = project;
}
@@ -1837,7 +1837,7 @@ namespace ts.server {
if (!openedByClient && !isDynamic && !(hostToQueryFileExistsOn || this.host).fileExists(fileName)) {
return;
}
info = new ScriptInfo(this.host, fileName, scriptKind, hasMixedContent, path);
info = new ScriptInfo(this.host, fileName, scriptKind!, !!hasMixedContent, path); // TODO: GH#18217
this.filenameToScriptInfo.set(info.path, info);
if (!openedByClient) {
this.watchClosedScriptInfo(info);
@@ -1851,7 +1851,7 @@ namespace ts.server {
// Opening closed script info
// either it was created just now, or was part of projects but was closed
this.stopWatchingScriptInfo(info);
info.open(fileContent);
info.open(fileContent!);
if (hasMixedContent) {
info.registerFileUpdate();
}
@@ -1878,7 +1878,7 @@ namespace ts.server {
if (args.file) {
const info = this.getScriptInfoForNormalizedPath(toNormalizedPath(args.file));
if (info) {
info.setOptions(convertFormatOptions(args.formatOptions), args.preferences);
info.setOptions(convertFormatOptions(args.formatOptions!), args.preferences);
this.logger.info(`Host configuration update for file ${args.file}`);
}
}
@@ -1952,7 +1952,7 @@ namespace ts.server {
return;
}
const info = this.getScriptInfoForPath(path as Path);
const info = this.getScriptInfoForPath(path as Path)!; // TODO: GH#18217
Debug.assert(info.isScriptOpen());
// This tries to search for a tsconfig.json for the given file. If we found it,
// we first detect if there is already a configured project created for it: if so,
@@ -2020,7 +2020,7 @@ namespace ts.server {
this.printProjects();
this.openFiles.forEach((projectRootPath, path) => {
const info = this.getScriptInfoForPath(path as Path);
const info = this.getScriptInfoForPath(path as Path)!;
// collect all orphaned script infos from open files
if (info.isOrphan()) {
this.assignOrphanScriptInfoToInferredProject(info, projectRootPath);
@@ -2055,10 +2055,10 @@ namespace ts.server {
}
openClientFileWithNormalizedPath(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, projectRootPath?: NormalizedPath): OpenConfiguredProjectResult {
let configFileName: NormalizedPath;
let configFileErrors: ReadonlyArray<Diagnostic>;
let configFileName: NormalizedPath | undefined;
let configFileErrors: ReadonlyArray<Diagnostic> | undefined;
const info = this.getOrCreateScriptInfoOpenedByClientForNormalizedPath(fileName, projectRootPath ? this.getNormalizedAbsolutePath(projectRootPath) : this.currentDirectory, fileContent, scriptKind, hasMixedContent);
const info = this.getOrCreateScriptInfoOpenedByClientForNormalizedPath(fileName, projectRootPath ? this.getNormalizedAbsolutePath(projectRootPath) : this.currentDirectory, fileContent, scriptKind, hasMixedContent)!; // TODO: GH#18217
this.openFiles.set(info.path, projectRootPath);
let project: ConfiguredProject | ExternalProject | undefined = this.findExternalProjectContainingOpenScriptInfo(info);
if (!project && !this.syntaxOnly) { // Checking syntaxOnly is an optimization
@@ -2100,7 +2100,6 @@ namespace ts.server {
}
Debug.assert(!info.isOrphan());
// Remove the configured projects that have zero references from open files.
// This was postponed from closeOpenFile to after opening next file,
// so that we can reuse the project if we need to right away
@@ -2141,7 +2140,7 @@ namespace ts.server {
return;
}
const info: OpenFileInfo = { checkJs: !!scriptInfo.getDefaultProject().getSourceFile(scriptInfo.path).checkJsDirective };
const info: OpenFileInfo = { checkJs: !!scriptInfo.getDefaultProject().getSourceFile(scriptInfo.path)!.checkJsDirective };
this.eventHandler({ eventName: OpenFileInfoTelemetryEvent, data: { info } });
}
@@ -2159,7 +2158,7 @@ namespace ts.server {
private collectChanges(lastKnownProjectVersions: protocol.ProjectVersionInfo[], currentProjects: Project[], result: ProjectFilesWithTSDiagnostics[]): void {
for (const proj of currentProjects) {
const knownProject = forEach(lastKnownProjectVersions, p => p.projectName === proj.getProjectName() && p);
const knownProject = find(lastKnownProjectVersions, p => p.projectName === proj.getProjectName());
result.push(proj.getChangesSinceVersion(knownProject && knownProject.version));
}
}
@@ -2174,19 +2173,19 @@ namespace ts.server {
}
/* @internal */
applyChangesInOpenFiles(openFiles: protocol.ExternalFile[], changedFiles: protocol.ChangedOpenFile[], closedFiles: string[]): void {
applyChangesInOpenFiles(openFiles: protocol.ExternalFile[] | undefined, changedFiles: protocol.ChangedOpenFile[] | undefined, closedFiles: string[] | undefined): void {
if (openFiles) {
for (const file of openFiles) {
const scriptInfo = this.getScriptInfo(file.fileName);
Debug.assert(!scriptInfo || !scriptInfo.isScriptOpen(), "Script should not exist and not be open already");
const normalizedPath = scriptInfo ? scriptInfo.fileName : toNormalizedPath(file.fileName);
this.openClientFileWithNormalizedPath(normalizedPath, file.content, tryConvertScriptKindName(file.scriptKind), file.hasMixedContent);
this.openClientFileWithNormalizedPath(normalizedPath, file.content, tryConvertScriptKindName(file.scriptKind!), file.hasMixedContent); // TODO: GH#18217
}
}
if (changedFiles) {
for (const file of changedFiles) {
const scriptInfo = this.getScriptInfo(file.fileName);
const scriptInfo = this.getScriptInfo(file.fileName)!;
Debug.assert(!!scriptInfo);
this.applyChangesToFile(scriptInfo, file.changes);
}
@@ -2267,7 +2266,8 @@ namespace ts.server {
}
applySafeList(proj: protocol.ExternalProject): NormalizedPath[] {
const { rootFiles, typeAcquisition } = proj;
const { rootFiles } = proj;
const typeAcquisition = proj.typeAcquisition!;
Debug.assert(!!typeAcquisition, "proj.typeAcquisition should be set by now");
// If type acquisition has been explicitly disabled, do not exclude anything from the project
if (typeAcquisition.enable === false) {
@@ -2390,7 +2390,7 @@ namespace ts.server {
const excludedFiles = this.applySafeList(proj);
let tsConfigFiles: NormalizedPath[];
let tsConfigFiles: NormalizedPath[] | undefined;
const rootFiles: protocol.ExternalFile[] = [];
for (const file of proj.rootFiles) {
const normalized = toNormalizedPath(file.fileName);
@@ -2410,7 +2410,7 @@ namespace ts.server {
}
const externalProject = this.findExternalProjectByProjectName(proj.projectFileName);
let exisingConfigFiles: string[];
let exisingConfigFiles: string[] | undefined;
if (externalProject) {
externalProject.excludedFiles = excludedFiles;
if (!tsConfigFiles) {
@@ -2438,7 +2438,7 @@ namespace ts.server {
}
else {
// project previously had some config files - compare them with new set of files and close all configured projects that correspond to unused files
const oldConfigFiles = this.externalProjectToConfiguredProjectMap.get(proj.projectFileName);
const oldConfigFiles = this.externalProjectToConfiguredProjectMap.get(proj.projectFileName)!;
let iNew = 0;
let iOld = 0;
while (iNew < tsConfigFiles.length && iOld < oldConfigFiles.length) {
@@ -2487,7 +2487,7 @@ namespace ts.server {
}
hasDeferredExtension() {
for (const extension of this.hostConfiguration.extraFileExtensions) {
for (const extension of this.hostConfiguration.extraFileExtensions!) { // TODO: GH#18217
if (extension.scriptKind === ScriptKind.Deferred) {
return true;
}
+42 -42
View File
@@ -103,7 +103,7 @@ namespace ts.server {
cachedUnresolvedImportsPerFile = createMap<ReadonlyArray<string>>();
/*@internal*/
lastCachedUnresolvedImportsList: SortedReadonlyArray<string>;
lastCachedUnresolvedImportsList: SortedReadonlyArray<string> | undefined;
/*@internal*/
private hasAddedorRemovedFiles = false;
@@ -127,7 +127,7 @@ namespace ts.server {
/**
* Set of files names that were updated since the last call to getChangesSinceVersion.
*/
private updatedFileNames: Map<true>;
private updatedFileNames: Map<true> | undefined;
/**
* Set of files that was returned from the last call to getChangesSinceVersion.
*/
@@ -173,7 +173,7 @@ namespace ts.server {
public static resolveModule(moduleName: string, initialDir: string, host: ServerHost, log: (message: string) => void): {} | undefined {
const resolvedPath = normalizeSlashes(host.resolvePath(combinePaths(initialDir, "node_modules")));
log(`Loading ${moduleName} from ${initialDir} (resolved to ${resolvedPath})`);
const result = host.require(resolvedPath, moduleName);
const result = host.require!(resolvedPath, moduleName); // TODO: GH#18217
if (result.error) {
const err = result.error.stack || result.error.message || JSON.stringify(result.error);
log(`Failed to load module '${moduleName}': ${err}`);
@@ -226,11 +226,11 @@ namespace ts.server {
this.trace = s => this.writeLog(s);
}
else if (host.trace) {
this.trace = s => host.trace(s);
this.trace = s => host.trace!(s);
}
if (host.realpath) {
this.realpath = path => host.realpath(path);
this.realpath = path => host.realpath!(path);
}
// Use the current directory as resolution root only if the project created using current directory string
@@ -307,15 +307,15 @@ namespace ts.server {
getScriptKind(fileName: string) {
const info = this.getOrCreateScriptInfoAndAttachToProject(fileName);
return info && info.scriptKind;
return (info && info.scriptKind)!; // TODO: GH#18217
}
getScriptVersion(filename: string) {
const info = this.getOrCreateScriptInfoAndAttachToProject(filename);
return info && info.getLatestVersion();
return (info && info.getLatestVersion())!; // TODO: GH#18217
}
getScriptSnapshot(filename: string): IScriptSnapshot {
getScriptSnapshot(filename: string): IScriptSnapshot | undefined {
const scriptInfo = this.getOrCreateScriptInfoAndAttachToProject(filename);
if (scriptInfo) {
return scriptInfo.getSnapshot();
@@ -340,7 +340,7 @@ namespace ts.server {
}
readDirectory(path: string, extensions?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>, depth?: number): string[] {
return this.directoryStructureHost.readDirectory(path, extensions, exclude, include, depth);
return this.directoryStructureHost.readDirectory!(path, extensions, exclude, include, depth);
}
readFile(fileName: string): string | undefined {
@@ -358,7 +358,7 @@ namespace ts.server {
return this.resolutionCache.resolveModuleNames(moduleNames, containingFile, reusedNames);
}
getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string): ResolvedModuleWithFailedLookupLocations {
getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string): ResolvedModuleWithFailedLookupLocations | undefined {
return this.resolutionCache.getResolvedModuleWithFailedLookupLocationsFromCache(moduleName, containingFile);
}
@@ -367,16 +367,16 @@ namespace ts.server {
}
directoryExists(path: string): boolean {
return this.directoryStructureHost.directoryExists(path);
return this.directoryStructureHost.directoryExists!(path); // TODO: GH#18217
}
getDirectories(path: string): string[] {
return this.directoryStructureHost.getDirectories(path);
return this.directoryStructureHost.getDirectories!(path); // TODO: GH#18217
}
/*@internal*/
getCachedDirectoryStructureHost(): CachedDirectoryStructureHost {
return undefined;
return undefined!; // TODO: GH#18217
}
/*@internal*/
@@ -471,8 +471,8 @@ namespace ts.server {
}
this.updateGraph();
this.builderState = BuilderState.create(this.program, this.projectService.toCanonicalFileName, this.builderState);
return mapDefined(BuilderState.getFilesAffectedBy(this.builderState, this.program, scriptInfo.path, this.cancellationToken, data => this.projectService.host.createHash(data)),
sourceFile => this.shouldEmitFile(this.projectService.getScriptInfoForPath(sourceFile.path)) ? sourceFile.fileName : undefined);
return mapDefined(BuilderState.getFilesAffectedBy(this.builderState, this.program, scriptInfo.path, this.cancellationToken, data => this.projectService.host.createHash!(data)), // TODO: GH#18217
sourceFile => this.shouldEmitFile(this.projectService.getScriptInfoForPath(sourceFile.path)!) ? sourceFile.fileName : undefined);
}
/**
@@ -567,25 +567,25 @@ namespace ts.server {
}
this.projectService.pendingEnsureProjectForOpenFiles = true;
this.rootFiles = undefined;
this.rootFilesMap = undefined;
this.externalFiles = undefined;
this.program = undefined;
this.builderState = undefined;
this.rootFiles = undefined!;
this.rootFilesMap = undefined!;
this.externalFiles = undefined!;
this.program = undefined!;
this.builderState = undefined!;
this.resolutionCache.clear();
this.resolutionCache = undefined;
this.cachedUnresolvedImportsPerFile = undefined;
this.directoryStructureHost = undefined;
this.resolutionCache = undefined!;
this.cachedUnresolvedImportsPerFile = undefined!;
this.directoryStructureHost = undefined!;
// Clean up file watchers waiting for missing files
if (this.missingFilesMap) {
clearMap(this.missingFilesMap, closeFileWatcher);
this.missingFilesMap = undefined;
this.missingFilesMap = undefined!;
}
// signal language service to release source files acquired from document registry
this.languageService.dispose();
this.languageService = undefined;
this.languageService = undefined!;
}
private detachScriptInfoIfNotRoot(uncheckedFilename: string) {
@@ -623,17 +623,15 @@ namespace ts.server {
return this.rootFiles;
}
getScriptInfos() {
getScriptInfos(): ScriptInfo[] {
if (!this.languageServiceEnabled) {
// if language service is not enabled - return just root files
return this.rootFiles;
}
return map(this.program.getSourceFiles(), sourceFile => {
const scriptInfo = this.projectService.getScriptInfoForPath(sourceFile.path);
if (!scriptInfo) {
Debug.fail(`scriptInfo for a file '${sourceFile.fileName}' Path: '${sourceFile.path}' is missing.`);
}
return scriptInfo;
Debug.assert(!!scriptInfo, "getScriptInfo", () => `scriptInfo for a file '${sourceFile.fileName}' Path: '${sourceFile.path}' is missing.`);
return scriptInfo!;
});
}
@@ -701,11 +699,12 @@ namespace ts.server {
return this.isRoot(info) || (this.program && this.program.getSourceFileByPath(info.path) !== undefined);
}
containsFile(filename: NormalizedPath, requireOpen?: boolean) {
containsFile(filename: NormalizedPath, requireOpen?: boolean): boolean {
const info = this.projectService.getScriptInfoForPath(this.toPath(filename));
if (info && (info.isScriptOpen() || !requireOpen)) {
return this.containsScriptInfo(info);
}
return false;
}
isRoot(info: ScriptInfo) {
@@ -879,7 +878,7 @@ namespace ts.server {
const start = timestamp();
this.hasInvalidatedResolution = this.resolutionCache.createHasInvalidatedResolution();
this.resolutionCache.startCachingPerDirectoryResolution();
this.program = this.languageService.getProgram();
this.program = this.languageService.getProgram()!; // TODO: GH#18217
this.dirty = false;
this.resolutionCache.finishCachingPerDirectoryResolution();
@@ -888,7 +887,7 @@ namespace ts.server {
// bump up the version if
// - oldProgram is not set - this is a first time updateGraph is called
// - newProgram is different from the old program and structure of the old program was not reused.
const hasNewProgram = this.program && (!oldProgram || (this.program !== oldProgram && !(oldProgram.structureIsReused & StructureIsReused.Completely)));
const hasNewProgram = this.program && (!oldProgram || (this.program !== oldProgram && !(oldProgram.structureIsReused! & StructureIsReused.Completely)));
this.hasChangedAutomaticTypeDirectiveNames = false;
if (hasNewProgram) {
if (oldProgram) {
@@ -922,7 +921,7 @@ namespace ts.server {
// by the LSHost for files in the program when the program is retrieved above but
// the program doesn't contain external files so this must be done explicitly.
inserted => {
const scriptInfo = this.projectService.getOrCreateScriptInfoNotOpenedByClient(inserted, this.currentDirectory, this.directoryStructureHost);
const scriptInfo = this.projectService.getOrCreateScriptInfoNotOpenedByClient(inserted, this.currentDirectory, this.directoryStructureHost)!;
scriptInfo.attachToProject(this);
},
removed => this.detachScriptInfoFromProject(removed)
@@ -1212,7 +1211,8 @@ namespace ts.server {
ProjectKind.Inferred,
projectService,
documentRegistry,
/*files*/ undefined,
// TODO: GH#18217
/*files*/ undefined!,
/*lastFileExceededProgramSize*/ undefined,
compilerOptions,
/*compileOnSaveEnabled*/ false,
@@ -1279,7 +1279,7 @@ namespace ts.server {
export class ConfiguredProject extends Project {
private typeAcquisition: TypeAcquisition;
/* @internal */
configFileWatcher: FileWatcher;
configFileWatcher: FileWatcher | undefined;
private directoriesWatchedForWildcards: Map<WildcardDirectoryWatcher> | undefined;
readonly canonicalConfigFilePath: NormalizedPath;
@@ -1287,12 +1287,12 @@ namespace ts.server {
pendingReload: ConfigFileProgramReloadLevel;
/*@internal*/
configFileSpecs: ConfigFileSpecs;
configFileSpecs: ConfigFileSpecs | undefined;
/** Ref count to the project when opened from external project */
private externalProjectRefCount = 0;
private projectErrors: Diagnostic[];
private projectErrors: Diagnostic[] | undefined;
/*@internal*/
constructor(configFileName: NormalizedPath,
@@ -1473,7 +1473,7 @@ namespace ts.server {
// The project is referenced only if open files impacted by this project are present in this project
return forEachEntry(
configFileExistenceInfo.openFilesImpactedByConfigFile,
(_value, infoPath) => this.containsScriptInfo(this.projectService.getScriptInfoForPath(infoPath as Path))
(_value, infoPath) => this.containsScriptInfo(this.projectService.getScriptInfoForPath(infoPath as Path)!)
) || false;
}
@@ -1484,10 +1484,10 @@ namespace ts.server {
/*@internal*/
updateErrorOnNoInputFiles(hasFileNames: boolean) {
if (hasFileNames) {
filterMutate(this.projectErrors, error => !isErrorNoInputFiles(error));
filterMutate(this.projectErrors!, error => !isErrorNoInputFiles(error)); // TODO: GH#18217
}
else if (!this.configFileSpecs.filesSpecs && !some(this.projectErrors, isErrorNoInputFiles)) {
this.projectErrors.push(getErrorForNoInputFiles(this.configFileSpecs, this.getConfigFilePath()));
else if (!this.configFileSpecs!.filesSpecs && !some(this.projectErrors, isErrorNoInputFiles)) { // TODO: GH#18217
this.projectErrors!.push(getErrorForNoInputFiles(this.configFileSpecs!, this.getConfigFilePath()));
}
}
}
+5 -5
View File
@@ -1201,7 +1201,7 @@ namespace ts.server.protocol {
/**
* Filename of the last file analyzed before disabling the language service. undefined, if the language service is enabled.
*/
lastFileExceededProgramSize: string | undefined;
lastFileExceededProgramSize?: string;
}
/**
@@ -1809,7 +1809,7 @@ namespace ts.server.protocol {
export interface CompletionEntryIdentifier {
name: string;
source: string;
source?: string;
}
/**
@@ -1853,7 +1853,7 @@ namespace ts.server.protocol {
/**
* Optional modifiers for the kind (such as 'public').
*/
kindModifiers: string;
kindModifiers?: string;
/**
* A string that is used for comparing completion items so that they can be ordered. This
* is often the same as the name but may be different in certain circumstances.
@@ -1912,12 +1912,12 @@ namespace ts.server.protocol {
/**
* Documentation strings for the symbol.
*/
documentation: SymbolDisplayPart[];
documentation?: SymbolDisplayPart[];
/**
* JSDoc tags for the symbol.
*/
tags: JSDocTagInfo[];
tags?: JSDocTagInfo[];
/**
* The associated code actions for this entry
+14 -14
View File
@@ -14,11 +14,11 @@ namespace ts.server {
* The script version cache is generated on demand and text is still retained.
* Only on edits to the script version cache, the text will be set to undefined
*/
private text: string;
private text: string | undefined;
/**
* Line map for the text when there is no script version cache present
*/
private lineMap: number[];
private lineMap: number[] | undefined;
private textVersion = 0;
/**
@@ -115,7 +115,7 @@ namespace ts.server {
public getSnapshot(): IScriptSnapshot {
return this.useScriptVersionCacheIfValidOrOpen()
? this.svc.getSnapshot()
? this.svc!.getSnapshot()
: ScriptSnapshot.fromString(this.getOrLoadText());
}
@@ -129,10 +129,10 @@ namespace ts.server {
if (!this.useScriptVersionCacheIfValidOrOpen()) {
const lineMap = this.getLineMap();
const start = lineMap[line]; // -1 since line is 1-based
const end = line + 1 < lineMap.length ? lineMap[line + 1] : this.text.length;
const end = line + 1 < lineMap.length ? lineMap[line + 1] : this.text!.length;
return createTextSpanFromBounds(start, end);
}
return this.svc.lineToTextSpan(line);
return this.svc!.lineToTextSpan(line);
}
/**
@@ -145,7 +145,7 @@ namespace ts.server {
}
// TODO: assert this offset is actually on the line
return this.svc.lineOffsetToPosition(line, offset);
return this.svc!.lineOffsetToPosition(line, offset);
}
positionToLineOffset(position: number): protocol.Location {
@@ -153,7 +153,7 @@ namespace ts.server {
const { line, character } = computeLineAndCharacterOfPosition(this.getLineMap(), position);
return { line: line + 1, offset: character + 1 };
}
return this.svc.positionToLineOffset(position);
return this.svc!.positionToLineOffset(position);
}
private getFileText(tempFileName?: string) {
@@ -188,7 +188,7 @@ namespace ts.server {
Debug.assert(!this.svc || this.pendingReloadFromDisk, "ScriptVersionCache should not be set when reloading from disk");
this.reloadWithFileText();
}
return this.text;
return this.text!;
}
private getLineMap() {
@@ -217,7 +217,7 @@ namespace ts.server {
private preferences: UserPreferences | undefined;
/* @internal */
fileWatcher: FileWatcher;
fileWatcher: FileWatcher | undefined;
private textStorage: TextStorage;
/*@internal*/
@@ -294,7 +294,7 @@ namespace ts.server {
this.realpath = project.toPath(realpath);
// If it is different from this.path, add to the map
if (this.realpath !== this.path) {
project.projectService.realpathToScriptInfos.add(this.realpath, this);
project.projectService.realpathToScriptInfos!.add(this.realpath, this); // TODO: GH#18217
}
}
}
@@ -306,8 +306,8 @@ namespace ts.server {
return this.realpath && this.realpath !== this.path ? this.realpath : undefined;
}
getFormatCodeSettings(): FormatCodeSettings { return this.formatSettings; }
getPreferences(): UserPreferences { return this.preferences; }
getFormatCodeSettings(): FormatCodeSettings | undefined { return this.formatSettings; }
getPreferences(): UserPreferences | undefined { return this.preferences; }
attachToProject(project: Project): boolean {
const isNew = !this.isAttached(project);
@@ -345,7 +345,7 @@ namespace ts.server {
case 2:
if (this.containingProjects[0] === project) {
project.onFileAddedOrRemoved();
this.containingProjects[0] = this.containingProjects.pop();
this.containingProjects[0] = this.containingProjects.pop()!;
}
else if (this.containingProjects[1] === project) {
project.onFileAddedOrRemoved();
@@ -406,7 +406,7 @@ namespace ts.server {
}
}
setOptions(formatSettings: FormatCodeSettings, preferences: UserPreferences): void {
setOptions(formatSettings: FormatCodeSettings, preferences: UserPreferences | undefined): void {
if (formatSettings) {
if (!this.formatSettings) {
this.formatSettings = getDefaultFormatCodeSettings(this.host);
+12 -11
View File
@@ -55,7 +55,7 @@ namespace ts.server {
this.stack = [this.lineIndex.root];
}
insertLines(insertedText: string, suppressTrailingText: boolean) {
insertLines(insertedText: string | undefined, suppressTrailingText: boolean) {
if (suppressTrailingText) {
this.trailingText = "";
}
@@ -72,8 +72,8 @@ namespace ts.server {
lines.pop();
}
}
let branchParent: LineNode;
let lastZeroCount: LineCollection;
let branchParent: LineNode | undefined;
let lastZeroCount: LineCollection | undefined;
for (let k = this.endBranch.length - 1; k >= 0; k--) {
(<LineNode>this.endBranch[k]).updateCounts();
@@ -88,7 +88,7 @@ namespace ts.server {
}
}
if (lastZeroCount) {
branchParent.remove(lastZeroCount);
branchParent!.remove(lastZeroCount);
}
// path at least length two (root and leaf)
@@ -159,7 +159,7 @@ namespace ts.server {
this.lineCollectionAtBranch = lineCollection;
}
let child: LineCollection;
let child: LineCollection | undefined;
function fresh(node: LineCollection): LineCollection {
if (node.isLeaf()) {
return new LineLeaf("");
@@ -332,7 +332,7 @@ namespace ts.server {
if (oldVersion >= this.minVersion) {
const textChangeRanges: TextChangeRange[] = [];
for (let i = oldVersion + 1; i <= newVersion; i++) {
const snap = this.versions[this.versionToIndex(i)];
const snap = this.versions[this.versionToIndex(i)!]; // TODO: GH#18217
for (const textChange of snap.changesSincePreviousVersion) {
textChangeRanges.push(textChange.getTextChangeRange());
}
@@ -370,7 +370,7 @@ namespace ts.server {
return this.index.getLength();
}
getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange {
getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange | undefined {
if (oldSnapshot instanceof LineIndexSnapshot && this.cache === oldSnapshot.cache) {
if (this.version <= oldSnapshot.version) {
return unchangedTextChangeRange;
@@ -397,7 +397,7 @@ namespace ts.server {
return { line: oneBasedLine, offset: zeroBasedColumn + 1 };
}
private positionToColumnAndLineText(position: number): { zeroBasedColumn: number, lineText: string } {
private positionToColumnAndLineText(position: number): { zeroBasedColumn: number, lineText: string | undefined } {
return this.root.charOffsetToLineInfo(1, position);
}
@@ -471,9 +471,10 @@ namespace ts.server {
this.load(LineIndex.linesFromText(newText).lines);
return this;
}
return undefined!; // TODO: GH#18217
}
else {
let checkText: string;
let checkText: string | undefined;
if (this.checkEdits) {
const source = this.getText(0, this.root.charCount());
checkText = source.slice(0, pos) + newText + source.slice(pos + deleteLength);
@@ -499,7 +500,7 @@ namespace ts.server {
const { zeroBasedColumn, lineText } = this.positionToColumnAndLineText(e);
if (zeroBasedColumn === 0) {
// move range end just past line that will merge with previous line
deleteLength += lineText.length;
deleteLength += lineText!.length; // TODO: GH#18217
// store text by appending to end of insertedText
newText = newText ? newText + lineText : lineText;
}
@@ -700,7 +701,7 @@ namespace ts.server {
}
private splitAfter(childIndex: number) {
let splitNode: LineNode;
let splitNode: LineNode | undefined;
const clen = this.children.length;
childIndex++;
const endLength = childIndex;
+20 -19
View File
@@ -1,3 +1,5 @@
// tslint:disable no-unnecessary-type-assertion (TODO: tslint can't find node types)
namespace ts.server {
const childProcess: {
fork(modulePath: string, args: string[], options?: { execArgv: string[], env?: MapLike<string> }): NodeChildProcess;
@@ -38,8 +40,7 @@ namespace ts.server {
return combinePaths(combinePaths(cacheLocation, "typescript"), versionMajorMinor);
}
default:
Debug.fail(`unsupported platform '${process.platform}'`);
return;
return Debug.fail(`unsupported platform '${process.platform}'`);
}
}
@@ -200,7 +201,7 @@ namespace ts.server {
if (this.fd >= 0) {
const buf = new Buffer(s);
// tslint:disable-next-line no-null-keyword
fs.writeSync(this.fd, buf, 0, buf.length, /*position*/ null);
fs.writeSync(this.fd, buf, 0, buf.length, /*position*/ null!); // TODO: GH#18217
}
if (this.traceToConsole) {
console.warn(s);
@@ -230,7 +231,7 @@ namespace ts.server {
// buffer, but we have yet to find a way to retrieve that value.
private static readonly maxActiveRequestCount = 10;
private static readonly requestDelayMillis = 100;
private packageInstalledPromise: { resolve(value: ApplyCodeActionCommandResult): void, reject(reason: any): void };
private packageInstalledPromise: { resolve(value: ApplyCodeActionCommandResult): void, reject(reason: any): void } | undefined;
constructor(
private readonly telemetryEnabled: boolean,
@@ -364,10 +365,10 @@ namespace ts.server {
case ActionPackageInstalled: {
const { success, message } = response;
if (success) {
this.packageInstalledPromise.resolve({ successMessage: message });
this.packageInstalledPromise!.resolve({ successMessage: message });
}
else {
this.packageInstalledPromise.reject(message);
this.packageInstalledPromise!.reject(message);
}
this.packageInstalledPromise = undefined;
@@ -435,7 +436,7 @@ namespace ts.server {
}
while (this.requestQueue.length > 0) {
const queuedRequest = this.requestQueue.shift();
const queuedRequest = this.requestQueue.shift()!;
if (this.requestMap.get(queuedRequest.operationId) === queuedRequest) {
this.requestMap.delete(queuedRequest.operationId);
this.scheduleRequest(queuedRequest);
@@ -468,7 +469,7 @@ namespace ts.server {
}
class IOSession extends Session {
private eventPort: number;
private eventPort: number | undefined;
private eventSocket: NodeSocket | undefined;
private socketEventQueue: { body: any, eventName: string }[] | undefined;
private constructed: boolean | undefined;
@@ -529,7 +530,7 @@ namespace ts.server {
}
event<T extends object>(body: T, eventName: string): void {
Debug.assert(this.constructed, "Should only call `IOSession.prototype.event` on an initialized IOSession");
Debug.assert(!!this.constructed, "Should only call `IOSession.prototype.event` on an initialized IOSession");
if (this.canUseEvents && this.eventPort) {
if (!this.eventSocket) {
@@ -550,7 +551,7 @@ namespace ts.server {
}
private writeToEventSocket(body: object, eventName: string): void {
this.eventSocket.write(formatMessage(toEvent(eventName, body), this.logger, this.byteLength, this.host.newLine), "utf8");
this.eventSocket!.write(formatMessage(toEvent(eventName, body), this.logger, this.byteLength, this.host.newLine), "utf8");
}
exit() {
@@ -578,7 +579,7 @@ namespace ts.server {
logToFile?: boolean;
}
function parseLoggingEnvironmentString(logEnvStr: string): LogOptions {
function parseLoggingEnvironmentString(logEnvStr: string | undefined): LogOptions {
if (!logEnvStr) {
return {};
}
@@ -625,7 +626,7 @@ namespace ts.server {
}
}
function getLogLevel(level: string) {
function getLogLevel(level: string | undefined) {
if (level) {
const l = level.toLowerCase();
for (const name in LogLevel) {
@@ -650,7 +651,7 @@ namespace ts.server {
: undefined;
const logVerbosity = cmdLineVerbosity || envLogOptions.detailLevel;
return new Logger(logFileName, envLogOptions.traceToConsole, logVerbosity);
return new Logger(logFileName!, envLogOptions.traceToConsole!, logVerbosity!); // TODO: GH#18217
}
// This places log file in the directory containing editorServices.js
// TODO: check that this location is writable
@@ -765,11 +766,11 @@ namespace ts.server {
function setCanWriteFlagAndWriteMessageIfNecessary() {
canWrite = true;
if (pending.length) {
writeMessage(pending.shift());
writeMessage(pending.shift()!);
}
}
function extractWatchDirectoryCacheKey(path: string, currentDriveKey: string) {
function extractWatchDirectoryCacheKey(path: string, currentDriveKey: string | undefined) {
path = normalizeSlashes(path);
if (isUNCPath(path)) {
// UNC path: extract server name
@@ -804,7 +805,7 @@ namespace ts.server {
const sys = <ServerHost>ts.sys;
const nodeVersion = getNodeMajorVersion();
// use watchGuard process on Windows when node version is 4 or later
const useWatchGuard = process.platform === "win32" && nodeVersion >= 4;
const useWatchGuard = process.platform === "win32" && nodeVersion! >= 4;
const originalWatchDirectory: ServerHost["watchDirectory"] = sys.watchDirectory.bind(sys);
const noopWatcher: FileWatcher = { close: noop };
// This is the function that catches the exceptions when watching directory, and yet lets project service continue to function
@@ -905,8 +906,8 @@ namespace ts.server {
let eventPort: number | undefined;
{
const str = findArgument("--eventPort");
const v = str && parseInt(str);
if (!isNaN(v)) {
const v = str === undefined ? undefined : parseInt(str);
if (v !== undefined && !isNaN(v)) {
eventPort = v;
}
}
@@ -918,7 +919,7 @@ namespace ts.server {
setStackTraceLimit();
const typingSafeListLocation = findArgument(Arguments.TypingSafeListLocation);
const typingSafeListLocation = findArgument(Arguments.TypingSafeListLocation)!; // TODO: GH#18217
const typesMapLocation = findArgument(Arguments.TypesMapLocation) || combinePaths(sys.getExecutingFilePath(), "../typesMap.json");
const npmLocation = findArgument(Arguments.NpmLocation);
+105 -105
View File
@@ -68,10 +68,10 @@ namespace ts.server {
}
function formatDiag(fileName: NormalizedPath, project: Project, diag: Diagnostic): protocol.Diagnostic {
const scriptInfo = project.getScriptInfoForNormalizedPath(fileName);
const scriptInfo = project.getScriptInfoForNormalizedPath(fileName)!; // TODO: GH#18217
return {
start: scriptInfo.positionToLineOffset(diag.start),
end: scriptInfo.positionToLineOffset(diag.start + diag.length),
start: scriptInfo.positionToLineOffset(diag.start!),
end: scriptInfo.positionToLineOffset(diag.start! + diag.length!), // TODO: GH#18217
text: flattenDiagnosticMessageText(diag.messageText, "\n"),
code: diag.code,
category: diagnosticCategoryName(diag),
@@ -87,8 +87,8 @@ namespace ts.server {
function formatConfigFileDiag(diag: Diagnostic, includeFileName: true): protocol.DiagnosticWithFileName;
function formatConfigFileDiag(diag: Diagnostic, includeFileName: false): protocol.Diagnostic;
function formatConfigFileDiag(diag: Diagnostic, includeFileName: boolean): protocol.Diagnostic | protocol.DiagnosticWithFileName {
const start = diag.file && convertToLocation(getLineAndCharacterOfPosition(diag.file, diag.start));
const end = diag.file && convertToLocation(getLineAndCharacterOfPosition(diag.file, diag.start + diag.length));
const start = (diag.file && convertToLocation(getLineAndCharacterOfPosition(diag.file, diag.start!)))!; // TODO: GH#18217
const end = (diag.file && convertToLocation(getLineAndCharacterOfPosition(diag.file, diag.start! + diag.length!)))!; // TODO: GH#18217
const text = flattenDiagnosticMessageText(diag.messageText, "\n");
const { code, source } = diag;
const category = diagnosticCategoryName(diag);
@@ -177,7 +177,7 @@ namespace ts.server {
}
public immediate(action: () => void) {
const requestId = this.requestId;
const requestId = this.requestId!;
Debug.assert(requestId === this.operationHost.getCurrentRequestId(), "immediate: incorrect request id");
this.setImmediateId(this.operationHost.getServerHost().setImmediate(() => {
this.immediateId = undefined;
@@ -186,7 +186,7 @@ namespace ts.server {
}
public delay(ms: number, action: () => void) {
const requestId = this.requestId;
const requestId = this.requestId!;
Debug.assert(requestId === this.operationHost.getCurrentRequestId(), "delay: incorrect request id");
this.setTimerHandle(this.operationHost.getServerHost().setTimeout(() => {
this.timerHandle = undefined;
@@ -223,7 +223,7 @@ namespace ts.server {
this.timerHandle = timerHandle;
}
private setImmediateId(immediateId: number) {
private setImmediateId(immediateId: number | undefined) {
if (this.immediateId !== undefined) {
this.operationHost.getServerHost().clearImmediate(this.immediateId);
}
@@ -319,7 +319,7 @@ namespace ts.server {
protected canUseEvents: boolean;
private suppressDiagnosticEvents?: boolean;
private eventHandler: ProjectServiceEventHandler;
private eventHandler: ProjectServiceEventHandler | undefined;
private readonly noGetErrOnBackgroundUpdate?: boolean;
constructor(opts: SessionOptions) {
@@ -426,7 +426,7 @@ namespace ts.server {
if (err.message) {
msg += ":\n" + indent(err.message);
if ((<StackTraceError>err).stack) {
msg += "\n" + indent((<StackTraceError>err).stack);
msg += "\n" + indent((<StackTraceError>err).stack!);
}
}
this.logger.msg(msg, Msg.Err);
@@ -449,7 +449,7 @@ namespace ts.server {
// For backwards-compatibility only.
/** @deprecated */
public output(info: any, cmdName: string, reqSeq?: number, errorMsg?: string): void {
this.doOutput(info, cmdName, reqSeq, /*success*/ !errorMsg, errorMsg);
this.doOutput(info, cmdName, reqSeq!, /*success*/ !errorMsg, errorMsg); // TODO: GH#18217
}
private doOutput(info: {} | undefined, cmdName: string, reqSeq: number, success: boolean, message?: string): void {
@@ -573,16 +573,16 @@ namespace ts.server {
return project.getLanguageService().getEncodedSemanticClassifications(file, args);
}
private getProject(projectFileName: string) {
return projectFileName && this.projectService.findProject(projectFileName);
private getProject(projectFileName: string | undefined): Project | undefined {
return projectFileName === undefined ? undefined : this.projectService.findProject(projectFileName);
}
private getConfigFileAndProject(args: protocol.FileRequestArgs) {
private getConfigFileAndProject(args: protocol.FileRequestArgs): { configFile: NormalizedPath | undefined, project: Project | undefined } {
const project = this.getProject(args.projectFileName);
const file = toNormalizedPath(args.file);
return {
configFile: project && project.hasConfigFile(file) && file,
configFile: project && project.hasConfigFile(file) ? file : undefined,
project
};
}
@@ -592,7 +592,7 @@ namespace ts.server {
const optionsErrors = project.getLanguageService().getCompilerOptionsDiagnostics();
const diagnosticsForConfigFile = filter(
concatenate(projectErrors, optionsErrors),
diagnostic => diagnostic.file && diagnostic.file.fileName === configFile
diagnostic => !!diagnostic.file && diagnostic.file.fileName === configFile
);
return includeLinePosition ?
this.convertToDiagnosticsWithLinePositionFromDiagnosticFile(diagnosticsForConfigFile) :
@@ -605,17 +605,17 @@ namespace ts.server {
private convertToDiagnosticsWithLinePositionFromDiagnosticFile(diagnostics: ReadonlyArray<Diagnostic>): protocol.DiagnosticWithLinePosition[] {
return diagnostics.map<protocol.DiagnosticWithLinePosition>(d => ({
message: flattenDiagnosticMessageText(d.messageText, this.host.newLine),
start: d.start,
length: d.length,
start: d.start!, // TODO: GH#18217
length: d.length!, // TODO: GH#18217
category: diagnosticCategoryName(d),
code: d.code,
startLocation: d.file && convertToLocation(getLineAndCharacterOfPosition(d.file, d.start)),
endLocation: d.file && convertToLocation(getLineAndCharacterOfPosition(d.file, d.start + d.length))
startLocation: (d.file && convertToLocation(getLineAndCharacterOfPosition(d.file, d.start!)))!, // TODO: GH#18217
endLocation: (d.file && convertToLocation(getLineAndCharacterOfPosition(d.file, d.start! + d.length!)))! // TODO: GH#18217
}));
}
private getCompilerOptionsDiagnostics(args: protocol.CompilerOptionsDiagnosticsRequestArgs) {
const project = this.getProject(args.projectFileName);
const project = this.getProject(args.projectFileName)!;
// Get diagnostics that dont have associated file with them
// The diagnostics which have file would be in config file and
// would be reported as part of configFileDiagnostics
@@ -628,7 +628,7 @@ namespace ts.server {
);
}
private convertToDiagnosticsWithLinePosition(diagnostics: ReadonlyArray<Diagnostic>, scriptInfo: ScriptInfo): protocol.DiagnosticWithLinePosition[] {
private convertToDiagnosticsWithLinePosition(diagnostics: ReadonlyArray<Diagnostic>, scriptInfo: ScriptInfo | undefined): protocol.DiagnosticWithLinePosition[] {
return diagnostics.map(d => <protocol.DiagnosticWithLinePosition>{
message: flattenDiagnosticMessageText(d.messageText, this.host.newLine),
start: d.start,
@@ -636,8 +636,8 @@ namespace ts.server {
category: diagnosticCategoryName(d),
code: d.code,
source: d.source,
startLocation: scriptInfo && scriptInfo.positionToLineOffset(d.start),
endLocation: scriptInfo && scriptInfo.positionToLineOffset(d.start + d.length),
startLocation: scriptInfo && scriptInfo.positionToLineOffset(d.start!), // TODO: GH#18217
endLocation: scriptInfo && scriptInfo.positionToLineOffset(d.start! + d.length!),
reportsUnnecessary: d.reportsUnnecessary
});
}
@@ -675,14 +675,14 @@ namespace ts.server {
private getDefinitionAndBoundSpan(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): protocol.DefinitionInfoAndBoundSpan | DefinitionInfoAndBoundSpan {
const { file, project } = this.getFileAndProject(args);
const position = this.getPositionInFile(args, file);
const scriptInfo = project.getScriptInfo(file);
const scriptInfo = project.getScriptInfo(file)!;
const definitionAndBoundSpan = project.getLanguageService().getDefinitionAndBoundSpan(file, position);
if (!definitionAndBoundSpan || !definitionAndBoundSpan.definitions) {
return {
definitions: emptyArray,
textSpan: undefined
textSpan: undefined! // TODO: GH#18217
};
}
@@ -726,8 +726,8 @@ namespace ts.server {
private toFileSpan(fileName: string, textSpan: TextSpan, project: Project): protocol.FileSpan {
const ls = project.getLanguageService();
const start = ls.toLineColumnOffset(fileName, textSpan.start);
const end = ls.toLineColumnOffset(fileName, textSpanEnd(textSpan));
const start = ls.toLineColumnOffset!(fileName, textSpan.start); // TODO: GH#18217
const end = ls.toLineColumnOffset!(fileName, textSpanEnd(textSpan));
return {
file: fileName,
@@ -775,7 +775,7 @@ namespace ts.server {
return occurrences.map(occurrence => {
const { fileName, isWriteAccess, textSpan, isInString } = occurrence;
const scriptInfo = project.getScriptInfo(fileName);
const scriptInfo = project.getScriptInfo(fileName)!;
const result: protocol.OccurrencesResponseItem = {
start: scriptInfo.positionToLineOffset(textSpan.start),
end: scriptInfo.positionToLineOffset(textSpanEnd(textSpan)),
@@ -797,15 +797,15 @@ namespace ts.server {
return emptyArray;
}
return this.getDiagnosticsWorker(args, /*isSemantic*/ false, (project, file) => project.getLanguageService().getSyntacticDiagnostics(file), args.includeLinePosition);
return this.getDiagnosticsWorker(args, /*isSemantic*/ false, (project, file) => project.getLanguageService().getSyntacticDiagnostics(file), !!args.includeLinePosition);
}
private getSemanticDiagnosticsSync(args: protocol.SemanticDiagnosticsSyncRequestArgs): ReadonlyArray<protocol.Diagnostic> | ReadonlyArray<protocol.DiagnosticWithLinePosition> {
const { configFile, project } = this.getConfigFileAndProject(args);
if (configFile) {
return this.getConfigFileDiagnostics(configFile, project, args.includeLinePosition);
return this.getConfigFileDiagnostics(configFile, project!, !!args.includeLinePosition); // TODO: GH#18217
}
return this.getDiagnosticsWorker(args, /*isSemantic*/ true, (project, file) => project.getLanguageService().getSemanticDiagnostics(file), args.includeLinePosition);
return this.getDiagnosticsWorker(args, /*isSemantic*/ true, (project, file) => project.getLanguageService().getSemanticDiagnostics(file), !!args.includeLinePosition);
}
private getSuggestionDiagnosticsSync(args: protocol.SuggestionDiagnosticsSyncRequestArgs): ReadonlyArray<protocol.Diagnostic> | ReadonlyArray<protocol.DiagnosticWithLinePosition> {
@@ -815,7 +815,7 @@ namespace ts.server {
return emptyArray;
}
// isSemantic because we don't want to info diagnostics in declaration files for JS-only users
return this.getDiagnosticsWorker(args, /*isSemantic*/ true, (project, file) => project.getLanguageService().getSuggestionDiagnostics(file), args.includeLinePosition);
return this.getDiagnosticsWorker(args, /*isSemantic*/ true, (project, file) => project.getLanguageService().getSuggestionDiagnostics(file), !!args.includeLinePosition);
}
private getDocumentHighlights(args: protocol.DocumentHighlightsRequestArgs, simplifiedResult: boolean): ReadonlyArray<protocol.DocumentHighlightsItem> | ReadonlyArray<DocumentHighlights> {
@@ -837,7 +837,7 @@ namespace ts.server {
function convertToDocumentHighlightsItem(documentHighlights: DocumentHighlights): protocol.DocumentHighlightsItem {
const { fileName, highlightSpans } = documentHighlights;
const scriptInfo = project.getScriptInfo(fileName);
const scriptInfo = project.getScriptInfo(fileName)!;
return {
file: fileName,
highlightSpans: highlightSpans.map(convertHighlightSpan)
@@ -860,7 +860,7 @@ namespace ts.server {
return this.getProjectInfoWorker(args.file, args.projectFileName, args.needFileNameList, /*excludeConfigFiles*/ false);
}
private getProjectInfoWorker(uncheckedFileName: string, projectFileName: string, needFileNameList: boolean, excludeConfigFiles: boolean) {
private getProjectInfoWorker(uncheckedFileName: string, projectFileName: string | undefined, needFileNameList: boolean, excludeConfigFiles: boolean) {
const { project } = this.getFileAndProjectWorker(uncheckedFileName, projectFileName);
project.updateGraph();
const projectInfo = {
@@ -878,7 +878,7 @@ namespace ts.server {
}
private getProjects(args: protocol.FileRequestArgs): Projects {
let projects: ReadonlyArray<Project>;
let projects: ReadonlyArray<Project> | undefined;
let symLinkedProjects: MultiMap<Project> | undefined;
if (args.projectFileName) {
const project = this.getProject(args.projectFileName);
@@ -887,7 +887,7 @@ namespace ts.server {
}
}
else {
const scriptInfo = this.projectService.getScriptInfo(args.file);
const scriptInfo = this.projectService.getScriptInfo(args.file)!;
projects = scriptInfo.containingProjects;
symLinkedProjects = this.projectService.getSymlinkedProjects(scriptInfo);
}
@@ -896,7 +896,7 @@ namespace ts.server {
if ((!projects || !projects.length) && !symLinkedProjects) {
return Errors.ThrowNoProject();
}
return symLinkedProjects ? { projects, symLinkedProjects } : projects;
return symLinkedProjects ? { projects: projects!, symLinkedProjects } : projects!; // TODO: GH#18217
}
private getDefaultProject(args: protocol.FileRequestArgs) {
@@ -906,11 +906,11 @@ namespace ts.server {
return project;
}
}
const info = this.projectService.getScriptInfo(args.file);
const info = this.projectService.getScriptInfo(args.file)!;
return info.getDefaultProject();
}
private getRenameLocations(args: protocol.RenameRequestArgs, simplifiedResult: boolean): protocol.RenameResponseBody | ReadonlyArray<RenameLocation> {
private getRenameLocations(args: protocol.RenameRequestArgs, simplifiedResult: boolean): protocol.RenameResponseBody | ReadonlyArray<RenameLocation> | undefined {
const file = toNormalizedPath(args.file);
const position = this.getPositionInFile(args, file);
const projects = this.getProjects(args);
@@ -932,16 +932,16 @@ namespace ts.server {
const fileSpans = combineProjectOutput(
file,
path => this.projectService.getScriptInfoForPath(path).fileName,
path => this.projectService.getScriptInfoForPath(path)!.fileName,
projects,
(project, file) => {
const renameLocations = project.getLanguageService().findRenameLocations(file, position, args.findInStrings, args.findInComments);
const renameLocations = project.getLanguageService().findRenameLocations(file, position, args.findInStrings!, args.findInComments!);
if (!renameLocations) {
return emptyArray;
}
return renameLocations.map(location => {
const locationScriptInfo = project.getScriptInfo(location.fileName);
const locationScriptInfo = project.getScriptInfo(location.fileName)!;
return {
file: location.fileName,
start: locationScriptInfo.positionToLineOffset(location.textSpan.start),
@@ -955,7 +955,7 @@ namespace ts.server {
const locs: protocol.SpanGroup[] = [];
for (const cur of fileSpans) {
let curFileAccum: protocol.SpanGroup;
let curFileAccum: protocol.SpanGroup | undefined;
if (locs.length > 0) {
curFileAccum = locs[locs.length - 1];
if (curFileAccum.file !== cur.file) {
@@ -974,9 +974,9 @@ namespace ts.server {
else {
return combineProjectOutput(
file,
path => this.projectService.getScriptInfoForPath(path).fileName,
path => this.projectService.getScriptInfoForPath(path)!.fileName,
projects,
(p, file) => p.getLanguageService().findRenameLocations(file, position, args.findInStrings, args.findInComments),
(p, file) => p.getLanguageService().findRenameLocations(file, position, args.findInStrings!, args.findInComments!),
/*comparer*/ undefined,
renameLocationIsEqualTo
);
@@ -1021,7 +1021,7 @@ namespace ts.server {
const projects = this.getProjects(args);
const defaultProject = this.getDefaultProject(args);
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file);
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!;
const position = this.getPosition(args, scriptInfo);
if (simplifiedResult) {
const nameInfo = defaultProject.getLanguageService().getQuickInfoAtPosition(file, position);
@@ -1034,7 +1034,7 @@ namespace ts.server {
const nameText = scriptInfo.getSnapshot().getText(nameSpan.start, textSpanEnd(nameSpan));
const refs = combineProjectOutput<NormalizedPath, protocol.ReferencesResponseItem>(
file,
path => this.projectService.getScriptInfoForPath(path).fileName,
path => this.projectService.getScriptInfoForPath(path)!.fileName,
projects,
(project, file) => {
const references = project.getLanguageService().getReferencesAtPosition(file, position);
@@ -1043,7 +1043,7 @@ namespace ts.server {
}
return references.map(ref => {
const refScriptInfo = project.getScriptInfo(ref.fileName);
const refScriptInfo = project.getScriptInfo(ref.fileName)!;
const start = refScriptInfo.positionToLineOffset(ref.textSpan.start);
const refLineSpan = refScriptInfo.lineToTextSpan(start.line - 1);
const lineText = refScriptInfo.getSnapshot().getText(refLineSpan.start, textSpanEnd(refLineSpan)).replace(/\r|\n/g, "");
@@ -1071,7 +1071,7 @@ namespace ts.server {
else {
return combineProjectOutput(
file,
path => this.projectService.getScriptInfoForPath(path).fileName,
path => this.projectService.getScriptInfoForPath(path)!.fileName,
projects,
(project, file) => project.getLanguageService().findReferences(file, position),
/*comparer*/ undefined,
@@ -1102,11 +1102,11 @@ namespace ts.server {
}
private getPositionInFile(args: protocol.FileLocationRequestArgs, file: NormalizedPath): number {
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file);
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!;
return this.getPosition(args, scriptInfo);
}
private getFileAndProject(args: protocol.FileRequestArgs) {
private getFileAndProject(args: protocol.FileRequestArgs): { file: NormalizedPath, project: Project } {
return this.getFileAndProjectWorker(args.file, args.projectFileName);
}
@@ -1124,9 +1124,9 @@ namespace ts.server {
};
}
private getFileAndProjectWorker(uncheckedFileName: string, projectFileName: string) {
private getFileAndProjectWorker(uncheckedFileName: string, projectFileName: string | undefined): { file: NormalizedPath, project: Project } {
const file = toNormalizedPath(uncheckedFileName);
const project: Project = this.getProject(projectFileName) || this.projectService.getDefaultProjectForFile(file, /*ensureProject*/ true);
const project = this.getProject(projectFileName) || this.projectService.getDefaultProjectForFile(file, /*ensureProject*/ true)!; // TODO: GH#18217
return { file, project };
}
@@ -1134,7 +1134,7 @@ namespace ts.server {
const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args);
const spans = languageService.getOutliningSpans(file);
if (simplifiedResult) {
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file);
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!;
return spans.map(s => ({
textSpan: this.toLocationTextSpan(s.textSpan, scriptInfo),
hintSpan: this.toLocationTextSpan(s.hintSpan, scriptInfo),
@@ -1192,9 +1192,9 @@ namespace ts.server {
return languageService.isValidBraceCompletionAtPosition(file, position, args.openingBrace.charCodeAt(0));
}
private getQuickInfoWorker(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): protocol.QuickInfoResponseBody | QuickInfo {
private getQuickInfoWorker(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): protocol.QuickInfoResponseBody | QuickInfo | undefined {
const { file, project } = this.getFileAndProject(args);
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file);
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!;
const quickInfo = project.getLanguageService().getQuickInfoAtPosition(file, this.getPosition(args, scriptInfo));
if (!quickInfo) {
return undefined;
@@ -1219,9 +1219,9 @@ namespace ts.server {
}
}
private getFormattingEditsForRange(args: protocol.FormatRequestArgs): protocol.CodeEdit[] {
private getFormattingEditsForRange(args: protocol.FormatRequestArgs): protocol.CodeEdit[] | undefined {
const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args);
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file);
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!;
const startPosition = scriptInfo.lineOffsetToPosition(args.line, args.offset);
const endPosition = scriptInfo.lineOffsetToPosition(args.endLine, args.endOffset);
@@ -1238,7 +1238,7 @@ namespace ts.server {
private getFormattingEditsForRangeFull(args: protocol.FormatRequestArgs) {
const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args);
const options = args.options ? convertFormatOptions(args.options) : this.getFormatOptions(file);
return languageService.getFormattingEditsForRange(file, args.position, args.endPosition, options);
return languageService.getFormattingEditsForRange(file, args.position!, args.endPosition!, options); // TODO: GH#18217
}
private getFormattingEditsForDocumentFull(args: protocol.FormatRequestArgs) {
@@ -1250,12 +1250,12 @@ namespace ts.server {
private getFormattingEditsAfterKeystrokeFull(args: protocol.FormatOnKeyRequestArgs) {
const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args);
const options = args.options ? convertFormatOptions(args.options) : this.getFormatOptions(file);
return languageService.getFormattingEditsAfterKeystroke(file, args.position, args.key, options);
return languageService.getFormattingEditsAfterKeystroke(file, args.position!, args.key, options); // TODO: GH#18217
}
private getFormattingEditsAfterKeystroke(args: protocol.FormatOnKeyRequestArgs): protocol.CodeEdit[] {
private getFormattingEditsAfterKeystroke(args: protocol.FormatOnKeyRequestArgs): protocol.CodeEdit[] | undefined {
const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args);
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file);
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!;
const position = scriptInfo.lineOffsetToPosition(args.line, args.offset);
const formatOptions = this.getFormatOptions(file);
const edits = languageService.getFormattingEditsAfterKeystroke(file, position, args.key,
@@ -1277,7 +1277,7 @@ namespace ts.server {
hasIndent++;
}
else if (lineText.charAt(i) === "\t") {
hasIndent += formatOptions.tabSize;
hasIndent += formatOptions.tabSize!; // TODO: GH#18217
}
else {
break;
@@ -1310,7 +1310,7 @@ namespace ts.server {
private getCompletions(args: protocol.CompletionsRequestArgs, simplifiedResult: boolean): ReadonlyArray<protocol.CompletionEntry> | CompletionInfo | undefined {
const prefix = args.prefix || "";
const { file, project } = this.getFileAndProject(args);
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file);
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!;
const position = this.getPosition(args, scriptInfo);
const completions = project.getLanguageService().getCompletionsAtPosition(file, position, {
@@ -1321,7 +1321,7 @@ namespace ts.server {
});
if (simplifiedResult) {
return mapDefined<CompletionEntry, protocol.CompletionEntry>(completions && completions.entries, entry => {
if (completions.isMemberCompletion || startsWith(entry.name.toLowerCase(), prefix.toLowerCase())) {
if (completions!.isMemberCompletion || startsWith(entry.name.toLowerCase(), prefix.toLowerCase())) {
const { name, kind, kindModifiers, sortText, insertText, replacementSpan, hasAction, source, isRecommended } = entry;
const convertedSpan = replacementSpan ? this.toLocationTextSpan(replacementSpan, scriptInfo) : undefined;
// Use `hasAction || undefined` to avoid serializing `false`.
@@ -1336,7 +1336,7 @@ namespace ts.server {
private getCompletionEntryDetails(args: protocol.CompletionDetailsRequestArgs, simplifiedResult: boolean): ReadonlyArray<protocol.CompletionEntryDetails> | ReadonlyArray<CompletionEntryDetails> {
const { file, project } = this.getFileAndProject(args);
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file);
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!;
const position = this.getPosition(args, scriptInfo);
const formattingOptions = project.projectService.getFormatCodeOptions(file);
@@ -1356,14 +1356,14 @@ namespace ts.server {
}
// if specified a project, we only return affected file list in this project
const projects = args.projectFileName ? [this.projectService.findProject(args.projectFileName)] : info.containingProjects;
const projects = args.projectFileName ? [this.projectService.findProject(args.projectFileName)!] : info.containingProjects;
const symLinkedProjects = !args.projectFileName && this.projectService.getSymlinkedProjects(info);
return combineProjectOutput(
info,
path => this.projectService.getScriptInfoForPath(path),
path => this.projectService.getScriptInfoForPath(path)!,
symLinkedProjects ? { projects, symLinkedProjects } : projects,
(project, info) => {
let result: protocol.CompileOnSaveAffectedFileListSingleProject;
let result: protocol.CompileOnSaveAffectedFileListSingleProject | undefined;
if (project.compileOnSaveEnabled && project.languageServiceEnabled && !project.isOrphan() && !project.getCompilationSettings().noEmit) {
result = {
projectFileName: project.getProjectName(),
@@ -1384,13 +1384,13 @@ namespace ts.server {
if (!project.languageServiceEnabled) {
return false;
}
const scriptInfo = project.getScriptInfo(file);
const scriptInfo = project.getScriptInfo(file)!;
return project.emitFile(scriptInfo, (path, data, writeByteOrderMark) => this.host.writeFile(path, data, writeByteOrderMark));
}
private getSignatureHelpItems(args: protocol.SignatureHelpRequestArgs, simplifiedResult: boolean): protocol.SignatureHelpItems | SignatureHelpItems {
private getSignatureHelpItems(args: protocol.SignatureHelpRequestArgs, simplifiedResult: boolean): protocol.SignatureHelpItems | SignatureHelpItems | undefined {
const { file, project } = this.getFileAndProject(args);
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file);
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!;
const position = this.getPosition(args, scriptInfo);
const helpItems = project.getLanguageService().getSignatureHelpItems(file, position);
if (!helpItems) {
@@ -1435,7 +1435,7 @@ namespace ts.server {
}
private change(args: protocol.ChangeRequestArgs) {
const scriptInfo = this.projectService.getScriptInfo(args.file);
const scriptInfo = this.projectService.getScriptInfo(args.file)!;
Debug.assert(!!scriptInfo);
const start = scriptInfo.lineOffsetToPosition(args.line, args.offset);
const end = scriptInfo.lineOffsetToPosition(args.endLine, args.endOffset);
@@ -1443,14 +1443,14 @@ namespace ts.server {
this.changeSeq++;
this.projectService.applyChangesToFile(scriptInfo, [{
span: { start, length: end - start },
newText: args.insertString
newText: args.insertString! // TODO: GH#18217
}]);
}
}
private reload(args: protocol.ReloadRequestArgs, reqSeq: number) {
const file = toNormalizedPath(args.file);
const tempFileName = args.tmpfile && toNormalizedPath(args.tmpfile);
const tempFileName = args.tmpfile === undefined ? undefined : toNormalizedPath(args.tmpfile);
const info = this.projectService.getScriptInfoForNormalizedPath(file);
if (info) {
this.changeSeq++;
@@ -1487,13 +1487,13 @@ namespace ts.server {
}));
}
private getNavigationBarItems(args: protocol.FileRequestArgs, simplifiedResult: boolean): protocol.NavigationBarItem[] | NavigationBarItem[] {
private getNavigationBarItems(args: protocol.FileRequestArgs, simplifiedResult: boolean): protocol.NavigationBarItem[] | NavigationBarItem[] | undefined {
const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args);
const items = languageService.getNavigationBarItems(file);
return !items
? undefined
: simplifiedResult
? this.mapLocationNavigationBarItems(items, this.projectService.getScriptInfoForNormalizedPath(file))
? this.mapLocationNavigationBarItems(items, this.projectService.getScriptInfoForNormalizedPath(file)!)
: items;
}
@@ -1514,13 +1514,13 @@ namespace ts.server {
};
}
private getNavigationTree(args: protocol.FileRequestArgs, simplifiedResult: boolean): protocol.NavigationTree | NavigationTree {
private getNavigationTree(args: protocol.FileRequestArgs, simplifiedResult: boolean): protocol.NavigationTree | NavigationTree | undefined {
const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args);
const tree = languageService.getNavigationTree(file);
return !tree
? undefined
: simplifiedResult
? this.toLocationNavigationTree(tree, this.projectService.getScriptInfoForNormalizedPath(file))
? this.toLocationNavigationTree(tree, this.projectService.getScriptInfoForNormalizedPath(file)!)
: tree;
}
@@ -1544,7 +1544,7 @@ namespace ts.server {
}
return navItems.map((navItem) => {
const scriptInfo = project.getScriptInfo(navItem.fileName);
const scriptInfo = project.getScriptInfo(navItem.fileName)!;
const bakedItem: protocol.NavtoItem = {
name: navItem.name,
kind: navItem.kind,
@@ -1624,8 +1624,8 @@ namespace ts.server {
}
private extractPositionAndRange(args: protocol.FileLocationOrRangeRequestArgs, scriptInfo: ScriptInfo): { position: number, textRange: TextRange } {
let position: number;
let textRange: TextRange;
let position: number | undefined;
let textRange: TextRange | undefined;
if (this.isLocation(args)) {
position = getPosition(args);
}
@@ -1633,7 +1633,7 @@ namespace ts.server {
const { startPosition, endPosition } = this.getStartAndEndPosition(args, scriptInfo);
textRange = { pos: startPosition, end: endPosition };
}
return { position, textRange };
return { position: position!, textRange: textRange! }; // TODO: GH#18217
function getPosition(loc: protocol.FileLocationRequestArgs) {
return loc.position !== undefined ? loc.position : scriptInfo.lineOffsetToPosition(loc.line, loc.offset);
@@ -1642,14 +1642,14 @@ namespace ts.server {
private getApplicableRefactors(args: protocol.GetApplicableRefactorsRequestArgs): protocol.ApplicableRefactorInfo[] {
const { file, project } = this.getFileAndProject(args);
const scriptInfo = project.getScriptInfoForNormalizedPath(file);
const scriptInfo = project.getScriptInfoForNormalizedPath(file)!;
const { position, textRange } = this.extractPositionAndRange(args, scriptInfo);
return project.getLanguageService().getApplicableRefactors(file, position || textRange, this.getPreferences(file));
}
private getEditsForRefactor(args: protocol.GetEditsForRefactorRequestArgs, simplifiedResult: boolean): RefactorEditInfo | protocol.RefactorEditInfo {
const { file, project } = this.getFileAndProject(args);
const scriptInfo = project.getScriptInfoForNormalizedPath(file);
const scriptInfo = project.getScriptInfoForNormalizedPath(file)!;
const { position, textRange } = this.extractPositionAndRange(args, scriptInfo);
const result = project.getLanguageService().getEditsForRefactor(
@@ -1671,7 +1671,7 @@ namespace ts.server {
const { renameFilename, renameLocation, edits } = result;
let mappedRenameLocation: protocol.Location | undefined;
if (renameFilename !== undefined && renameLocation !== undefined) {
const renameScriptInfo = project.getScriptInfoForNormalizedPath(toNormalizedPath(renameFilename));
const renameScriptInfo = project.getScriptInfoForNormalizedPath(toNormalizedPath(renameFilename))!;
mappedRenameLocation = getLocationInNewDocument(getSnapshotText(renameScriptInfo.getSnapshot()), renameFilename, renameLocation, edits);
}
return { renameLocation: mappedRenameLocation, renameFilename, edits: this.mapTextChangesToCodeEdits(project, edits) };
@@ -1699,16 +1699,16 @@ namespace ts.server {
return simplifiedResult ? this.mapTextChangesToCodeEdits(project, changes) : changes;
}
private getCodeFixes(args: protocol.CodeFixRequestArgs, simplifiedResult: boolean): ReadonlyArray<protocol.CodeFixAction> | ReadonlyArray<CodeFixAction> {
if (args.errorCodes.length === 0) {
private getCodeFixes(args: protocol.CodeFixRequestArgs, simplifiedResult: boolean): ReadonlyArray<protocol.CodeFixAction> | ReadonlyArray<CodeFixAction> | undefined {
if (args.errorCodes!.length === 0) { // TODO: GH#18217
return undefined;
}
const { file, project } = this.getFileAndProject(args);
const scriptInfo = project.getScriptInfoForNormalizedPath(file);
const scriptInfo = project.getScriptInfoForNormalizedPath(file)!;
const { startPosition, endPosition } = this.getStartAndEndPosition(args, scriptInfo);
const codeActions = project.getLanguageService().getCodeFixesAtPosition(file, startPosition, endPosition, args.errorCodes, this.getFormatOptions(file), this.getPreferences(file));
const codeActions = project.getLanguageService().getCodeFixesAtPosition(file, startPosition, endPosition, args.errorCodes!, this.getFormatOptions(file), this.getPreferences(file));
return simplifiedResult ? codeActions.map(codeAction => this.mapCodeFixAction(project, codeAction)) : codeActions;
}
@@ -1736,7 +1736,7 @@ namespace ts.server {
}
private getStartAndEndPosition(args: protocol.FileRangeRequestArgs, scriptInfo: ScriptInfo) {
let startPosition: number, endPosition: number;
let startPosition: number | undefined, endPosition: number | undefined;
if (args.startPosition !== undefined) {
startPosition = args.startPosition;
}
@@ -1766,7 +1766,7 @@ namespace ts.server {
}
private mapTextChangesToCodeEdits(project: Project, textChanges: ReadonlyArray<FileTextChanges>): protocol.FileCodeEdits[] {
return textChanges.map(change => this.mapTextChangesToCodeEditsUsingScriptinfo(change, project.getScriptInfoForNormalizedPath(toNormalizedPath(change.fileName))));
return textChanges.map(change => this.mapTextChangesToCodeEditsUsingScriptinfo(change, project.getScriptInfoForNormalizedPath(toNormalizedPath(change.fileName))!));
}
private mapTextChangesToCodeEditsUsingScriptinfo(textChanges: FileTextChanges, scriptInfo: ScriptInfo | undefined): protocol.FileCodeEdits {
@@ -1797,9 +1797,9 @@ namespace ts.server {
return { fileName: textChanges.fileName, textChanges: [{ start: { line: 0, offset: 0 }, end: { line: 0, offset: 0 }, newText: change.newText }] };
}
private getBraceMatching(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): protocol.TextSpan[] | TextSpan[] {
private getBraceMatching(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): protocol.TextSpan[] | TextSpan[] | undefined {
const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args);
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file);
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!;
const position = this.getPosition(args, scriptInfo);
const spans = languageService.getBraceMatchingAtPosition(file, position);
@@ -1821,7 +1821,7 @@ namespace ts.server {
}
// No need to analyze lib.d.ts
const fileNamesInProject = fileNames.filter(value => !stringContains(value, "lib.d.ts"));
const fileNamesInProject = fileNames!.filter(value => !stringContains(value, "lib.d.ts")); // TODO: GH#18217
if (fileNamesInProject.length === 0) {
return;
}
@@ -1832,13 +1832,13 @@ namespace ts.server {
const lowPriorityFiles: NormalizedPath[] = [];
const veryLowPriorityFiles: NormalizedPath[] = [];
const normalizedFileName = toNormalizedPath(fileName);
const project = this.projectService.getDefaultProjectForFile(normalizedFileName, /*ensureProject*/ true);
const project = this.projectService.getDefaultProjectForFile(normalizedFileName, /*ensureProject*/ true)!;
for (const fileNameInProject of fileNamesInProject) {
if (this.getCanonicalFileName(fileNameInProject) === this.getCanonicalFileName(fileName)) {
highPriorityFiles.push(fileNameInProject);
}
else {
const info = this.projectService.getScriptInfo(fileNameInProject);
const info = this.projectService.getScriptInfo(fileNameInProject)!; // TODO: GH#18217
if (!info.isScriptOpen()) {
if (fileExtensionIs(fileNameInProject, Extension.Dts)) {
veryLowPriorityFiles.push(fileNameInProject);
@@ -1871,7 +1871,7 @@ namespace ts.server {
return { responseRequired: false };
}
private requiredResponse(response: {}): HandlerResponse {
private requiredResponse(response: {} | undefined): HandlerResponse {
return { response, responseRequired: true };
}
@@ -1915,7 +1915,7 @@ namespace ts.server {
},
[CommandNames.ApplyChangedToOpenFiles]: (request: protocol.ApplyChangedToOpenFilesRequest) => {
this.changeSeq++;
this.projectService.applyChangesInOpenFiles(request.arguments.openFiles, request.arguments.changedFiles, request.arguments.closedFiles);
this.projectService.applyChangesInOpenFiles(request.arguments.openFiles, request.arguments.changedFiles!, request.arguments.closedFiles!); // TODO: GH#18217
// TODO: report errors
return this.requiredResponse(/*response*/ true);
},
@@ -1963,7 +1963,7 @@ namespace ts.server {
this.openClientFile(
toNormalizedPath(request.arguments.file),
request.arguments.fileContent,
convertScriptKindName(request.arguments.scriptKindName),
convertScriptKindName(request.arguments.scriptKindName!), // TODO: GH#18217
request.arguments.projectRootPath ? toNormalizedPath(request.arguments.projectRootPath) : undefined);
return this.notRequired();
},
@@ -2189,7 +2189,7 @@ namespace ts.server {
private resetCurrentRequest(requestId: number): void {
Debug.assert(this.currentRequestId === requestId);
this.currentRequestId = undefined;
this.currentRequestId = undefined!; // TODO: GH#18217
this.cancellationToken.resetRequest(requestId);
}
@@ -2217,7 +2217,7 @@ namespace ts.server {
public onMessage(message: string) {
this.gcTimer.scheduleCollect();
let start: number[];
let start: number[] | undefined;
if (this.logger.hasLevel(LogLevel.requestTime)) {
start = this.hrtime();
if (this.logger.hasLevel(LogLevel.verbose)) {
@@ -2225,7 +2225,7 @@ namespace ts.server {
}
}
let request: protocol.Request;
let request: protocol.Request | undefined;
try {
request = <protocol.Request>JSON.parse(message);
const { response, responseRequired } = this.executeCommand(request);
@@ -2250,7 +2250,7 @@ namespace ts.server {
catch (err) {
if (err instanceof OperationCanceledException) {
// Handle cancellation exceptions
this.doOutput({ canceled: true }, request.command, request.seq, /*success*/ true);
this.doOutput({ canceled: true }, request!.command, request!.seq, /*success*/ true);
return;
}
this.logError(err, message);
+8 -8
View File
@@ -8,7 +8,7 @@ namespace ts.server {
export interface ITypingsInstaller {
isKnownTypesPackageName(name: string): boolean;
installPackage(options: InstallPackageOptionsWithProject): Promise<ApplyCodeActionCommandResult>;
enqueueInstallTypingsRequest(p: Project, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray<string>): void;
enqueueInstallTypingsRequest(p: Project, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray<string> | undefined): void;
attach(projectService: ProjectService): void;
onProjectClosed(p: Project): void;
readonly globalTypingsCacheLocation: string | undefined;
@@ -21,19 +21,19 @@ namespace ts.server {
enqueueInstallTypingsRequest: noop,
attach: noop,
onProjectClosed: noop,
globalTypingsCacheLocation: undefined
globalTypingsCacheLocation: undefined! // TODO: GH#18217
};
interface TypingsCacheEntry {
readonly typeAcquisition: TypeAcquisition;
readonly compilerOptions: CompilerOptions;
readonly typings: SortedReadonlyArray<string>;
readonly unresolvedImports: SortedReadonlyArray<string>;
readonly unresolvedImports: SortedReadonlyArray<string> | undefined;
/* mainly useful for debugging */
poisoned: boolean;
}
function setIsEqualTo(arr1: string[], arr2: string[]): boolean {
function setIsEqualTo(arr1: string[] | undefined, arr2: string[] | undefined): boolean {
if (arr1 === arr2) {
return true;
}
@@ -43,13 +43,13 @@ namespace ts.server {
const set: Map<boolean> = createMap<boolean>();
let unique = 0;
for (const v of arr1) {
for (const v of arr1!) {
if (set.get(v) !== true) {
set.set(v, true);
unique++;
}
}
for (const v of arr2) {
for (const v of arr2!) {
const isSet = set.get(v);
if (isSet === undefined) {
return false;
@@ -73,7 +73,7 @@ namespace ts.server {
return opt1.allowJs !== opt2.allowJs;
}
function unresolvedImportsChanged(imports1: SortedReadonlyArray<string>, imports2: SortedReadonlyArray<string>): boolean {
function unresolvedImportsChanged(imports1: SortedReadonlyArray<string> | undefined, imports2: SortedReadonlyArray<string> | undefined): boolean {
if (imports1 === imports2) {
return false;
}
@@ -95,7 +95,7 @@ namespace ts.server {
return this.installer.installPackage(options);
}
enqueueInstallTypingsForProject(project: Project, unresolvedImports: SortedReadonlyArray<string>, forceRefresh: boolean) {
enqueueInstallTypingsForProject(project: Project, unresolvedImports: SortedReadonlyArray<string> | undefined, forceRefresh: boolean) {
const typeAcquisition = project.getTypeAcquisition();
if (!typeAcquisition || !typeAcquisition.enable) {
@@ -1,4 +1,4 @@
/// <reference types="node" />
// tslint:disable no-unnecessary-type-assertion (TODO: tslint can't find node types)
namespace ts.server.typingsInstaller {
const fs: {
@@ -22,7 +22,7 @@ namespace ts.server.typingsInstaller {
}
writeLine = (text: string) => {
try {
fs.appendFileSync(this.logFile, `[${nowString()}] ${text}${sys.newLine}`);
fs.appendFileSync(this.logFile!, `[${nowString()}] ${text}${sys.newLine}`); // TODO: GH#18217
}
catch (e) {
this.logEnabled = false;
@@ -53,7 +53,7 @@ namespace ts.server.typingsInstaller {
return createMap<MapLike<string>>();
}
try {
const content = <TypesRegistryFile>JSON.parse(host.readFile(typesRegistryFilePath));
const content = <TypesRegistryFile>JSON.parse(host.readFile(typesRegistryFilePath)!);
return createMapFromTemplate(content.entries);
}
catch (e) {
@@ -176,7 +176,7 @@ namespace ts.server.typingsInstaller {
if (this.log.isEnabled()) {
this.log.writeLine(`Sending response:\n ${JSON.stringify(response)}`);
}
process.send(response);
process.send!(response); // TODO: GH#18217
if (this.log.isEnabled()) {
this.log.writeLine(`Response has been sent.`);
}
@@ -240,7 +240,7 @@ namespace ts.server.typingsInstaller {
}
process.exit(0);
});
const installer = new NodeTypingsInstaller(globalTypingsCacheLocation, typingSafeListLocation, typesMapLocation, npmLocation, /*throttleLimit*/5, log);
const installer = new NodeTypingsInstaller(globalTypingsCacheLocation!, typingSafeListLocation!, typesMapLocation!, npmLocation, /*throttleLimit*/5, log); // TODO: GH#18217
installer.listen();
function indent(newline: string, str: string): string {
+11 -11
View File
@@ -17,7 +17,7 @@ namespace ts.server.typingsInstaller {
writeLine: noop
};
function typingToFileName(cachePath: string, packageName: string, installTypingHost: InstallTypingHost, log: Log): string {
function typingToFileName(cachePath: string, packageName: string, installTypingHost: InstallTypingHost, log: Log): string | undefined {
try {
const result = resolveModuleName(packageName, combinePaths(cachePath, "index.d.ts"), { moduleResolution: ModuleResolutionKind.NodeJs }, installTypingHost);
return result.resolvedModule && result.resolvedModule.resolvedFileName;
@@ -154,7 +154,7 @@ namespace ts.server.typingsInstaller {
this.log.isEnabled() ? (s => this.log.writeLine(s)) : undefined,
req.fileNames,
req.projectRootPath,
this.safeList,
this.safeList!,
this.packageNameToTypingLocation,
req.typeAcquisition,
req.unresolvedImports,
@@ -209,8 +209,8 @@ namespace ts.server.typingsInstaller {
this.log.writeLine(`Trying to find '${packageJson}'...`);
}
if (this.installTypingHost.fileExists(packageJson) && this.installTypingHost.fileExists(packageLockJson)) {
const npmConfig = <NpmConfig>JSON.parse(this.installTypingHost.readFile(packageJson));
const npmLock = <NpmLock>JSON.parse(this.installTypingHost.readFile(packageLockJson));
const npmConfig = <NpmConfig>JSON.parse(this.installTypingHost.readFile(packageJson)!); // TODO: GH#18217
const npmLock = <NpmLock>JSON.parse(this.installTypingHost.readFile(packageLockJson)!); // TODO: GH#18217
if (this.log.isEnabled()) {
this.log.writeLine(`Loaded content of '${packageJson}': ${JSON.stringify(npmConfig)}`);
this.log.writeLine(`Loaded content of '${packageLockJson}'`);
@@ -246,7 +246,7 @@ namespace ts.server.typingsInstaller {
}
const info = getProperty(npmLock.dependencies, key);
const version = info && info.version;
const semver = Semver.parse(version);
const semver = Semver.parse(version!); // TODO: GH#18217
const newTyping: JsTyping.CachedTyping = { typingLocation: typingFile, version: semver };
this.packageNameToTypingLocation.set(packageName, newTyping);
}
@@ -275,7 +275,7 @@ namespace ts.server.typingsInstaller {
if (this.log.isEnabled()) this.log.writeLine(`Entry for package '${typing}' does not exist in local types registry - skipping...`);
return false;
}
if (this.packageNameToTypingLocation.get(typing) && JsTyping.isTypingUpToDate(this.packageNameToTypingLocation.get(typing), this.typesRegistry.get(typing))) {
if (this.packageNameToTypingLocation.get(typing) && JsTyping.isTypingUpToDate(this.packageNameToTypingLocation.get(typing)!, this.typesRegistry.get(typing)!)) {
if (this.log.isEnabled()) this.log.writeLine(`'${typing}' already has an up-to-date typing - skipping...`);
return false;
}
@@ -349,7 +349,7 @@ namespace ts.server.typingsInstaller {
}
// packageName is guaranteed to exist in typesRegistry by filterTypings
const distTags = this.typesRegistry.get(packageName);
const distTags = this.typesRegistry.get(packageName)!;
const newVersion = Semver.parse(distTags[`ts${versionMajorMinor}`] || distTags[latestDistTag]);
const newTyping: JsTyping.CachedTyping = { typingLocation: typingFile, version: newVersion };
this.packageNameToTypingLocation.set(packageName, newTyping);
@@ -392,7 +392,7 @@ namespace ts.server.typingsInstaller {
return;
}
let watchers = this.projectWatchers.get(projectName);
let watchers = this.projectWatchers.get(projectName)!;
const toRemove = createMap<FileWatcher>();
if (!watchers) {
watchers = createMap();
@@ -418,7 +418,7 @@ namespace ts.server.typingsInstaller {
if (isLoggingEnabled) {
this.log.writeLine(`FileWatcher:: Added:: WatchInfo: ${file}`);
}
const watcher = this.installTypingHost.watchFile(file, (f, eventKind) => {
const watcher = this.installTypingHost.watchFile!(file, (f, eventKind) => { // TODO: GH#18217
if (isLoggingEnabled) {
this.log.writeLine(`FileWatcher:: Triggered with ${f} eventKind: ${FileWatcherEventKind[eventKind]}:: WatchInfo: ${file}:: handler is already invoked '${watchers.isInvoked}'`);
}
@@ -439,7 +439,7 @@ namespace ts.server.typingsInstaller {
if (isLoggingEnabled) {
this.log.writeLine(`DirectoryWatcher:: Added:: WatchInfo: ${dir} recursive`);
}
const watcher = this.installTypingHost.watchDirectory(dir, f => {
const watcher = this.installTypingHost.watchDirectory!(dir, f => { // TODO: GH#18217
if (isLoggingEnabled) {
this.log.writeLine(`DirectoryWatcher:: Triggered with ${f} :: WatchInfo: ${dir} recursive :: handler is already invoked '${watchers.isInvoked}'`);
}
@@ -512,7 +512,7 @@ namespace ts.server.typingsInstaller {
private executeWithThrottling() {
while (this.inFlightRequestCount < this.throttleLimit && this.pendingRunRequests.length) {
this.inFlightRequestCount++;
const request = this.pendingRunRequests.pop();
const request = this.pendingRunRequests.pop()!;
this.installWorker(request.requestId, request.packageNames, request.cwd, ok => {
this.inFlightRequestCount--;
request.onRequestCompleted(ok);
+7 -7
View File
@@ -17,7 +17,7 @@ namespace ts.server {
startGroup(): void;
endGroup(): void;
msg(s: string, type?: Msg): void;
getLogFileName(): string;
getLogFileName(): string | undefined;
}
// TODO: Use a const enum (https://github.com/Microsoft/TypeScript/issues/16804)
@@ -96,7 +96,7 @@ namespace ts.server {
}
export interface NormalizedPathMap<T> {
get(path: NormalizedPath): T;
get(path: NormalizedPath): T | undefined;
set(path: NormalizedPath, value: T): void;
contains(path: NormalizedPath): boolean;
remove(path: NormalizedPath): void;
@@ -150,7 +150,7 @@ namespace ts.server {
}
export function createSortedArray<T>(): SortedArray<T> {
return [] as SortedArray<T>;
return [] as any as SortedArray<T>; // TODO: GH#19873
}
}
@@ -160,7 +160,7 @@ namespace ts.server {
private readonly pendingTimeouts: Map<any> = createMap<any>();
private readonly logger?: Logger | undefined;
constructor(private readonly host: ServerHost, logger: Logger) {
this.logger = logger.hasLevel(LogLevel.verbose) && logger;
this.logger = logger.hasLevel(LogLevel.verbose) ? logger : undefined;
}
/**
@@ -208,11 +208,11 @@ namespace ts.server {
self.timerId = undefined;
const log = self.logger.hasLevel(LogLevel.requestTime);
const before = log && self.host.getMemoryUsage();
const before = log && self.host.getMemoryUsage!(); // TODO: GH#18217
self.host.gc();
self.host.gc!(); // TODO: GH#18217
if (log) {
const after = self.host.getMemoryUsage();
const after = self.host.getMemoryUsage!(); // TODO: GH#18217
self.logger.perftrc(`GC::before ${before}, after ${after}`);
}
}
+33 -30
View File
@@ -17,12 +17,13 @@ namespace ts.BreakpointResolver {
// let y = 10;
// token at position will return let keyword on second line as the token but we would like to use
// token on same line if trailing trivia (comments or white spaces on same line) part of the last token on that line
tokenAtLocation = findPrecedingToken(tokenAtLocation.pos, sourceFile);
const preceding = findPrecedingToken(tokenAtLocation.pos, sourceFile);
// It's a blank line
if (!tokenAtLocation || sourceFile.getLineAndCharacterOfPosition(tokenAtLocation.getEnd()).line !== lineOfPosition) {
if (!preceding || sourceFile.getLineAndCharacterOfPosition(preceding.getEnd()).line !== lineOfPosition) {
return undefined;
}
tokenAtLocation = preceding;
}
// Cannot set breakpoint in ambient declarations
@@ -44,7 +45,7 @@ namespace ts.BreakpointResolver {
return textSpan(startNode, findNextToken(previousTokenToFindNextEndToken, previousTokenToFindNextEndToken.parent, sourceFile));
}
function spanInNodeIfStartsOnSameLine(node: Node, otherwiseOnNode?: Node): TextSpan {
function spanInNodeIfStartsOnSameLine(node: Node | undefined, otherwiseOnNode?: Node): TextSpan | undefined {
if (node && lineOfPosition === sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line) {
return spanInNode(node);
}
@@ -55,16 +56,17 @@ namespace ts.BreakpointResolver {
return createTextSpanFromBounds(skipTrivia(sourceFile.text, nodeArray.pos), nodeArray.end);
}
function spanInPreviousNode(node: Node): TextSpan {
function spanInPreviousNode(node: Node): TextSpan | undefined {
return spanInNode(findPrecedingToken(node.pos, sourceFile));
}
function spanInNextNode(node: Node): TextSpan {
function spanInNextNode(node: Node): TextSpan | undefined {
return spanInNode(findNextToken(node, node.parent, sourceFile));
}
function spanInNode(node: Node): TextSpan {
function spanInNode(node: Node | undefined): TextSpan | undefined {
if (node) {
const { parent } = node;
switch (node.kind) {
case SyntaxKind.VariableStatement:
// Span on first variable declaration
@@ -195,7 +197,7 @@ namespace ts.BreakpointResolver {
return spanInNode((<WithStatement>node).statement);
case SyntaxKind.Decorator:
return spanInNodeArray(node.parent.decorators);
return spanInNodeArray(parent.decorators!);
case SyntaxKind.ObjectBindingPattern:
case SyntaxKind.ArrayBindingPattern:
@@ -263,7 +265,7 @@ namespace ts.BreakpointResolver {
node.kind === SyntaxKind.SpreadElement ||
node.kind === SyntaxKind.PropertyAssignment ||
node.kind === SyntaxKind.ShorthandPropertyAssignment) &&
isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent)) {
isArrayLiteralOrObjectLiteralDestructuringPattern(parent)) {
return textSpan(node);
}
@@ -292,7 +294,7 @@ namespace ts.BreakpointResolver {
}
if (isExpressionNode(node)) {
switch (node.parent.kind) {
switch (parent.kind) {
case SyntaxKind.DoStatement:
// Set span as if on while keyword
return spanInPreviousNode(node);
@@ -367,7 +369,7 @@ namespace ts.BreakpointResolver {
function textSpanFromVariableDeclaration(variableDeclaration: VariableDeclaration | PropertyDeclaration | PropertySignature): TextSpan {
if (isVariableDeclarationList(variableDeclaration.parent) && variableDeclaration.parent.declarations[0] === variableDeclaration) {
// First declaration - include let keyword
return textSpan(findPrecedingToken(variableDeclaration.pos, sourceFile, variableDeclaration.parent), variableDeclaration);
return textSpan(findPrecedingToken(variableDeclaration.pos, sourceFile, variableDeclaration.parent)!, variableDeclaration);
}
else {
// Span only on this declaration
@@ -375,12 +377,13 @@ namespace ts.BreakpointResolver {
}
}
function spanInVariableDeclaration(variableDeclaration: VariableDeclaration | PropertyDeclaration | PropertySignature): TextSpan {
function spanInVariableDeclaration(variableDeclaration: VariableDeclaration | PropertyDeclaration | PropertySignature): TextSpan | undefined {
// If declaration of for in statement, just set the span in parent
if (variableDeclaration.parent.parent.kind === SyntaxKind.ForInStatement) {
return spanInNode(variableDeclaration.parent.parent);
}
const parent = variableDeclaration.parent;
// If this is a destructuring pattern, set breakpoint in binding pattern
if (isBindingPattern(variableDeclaration.name)) {
return spanInBindingPattern(variableDeclaration.name);
@@ -390,7 +393,7 @@ namespace ts.BreakpointResolver {
// or its declaration from 'for of'
if (variableDeclaration.initializer ||
hasModifier(variableDeclaration, ModifierFlags.Export) ||
variableDeclaration.parent.parent.kind === SyntaxKind.ForOfStatement) {
parent.parent.kind === SyntaxKind.ForOfStatement) {
return textSpanFromVariableDeclaration(variableDeclaration);
}
@@ -410,7 +413,7 @@ namespace ts.BreakpointResolver {
hasModifier(parameter, ModifierFlags.Public | ModifierFlags.Private);
}
function spanInParameterDeclaration(parameter: ParameterDeclaration): TextSpan {
function spanInParameterDeclaration(parameter: ParameterDeclaration): TextSpan | undefined {
if (isBindingPattern(parameter.name)) {
// Set breakpoint in binding pattern
return spanInBindingPattern(parameter.name);
@@ -438,7 +441,7 @@ namespace ts.BreakpointResolver {
(functionDeclaration.parent.kind === SyntaxKind.ClassDeclaration && functionDeclaration.kind !== SyntaxKind.Constructor);
}
function spanInFunctionDeclaration(functionDeclaration: FunctionLikeDeclaration): TextSpan {
function spanInFunctionDeclaration(functionDeclaration: FunctionLikeDeclaration): TextSpan | undefined {
// No breakpoints in the function signature
if (!functionDeclaration.body) {
return undefined;
@@ -453,7 +456,7 @@ namespace ts.BreakpointResolver {
return spanInNode(functionDeclaration.body);
}
function spanInFunctionBlock(block: Block): TextSpan {
function spanInFunctionBlock(block: Block): TextSpan | undefined {
const nodeForSpanInBlock = block.statements.length ? block.statements[0] : block.getLastToken();
if (canFunctionHaveSpanInWholeDeclaration(<FunctionLikeDeclaration>block.parent)) {
return spanInNodeIfStartsOnSameLine(block.parent, nodeForSpanInBlock);
@@ -462,7 +465,7 @@ namespace ts.BreakpointResolver {
return spanInNode(nodeForSpanInBlock);
}
function spanInBlock(block: Block): TextSpan {
function spanInBlock(block: Block): TextSpan | undefined {
switch (block.parent.kind) {
case SyntaxKind.ModuleDeclaration:
if (getModuleInstanceState(block.parent as ModuleDeclaration) !== ModuleInstanceState.Instantiated) {
@@ -486,8 +489,8 @@ namespace ts.BreakpointResolver {
return spanInNode(block.statements[0]);
}
function spanInInitializerOfForLike(forLikeStatement: ForStatement | ForOfStatement | ForInStatement): TextSpan {
if (forLikeStatement.initializer.kind === SyntaxKind.VariableDeclarationList) {
function spanInInitializerOfForLike(forLikeStatement: ForStatement | ForOfStatement | ForInStatement): TextSpan | undefined {
if (forLikeStatement.initializer!.kind === SyntaxKind.VariableDeclarationList) {
// Declaration list - set breakpoint in first declaration
const variableDeclarationList = <VariableDeclarationList>forLikeStatement.initializer;
if (variableDeclarationList.declarations.length > 0) {
@@ -500,7 +503,7 @@ namespace ts.BreakpointResolver {
}
}
function spanInForStatement(forStatement: ForStatement): TextSpan {
function spanInForStatement(forStatement: ForStatement): TextSpan | undefined {
if (forStatement.initializer) {
return spanInInitializerOfForLike(forStatement);
}
@@ -513,7 +516,7 @@ namespace ts.BreakpointResolver {
}
}
function spanInBindingPattern(bindingPattern: BindingPattern): TextSpan {
function spanInBindingPattern(bindingPattern: BindingPattern): TextSpan | undefined {
// Set breakpoint in first binding element
const firstBindingElement = forEach(bindingPattern.elements,
element => element.kind !== SyntaxKind.OmittedExpression ? element : undefined);
@@ -531,7 +534,7 @@ namespace ts.BreakpointResolver {
return textSpanFromVariableDeclaration(<VariableDeclaration>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<Expression | ObjectLiteralElement> = node.kind === SyntaxKind.ArrayLiteralExpression ? node.elements : (node as ObjectLiteralExpression).properties;
@@ -550,7 +553,7 @@ namespace ts.BreakpointResolver {
}
// Tokens:
function spanInOpenBraceToken(node: Node): TextSpan {
function spanInOpenBraceToken(node: Node): TextSpan | undefined {
switch (node.parent.kind) {
case SyntaxKind.EnumDeclaration:
const enumDeclaration = <EnumDeclaration>node.parent;
@@ -568,7 +571,7 @@ namespace ts.BreakpointResolver {
return spanInNode(node.parent);
}
function spanInCloseBraceToken(node: Node): TextSpan {
function spanInCloseBraceToken(node: Node): TextSpan | undefined {
switch (node.parent.kind) {
case SyntaxKind.ModuleBlock:
// If this is not an instantiated module block, no bp span
@@ -617,7 +620,7 @@ namespace ts.BreakpointResolver {
}
}
function spanInCloseBracketToken(node: Node): TextSpan {
function spanInCloseBracketToken(node: Node): TextSpan | undefined {
switch (node.parent.kind) {
case SyntaxKind.ArrayBindingPattern:
// Breakpoint in last binding element or binding pattern if it contains no elements
@@ -636,7 +639,7 @@ namespace ts.BreakpointResolver {
}
}
function spanInOpenParenToken(node: Node): TextSpan {
function spanInOpenParenToken(node: Node): TextSpan | undefined {
if (node.parent.kind === SyntaxKind.DoStatement || // Go to while keyword and do action instead
node.parent.kind === SyntaxKind.CallExpression ||
node.parent.kind === SyntaxKind.NewExpression) {
@@ -651,7 +654,7 @@ namespace ts.BreakpointResolver {
return spanInNode(node.parent);
}
function spanInCloseParenToken(node: Node): TextSpan {
function spanInCloseParenToken(node: Node): TextSpan | undefined {
// Is this close paren token of parameter list, set span in previous token
switch (node.parent.kind) {
case SyntaxKind.FunctionExpression:
@@ -677,7 +680,7 @@ namespace ts.BreakpointResolver {
}
}
function spanInColonToken(node: Node): TextSpan {
function spanInColonToken(node: Node): TextSpan | undefined {
// Is this : specifying return annotation of the function declaration
if (isFunctionLike(node.parent) ||
node.parent.kind === SyntaxKind.PropertyAssignment ||
@@ -688,7 +691,7 @@ namespace ts.BreakpointResolver {
return spanInNode(node.parent);
}
function spanInGreaterThanOrLessThanToken(node: Node): TextSpan {
function spanInGreaterThanOrLessThanToken(node: Node): TextSpan | undefined {
if (node.parent.kind === SyntaxKind.TypeAssertionExpression) {
return spanInNextNode(node);
}
@@ -696,7 +699,7 @@ namespace ts.BreakpointResolver {
return spanInNode(node.parent);
}
function spanInWhileKeyword(node: Node): TextSpan {
function spanInWhileKeyword(node: Node): TextSpan | undefined {
if (node.parent.kind === SyntaxKind.DoStatement) {
// Set span on while expression
return textSpanEndingAtNextToken(node, (<DoStatement>node.parent).expression);
@@ -706,7 +709,7 @@ namespace ts.BreakpointResolver {
return spanInNode(node.parent);
}
function spanInOfKeyword(node: Node): TextSpan {
function spanInOfKeyword(node: Node): TextSpan | undefined {
if (node.parent.kind === SyntaxKind.ForOfStatement) {
// Set using next token
return spanInNextNode(node);
+17 -12
View File
@@ -300,6 +300,8 @@ namespace ts {
case ClassificationType.text:
case ClassificationType.parameterName:
return TokenClass.Identifier;
default:
return undefined!; // TODO: GH#18217 Debug.assertNever(type);
}
}
@@ -559,6 +561,7 @@ namespace ts {
case ClassificationType.jsxAttribute: return ClassificationTypeNames.jsxAttribute;
case ClassificationType.jsxText: return ClassificationTypeNames.jsxText;
case ClassificationType.jsxAttributeStringLiteralValue: return ClassificationTypeNames.jsxAttributeStringLiteralValue;
default: return undefined!; // TODO: GH#18217 throw Debug.assertNever(type);
}
}
@@ -813,7 +816,7 @@ namespace ts {
return true;
}
function tryClassifyJsxElementName(token: Node): ClassificationType {
function tryClassifyJsxElementName(token: Node): ClassificationType | undefined {
switch (token.parent && token.parent.kind) {
case SyntaxKind.JsxOpeningElement:
if ((<JsxOpeningElement>token.parent).tagName === token) {
@@ -842,7 +845,7 @@ namespace ts {
// for accurate classification, the actual token should be passed in. however, for
// cases like 'disabled merge code' classification, we just get the token kind and
// classify based on that instead.
function classifyTokenType(tokenKind: SyntaxKind, token?: Node): ClassificationType {
function classifyTokenType(tokenKind: SyntaxKind, token?: Node): ClassificationType | undefined {
if (isKeyword(tokenKind)) {
return ClassificationType.keyword;
}
@@ -859,20 +862,21 @@ namespace ts {
if (isPunctuation(tokenKind)) {
if (token) {
const parent = token.parent;
if (tokenKind === SyntaxKind.EqualsToken) {
// the '=' in a variable declaration is special cased here.
if (token.parent.kind === SyntaxKind.VariableDeclaration ||
token.parent.kind === SyntaxKind.PropertyDeclaration ||
token.parent.kind === SyntaxKind.Parameter ||
token.parent.kind === SyntaxKind.JsxAttribute) {
if (parent.kind === SyntaxKind.VariableDeclaration ||
parent.kind === SyntaxKind.PropertyDeclaration ||
parent.kind === SyntaxKind.Parameter ||
parent.kind === SyntaxKind.JsxAttribute) {
return ClassificationType.operator;
}
}
if (token.parent.kind === SyntaxKind.BinaryExpression ||
token.parent.kind === SyntaxKind.PrefixUnaryExpression ||
token.parent.kind === SyntaxKind.PostfixUnaryExpression ||
token.parent.kind === SyntaxKind.ConditionalExpression) {
if (parent.kind === SyntaxKind.BinaryExpression ||
parent.kind === SyntaxKind.PrefixUnaryExpression ||
parent.kind === SyntaxKind.PostfixUnaryExpression ||
parent.kind === SyntaxKind.ConditionalExpression) {
return ClassificationType.operator;
}
}
@@ -883,7 +887,8 @@ namespace ts {
return ClassificationType.numericLiteral;
}
else if (tokenKind === SyntaxKind.StringLiteral) {
return token.parent.kind === SyntaxKind.JsxAttribute ? ClassificationType.jsxAttributeStringLiteralValue : ClassificationType.stringLiteral;
// TODO: GH#18217
return token!.parent.kind === SyntaxKind.JsxAttribute ? ClassificationType.jsxAttributeStringLiteralValue : ClassificationType.stringLiteral;
}
else if (tokenKind === SyntaxKind.RegularExpressionLiteral) {
// TODO: we should get another classification type for these literals.
@@ -935,7 +940,7 @@ namespace ts {
}
}
function processElement(element: Node) {
function processElement(element: Node | undefined) {
if (!element) {
return;
}

Some files were not shown because too many files have changed in this diff Show More