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

View File

@@ -2,7 +2,7 @@ namespace ts {
/** The version of the language service API */
export const servicesVersion = "0.8";
function createNode<TKind extends SyntaxKind>(kind: TKind, pos: number, end: number, parent?: Node): NodeObject | TokenObject<TKind> | IdentifierObject {
function createNode<TKind extends SyntaxKind>(kind: TKind, pos: number, end: number, parent: Node): NodeObject | TokenObject<TKind> | IdentifierObject {
const node = isNodeKind(kind) ? new NodeObject(kind, pos, end) :
kind === SyntaxKind.Identifier ? new IdentifierObject(SyntaxKind.Identifier, pos, end) :
new TokenObject(kind, pos, end);
@@ -17,6 +17,7 @@ namespace ts {
public end: number;
public flags: NodeFlags;
public parent: Node;
public symbol: Symbol;
public jsDoc: JSDoc[];
public original: Node;
public transformFlags: TransformFlags;
@@ -26,8 +27,8 @@ namespace ts {
this.pos = pos;
this.end = end;
this.flags = NodeFlags.None;
this.transformFlags = undefined;
this.parent = undefined;
this.transformFlags = undefined!; // TODO: GH#18217
this.parent = undefined!;
this.kind = kind;
}
@@ -96,20 +97,20 @@ namespace ts {
return this._children || (this._children = createChildren(this, sourceFile));
}
public getFirstToken(sourceFile?: SourceFile): Node {
public getFirstToken(sourceFile?: SourceFile): Node | undefined {
this.assertHasRealPosition();
const children = this.getChildren(sourceFile);
if (!children.length) {
return undefined;
}
const child = find(children, kid => kid.kind < SyntaxKind.FirstJSDocNode || kid.kind > SyntaxKind.LastJSDocNode);
const child = find(children, kid => kid.kind < SyntaxKind.FirstJSDocNode || kid.kind > SyntaxKind.LastJSDocNode)!;
return child.kind < SyntaxKind.FirstNode ?
child :
child.getFirstToken(sourceFile);
}
public getLastToken(sourceFile?: SourceFile): Node {
public getLastToken(sourceFile?: SourceFile): Node | undefined {
this.assertHasRealPosition();
const children = this.getChildren(sourceFile);
@@ -121,7 +122,7 @@ namespace ts {
return child.kind < SyntaxKind.FirstNode ? child : child.getLastToken(sourceFile);
}
public forEachChild<T>(cbNode: (node: Node) => T, cbNodeArray?: (nodes: NodeArray<Node>) => T): T {
public forEachChild<T>(cbNode: (node: Node) => T, cbNodeArray?: (nodes: NodeArray<Node>) => T): T | undefined {
return forEachChild(this, cbNode, cbNodeArray);
}
}
@@ -200,14 +201,16 @@ namespace ts {
public end: number;
public flags: NodeFlags;
public parent: Node;
public symbol: Symbol;
public jsDocComments: JSDoc[];
public transformFlags: TransformFlags;
constructor(pos: number, end: number) {
// Set properties in same order as NodeObject
this.pos = pos;
this.end = end;
this.flags = NodeFlags.None;
this.parent = undefined;
this.parent = undefined!;
}
public getSourceFile(): SourceFile {
@@ -254,22 +257,22 @@ namespace ts {
}
public getChildAt(): Node {
return undefined;
return undefined!; // TODO: GH#18217
}
public getChildren(): Node[] {
return emptyArray;
}
public getFirstToken(): Node {
public getFirstToken(): Node | undefined {
return undefined;
}
public getLastToken(): Node {
public getLastToken(): Node | undefined {
return undefined;
}
public forEachChild<T>(): T {
public forEachChild<T>(): T | undefined {
return undefined;
}
}
@@ -277,7 +280,8 @@ namespace ts {
class SymbolObject implements Symbol {
flags: SymbolFlags;
escapedName: __String;
declarations?: Declaration[];
declarations: Declaration[];
valueDeclaration: Declaration;
// Undefined is used to indicate the value has not been computed. If, after computing, the
// symbol has no doc comment, then the empty array will be returned.
@@ -330,6 +334,7 @@ namespace ts {
}
class TokenObject<TKind extends SyntaxKind> extends TokenOrIdentifierObject implements Token<TKind> {
public symbol: Symbol;
public kind: TKind;
constructor(kind: TKind, pos: number, end: number) {
@@ -341,6 +346,8 @@ namespace ts {
class IdentifierObject extends TokenOrIdentifierObject implements Identifier {
public kind: SyntaxKind.Identifier;
public escapedText: __String;
public symbol: Symbol;
public autoGenerateFlags: GeneratedIdentifierFlags;
_primaryExpressionBrand: any;
_memberExpressionBrand: any;
_leftHandSideExpressionBrand: any;
@@ -364,7 +371,7 @@ namespace ts {
flags: TypeFlags;
objectFlags?: ObjectFlags;
id: number;
symbol?: Symbol;
symbol: Symbol;
constructor(checker: TypeChecker, flags: TypeFlags) {
this.checker = checker;
this.flags = flags;
@@ -503,7 +510,7 @@ namespace ts {
let doc = JsDoc.getJsDocCommentsFromDeclarations(declarations);
if (doc.length === 0 || declarations.some(hasJSDocInheritDocTag)) {
for (const declaration of declarations) {
const inheritedDocs = findInheritedJSDocComments(declaration, declaration.symbol.name, checker);
const inheritedDocs = findInheritedJSDocComments(declaration, declaration.symbol.name, checker!); // TODO: GH#18217
// TODO: GH#16312 Return a ReadonlyArray, avoid copying inheritedDocs
if (inheritedDocs) doc = doc.length === 0 ? inheritedDocs.slice() : inheritedDocs.concat(lineBreakPart(), doc);
}
@@ -600,7 +607,7 @@ namespace ts {
const { line } = this.getLineAndCharacterOfPosition(pos);
const lineStarts = this.getLineStarts();
let lastCharPos: number;
let lastCharPos: number | undefined;
if (line + 1 >= lineStarts.length) {
lastCharPos = this.getEnd();
}
@@ -723,7 +730,7 @@ namespace ts {
// Handle named exports case e.g.:
// export {a, b as B} from "mod";
if ((<ExportDeclaration>node).exportClause) {
forEach((<ExportDeclaration>node).exportClause.elements, visit);
forEach((<ExportDeclaration>node).exportClause!.elements, visit);
}
break;
@@ -829,7 +836,7 @@ namespace ts {
return !s.length || s.charAt(0) === s.charAt(0).toLowerCase();
}
export function displayPartsToString(displayParts: SymbolDisplayPart[]) {
export function displayPartsToString(displayParts: SymbolDisplayPart[] | undefined) {
if (displayParts) {
return map(displayParts, displayPart => displayPart.text).join("");
}
@@ -913,7 +920,7 @@ namespace ts {
public getOrCreateEntryByPath(fileName: string, path: Path): HostFileInformation {
const info = this.getEntryByPath(path) || this.createEntry(fileName, path);
return isString(info) ? undefined : info;
return isString(info) ? undefined! : info; // TODO: GH#18217
}
public getRootFileNames(): string[] {
@@ -933,12 +940,12 @@ namespace ts {
public getVersion(path: Path): string {
const file = this.getHostFileInformation(path);
return file && file.version;
return (file && file.version)!; // TODO: GH#18217
}
public getScriptSnapshot(path: Path): IScriptSnapshot {
const file = this.getHostFileInformation(path);
return file && file.scriptSnapshot;
return (file && file.scriptSnapshot)!; // TODO: GH#18217
}
}
@@ -962,7 +969,7 @@ namespace ts {
const scriptKind = getScriptKind(fileName, this.host);
const version = this.host.getScriptVersion(fileName);
let sourceFile: SourceFile;
let sourceFile: SourceFile | undefined;
if (this.currentFileName !== fileName) {
// This is a new file, just parse it
@@ -999,7 +1006,7 @@ namespace ts {
export let disableIncrementalParsing = false;
export function updateLanguageServiceSourceFile(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile {
export function updateLanguageServiceSourceFile(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string, textChangeRange: TextChangeRange | undefined, aggressiveChecks?: boolean): SourceFile {
// If we were given a text change range, and our version or open-ness changed, then
// incrementally parse this file.
if (textChangeRange) {
@@ -1058,11 +1065,11 @@ namespace ts {
}
class CancellationTokenObject implements CancellationToken {
constructor(private cancellationToken: HostCancellationToken) {
constructor(private cancellationToken: HostCancellationToken | undefined) {
}
public isCancellationRequested() {
return this.cancellationToken && this.cancellationToken.isCancellationRequested();
public isCancellationRequested(): boolean {
return !!this.cancellationToken && this.cancellationToken.isCancellationRequested();
}
public throwIfCancellationRequested(): void {
@@ -1108,7 +1115,7 @@ namespace ts {
}
/* @internal */
export function createSourceFileLikeCache(host: { readFile?: (path: string) => string, fileExists?: (path: string) => boolean }): SourceFileLikeCache {
export function createSourceFileLikeCache(host: { readFile?: (path: string) => string | undefined, fileExists?: (path: string) => boolean }): SourceFileLikeCache {
const cached = createMap<SourceFileLike>();
return {
get(path: Path) {
@@ -1117,7 +1124,7 @@ namespace ts {
}
if (!host.fileExists || !host.readFile || !host.fileExists(path)) return;
// And failing that, check the disk
const text = host.readFile(path);
const text = host.readFile(path)!; // TODO: GH#18217
const file: SourceFileLike = {
text,
lineMap: undefined,
@@ -1186,7 +1193,7 @@ namespace ts {
const typeRootsVersion = host.getTypeRootsVersion ? host.getTypeRootsVersion() : 0;
if (lastTypesRootVersion !== typeRootsVersion) {
log("TypeRoots version has changed; provide new program");
program = undefined;
program = undefined!; // TODO: GH#18217
lastTypesRootVersion = typeRootsVersion;
}
@@ -1197,7 +1204,7 @@ namespace ts {
const hasInvalidatedResolution: HasInvalidatedResolution = host.hasInvalidatedResolution || returnFalse;
// If the program is already up-to-date, we can reuse it
if (isProgramUptoDate(program, rootFileNames, hostCache.compilationSettings(), path => hostCache.getVersion(path), fileExists, hasInvalidatedResolution, host.hasChangedAutomaticTypeDirectiveNames)) {
if (isProgramUptoDate(program, rootFileNames, hostCache.compilationSettings(), path => hostCache.getVersion(path), fileExists, hasInvalidatedResolution, !!host.hasChangedAutomaticTypeDirectiveNames)) {
return;
}
@@ -1230,7 +1237,7 @@ namespace ts {
}
return host.readFile && host.readFile(fileName);
},
realpath: host.realpath && (path => host.realpath(path)),
realpath: host.realpath && (path => host.realpath!(path)),
directoryExists: directoryName => {
return directoryProbablyExists(directoryName, host);
},
@@ -1242,15 +1249,15 @@ namespace ts {
hasChangedAutomaticTypeDirectiveNames: host.hasChangedAutomaticTypeDirectiveNames
};
if (host.trace) {
compilerHost.trace = message => host.trace(message);
compilerHost.trace = message => host.trace!(message);
}
if (host.resolveModuleNames) {
compilerHost.resolveModuleNames = (moduleNames, containingFile, reusedNames) => host.resolveModuleNames(moduleNames, containingFile, reusedNames);
compilerHost.resolveModuleNames = (moduleNames, containingFile, reusedNames) => host.resolveModuleNames!(moduleNames, containingFile, reusedNames);
}
if (host.resolveTypeReferenceDirectives) {
compilerHost.resolveTypeReferenceDirectives = (typeReferenceDirectiveNames, containingFile) => {
return host.resolveTypeReferenceDirectives(typeReferenceDirectiveNames, containingFile);
return host.resolveTypeReferenceDirectives!(typeReferenceDirectiveNames, containingFile);
};
}
@@ -1266,7 +1273,7 @@ namespace ts {
// hostCache is captured in the closure for 'getOrCreateSourceFile' but it should not be used past this point.
// It needs to be cleared to allow all collected snapshots to be released
hostCache = undefined;
hostCache = undefined!;
// We reset this cache on structure invalidation so we don't hold on to outdated files for long; however we can't use the `compilerHost` above,
// Because it only functions until `hostCache` is cleared, while we'll potentially need the functionality to lazily read sourcemap files during
@@ -1278,12 +1285,12 @@ namespace ts {
program.getTypeChecker();
return;
function fileExists(fileName: string) {
function fileExists(fileName: string): boolean {
const path = toPath(fileName, currentDirectory, getCanonicalFileName);
const entry = hostCache.getEntryByPath(path);
return entry ?
!isString(entry) :
(host.fileExists && host.fileExists(fileName));
(!!host.fileExists && host.fileExists(fileName));
}
// Release any files we have acquired in the old program but are
@@ -1293,11 +1300,11 @@ namespace ts {
documentRegistry.releaseDocumentWithKey(oldSourceFile.path, oldSettingsKey);
}
function getOrCreateSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile {
function getOrCreateSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined {
return getOrCreateSourceFileByPath(fileName, toPath(fileName, currentDirectory, getCanonicalFileName), languageVersion, onError, shouldCreateNewSourceFile);
}
function getOrCreateSourceFileByPath(fileName: string, path: Path, _languageVersion: ScriptTarget, _onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile {
function getOrCreateSourceFileByPath(fileName: string, path: Path, _languageVersion: ScriptTarget, _onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined {
Debug.assert(hostCache !== undefined);
// The program is asking for this file, check first if the host can locate it.
// If the host can not locate the file, then it does not exist. return undefined
@@ -1352,7 +1359,8 @@ namespace ts {
}
}
function getProgram(): Program {
// TODO: GH#18217 frequently asserted as defined
function getProgram(): Program | undefined {
if (syntaxOnly) {
Debug.assert(program === undefined);
return undefined;
@@ -1364,16 +1372,16 @@ namespace ts {
}
function cleanupSemanticCache(): void {
program = undefined;
program = undefined!; // TODO: GH#18217
}
function dispose(): void {
if (program) {
forEach(program.getSourceFiles(), f =>
documentRegistry.releaseDocument(f.fileName, program.getCompilerOptions()));
program = undefined;
program = undefined!; // TODO: GH#18217
}
host = undefined;
host = undefined!;
}
/// Diagnostics
@@ -1415,7 +1423,7 @@ namespace ts {
return [...program.getOptionsDiagnostics(cancellationToken), ...program.getGlobalDiagnostics(cancellationToken)];
}
function getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions = defaultPreferences): CompletionInfo {
function getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions = defaultPreferences): CompletionInfo | undefined {
// Convert from deprecated options names to new names
const fullPreferences: UserPreferences = {
...identity<UserPreferences>(options), // avoid excess property check
@@ -1433,7 +1441,7 @@ namespace ts {
options.triggerCharacter);
}
function getCompletionEntryDetails(fileName: string, position: number, name: string, formattingOptions: FormatCodeSettings | undefined, source: string | undefined, preferences: UserPreferences = defaultPreferences): CompletionEntryDetails {
function getCompletionEntryDetails(fileName: string, position: number, name: string, formattingOptions: FormatCodeSettings | undefined, source: string | undefined, preferences: UserPreferences = defaultPreferences): CompletionEntryDetails | undefined {
synchronizeHostData();
return Completions.getCompletionEntryDetails(
program,
@@ -1442,19 +1450,19 @@ namespace ts {
position,
{ name, source },
host,
formattingOptions && formatting.getFormatContext(formattingOptions),
(formattingOptions && formatting.getFormatContext(formattingOptions))!, // TODO: GH#18217
getCanonicalFileName,
preferences,
cancellationToken,
);
}
function getCompletionEntrySymbol(fileName: string, position: number, name: string, source?: string): Symbol {
function getCompletionEntrySymbol(fileName: string, position: number, name: string, source?: string): Symbol | undefined {
synchronizeHostData();
return Completions.getCompletionEntrySymbol(program, log, getValidSourceFile(fileName), position, { name, source });
}
function getQuickInfoAtPosition(fileName: string, position: number): QuickInfo {
function getQuickInfoAtPosition(fileName: string, position: number): QuickInfo | undefined {
synchronizeHostData();
const sourceFile = getValidSourceFile(fileName);
@@ -1524,7 +1532,7 @@ namespace ts {
function toLineColumnOffset(fileName: string, position: number) {
const path = toPath(fileName, currentDirectory, getCanonicalFileName);
const file = program.getSourceFile(path) || sourcemappedFileCache.get(path);
const file = program.getSourceFile(path) || sourcemappedFileCache.get(path)!; // TODO: GH#18217
return file.getLineAndCharacterOfPosition(position);
}
@@ -1547,7 +1555,7 @@ namespace ts {
}
function convertDocumentToSourceMapper(file: { sourceMapper?: sourcemaps.SourceMapper }, contents: string, mapFileName: string) {
let maps: sourcemaps.SourceMapData;
let maps: sourcemaps.SourceMapData | undefined;
try {
maps = JSON.parse(contents);
}
@@ -1559,8 +1567,8 @@ namespace ts {
return file.sourceMapper = sourcemaps.identitySourceMapper;
}
return file.sourceMapper = sourcemaps.decode({
readFile: s => host.readFile(s),
fileExists: s => host.fileExists(s),
readFile: s => host.readFile!(s), // TODO: GH#18217
fileExists: s => host.fileExists!(s), // TODO: GH#18217
getCanonicalFileName,
log,
}, mapFileName, maps, program, sourcemappedFileCache);
@@ -1593,7 +1601,7 @@ namespace ts {
for (const location of possibleMapLocations) {
const mapPath = toPath(location, getDirectoryPath(fileName), getCanonicalFileName);
if (host.fileExists(mapPath)) {
return convertDocumentToSourceMapper(file, host.readFile(mapPath), mapPath);
return convertDocumentToSourceMapper(file, host.readFile(mapPath)!, mapPath); // TODO: GH#18217
}
}
return file.sourceMapper = sourcemaps.identitySourceMapper;
@@ -1607,7 +1615,7 @@ namespace ts {
function getTargetOfMappedPosition(input: TIn, original = input): TIn {
const info = extract(input);
if (endsWith(info.fileName, Extension.Dts)) {
let file: SourceFileLike = program.getSourceFile(info.fileName);
let file: SourceFileLike | undefined = program.getSourceFile(info.fileName);
if (!file) {
const path = toPath(info.fileName, currentDirectory, getCanonicalFileName);
file = sourcemappedFileCache.get(path);
@@ -1641,17 +1649,17 @@ namespace ts {
})
);
function getTargetOfMappedDeclarationFiles(infos: ReadonlyArray<DefinitionInfo>): DefinitionInfo[] {
function getTargetOfMappedDeclarationFiles(infos: ReadonlyArray<DefinitionInfo> | undefined): DefinitionInfo[] | undefined {
return map(infos, d => getTargetOfMappedDeclarationInfo(d));
}
/// Goto definition
function getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] {
function getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] | undefined {
synchronizeHostData();
return getTargetOfMappedDeclarationFiles(GoToDefinition.getDefinitionAtPosition(program, getValidSourceFile(fileName), position));
}
function getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan {
function getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan | undefined {
synchronizeHostData();
const result = GoToDefinition.getDefinitionAndBoundSpan(program, getValidSourceFile(fileName), position);
if (!result) return result;
@@ -1665,7 +1673,7 @@ namespace ts {
};
}
function getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] {
function getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] | undefined {
synchronizeHostData();
return getTargetOfMappedDeclarationFiles(GoToDefinition.getTypeDefinitionAtPosition(program.getTypeChecker(), getValidSourceFile(fileName), position));
}
@@ -1687,17 +1695,17 @@ namespace ts {
})
);
function getTargetOfMappedImplementationLocations(infos: ReadonlyArray<ImplementationLocation>): ImplementationLocation[] {
function getTargetOfMappedImplementationLocations(infos: ReadonlyArray<ImplementationLocation> | undefined): ImplementationLocation[] | undefined {
return map(infos, d => getTargetOfMappedImplementationLocation(d));
}
function getImplementationAtPosition(fileName: string, position: number): ImplementationLocation[] {
function getImplementationAtPosition(fileName: string, position: number): ImplementationLocation[] | undefined {
synchronizeHostData();
return getTargetOfMappedImplementationLocations(FindAllReferences.getImplementationsAtPosition(program, cancellationToken, program.getSourceFiles(), getValidSourceFile(fileName), position));
}
/// References and Occurrences
function getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[] {
function getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[] | undefined {
return flatMap(getDocumentHighlights(fileName, position, [fileName]), entry => entry.highlightSpans.map<ReferenceEntry>(highlightSpan => ({
fileName: entry.fileName,
textSpan: highlightSpan.textSpan,
@@ -1707,7 +1715,7 @@ namespace ts {
})));
}
function getDocumentHighlights(fileName: string, position: number, filesToSearch: ReadonlyArray<string>): DocumentHighlights[] {
function getDocumentHighlights(fileName: string, position: number, filesToSearch: ReadonlyArray<string>): DocumentHighlights[] | undefined {
Debug.assert(filesToSearch.some(f => normalizePath(f) === fileName));
synchronizeHostData();
const sourceFilesToSearch = map(filesToSearch, f => Debug.assertDefined(program.getSourceFile(f)));
@@ -1715,15 +1723,15 @@ namespace ts {
return DocumentHighlights.getDocumentHighlights(program, cancellationToken, sourceFile, position, sourceFilesToSearch);
}
function findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[] {
function findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[] | undefined {
return getReferences(fileName, position, { findInStrings, findInComments, isForRename: true });
}
function getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] {
return getReferences(fileName, position);
function getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] | undefined {
return getReferences(fileName, position)!;
}
function getReferences(fileName: string, position: number, options?: FindAllReferences.Options) {
function getReferences(fileName: string, position: number, options?: FindAllReferences.Options): ReferenceEntry[] | undefined {
synchronizeHostData();
// Exclude default library when renaming as commonly user don't want to change that file.
@@ -1742,20 +1750,20 @@ namespace ts {
return FindAllReferences.findReferencedEntries(program, cancellationToken, sourceFiles, getValidSourceFile(fileName), position, options);
}
function findReferences(fileName: string, position: number): ReferencedSymbol[] {
function findReferences(fileName: string, position: number): ReferencedSymbol[] | undefined {
synchronizeHostData();
return FindAllReferences.findReferencedSymbols(program, cancellationToken, program.getSourceFiles(), getValidSourceFile(fileName), position);
}
/// NavigateTo
function getNavigateToItems(searchValue: string, maxResultCount?: number, fileName?: string, excludeDtsFiles?: boolean): NavigateToItem[] {
function getNavigateToItems(searchValue: string, maxResultCount?: number, fileName?: string, excludeDtsFiles = false): NavigateToItem[] {
synchronizeHostData();
const sourceFiles = fileName ? [getValidSourceFile(fileName)] : program.getSourceFiles();
return NavigateTo.getNavigateToItems(sourceFiles, program.getTypeChecker(), cancellationToken, searchValue, maxResultCount, excludeDtsFiles);
}
function getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean) {
function getEmitOutput(fileName: string, emitOnlyDtsFiles = false) {
synchronizeHostData();
const sourceFile = getValidSourceFile(fileName);
@@ -1767,7 +1775,7 @@ namespace ts {
/**
* This is a semantic operation.
*/
function getSignatureHelpItems(fileName: string, position: number): SignatureHelpItems {
function getSignatureHelpItems(fileName: string, position: number): SignatureHelpItems | undefined {
synchronizeHostData();
const sourceFile = getValidSourceFile(fileName);
@@ -1784,14 +1792,14 @@ namespace ts {
return getNonBoundSourceFile(fileName);
}
function getNameOrDottedNameSpan(fileName: string, startPos: number, _endPos: number): TextSpan {
function getNameOrDottedNameSpan(fileName: string, startPos: number, _endPos: number): TextSpan | undefined {
const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
// Get node at the location
const node = getTouchingPropertyName(sourceFile, startPos, /*includeJsDocComment*/ false);
if (node === sourceFile) {
return;
return undefined;
}
switch (node.kind) {
@@ -1809,7 +1817,7 @@ namespace ts {
// Cant create the text span
default:
return;
return undefined;
}
let nodeForStartPos = node;
@@ -1841,7 +1849,7 @@ namespace ts {
return createTextSpanFromBounds(nodeForStartPos.getStart(), node.getEnd());
}
function getBreakpointStatementAtPosition(fileName: string, position: number) {
function getBreakpointStatementAtPosition(fileName: string, position: number): TextSpan | undefined {
// doesn't use compiler - no need to synchronize with host
const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
@@ -1986,7 +1994,7 @@ namespace ts {
}
function getEditsForFileRename(oldFilePath: string, newFilePath: string, formatOptions: FormatCodeSettings): ReadonlyArray<FileTextChanges> {
return ts.getEditsForFileRename(getProgram(), oldFilePath, newFilePath, host, formatting.getFormatContext(formatOptions));
return ts.getEditsForFileRename(getProgram()!, oldFilePath, newFilePath, host, formatting.getFormatContext(formatOptions));
}
function applyCodeActionCommand(action: CodeActionCommand): Promise<ApplyCodeActionCommandResult>;
@@ -2006,7 +2014,7 @@ namespace ts {
? host.installPackage({ fileName: toPath(action.file, currentDirectory, getCanonicalFileName), packageName: action.packageName })
: Promise.reject("Host does not implement `installPackage`");
default:
Debug.fail();
return Debug.fail();
// TODO: Debug.assertNever(action); will only work if there is more than one type.
}
}
@@ -2051,7 +2059,7 @@ namespace ts {
return true;
}
function getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean) {
function getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan | undefined {
const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
const range = formatting.getRangeOfEnclosingComment(sourceFile, position, onlyMultiLine);
return range && createTextSpanFromRange(range);
@@ -2077,7 +2085,7 @@ namespace ts {
if (descriptors.length > 0 && !isNodeModulesFile(sourceFile.fileName)) {
const regExp = getTodoCommentsRegExp();
let matchArray: RegExpExecArray;
let matchArray: RegExpExecArray | null;
while (matchArray = regExp.exec(fileContents)) {
cancellationToken.throwIfCancellationRequested();
@@ -2110,13 +2118,13 @@ namespace ts {
continue;
}
let descriptor: TodoCommentDescriptor;
let descriptor: TodoCommentDescriptor | undefined;
for (let i = 0; i < descriptors.length; i++) {
if (matchArray[i + firstDescriptorCaptureIndex]) {
descriptor = descriptors[i];
}
}
Debug.assert(descriptor !== undefined);
if (descriptor === undefined) return Debug.fail();
// We don't want to match something like 'TODOBY', so we make sure a non
// letter/digit follows the match.
@@ -2216,9 +2224,9 @@ namespace ts {
file,
startPosition,
endPosition,
program: getProgram(),
program: getProgram()!,
host,
formatContext: formatting.getFormatContext(formatOptions),
formatContext: formatting.getFormatContext(formatOptions!), // TODO: GH#18217
cancellationToken,
preferences,
};
@@ -2237,8 +2245,7 @@ namespace ts {
refactorName: string,
actionName: string,
preferences: UserPreferences = defaultPreferences,
): RefactorEditInfo {
): RefactorEditInfo | undefined {
synchronizeHostData();
const file = getValidSourceFile(fileName);
return refactor.getEditsForRefactor(getRefactorContext(file, positionOrRange, preferences, formatOptions), refactorName, actionName);
@@ -2307,7 +2314,7 @@ namespace ts {
initializeNameTable(sourceFile);
}
return sourceFile.nameTable;
return sourceFile.nameTable!; // TODO: GH#18217
}
function initializeNameTable(sourceFile: SourceFile): void {
@@ -2320,7 +2327,7 @@ namespace ts {
forEachChild(node, walk);
if (hasJSDocNodes(node)) {
for (const jsDoc of node.jsDoc) {
for (const jsDoc of node.jsDoc!) {
forEachChild(jsDoc, walk);
}
}
@@ -2344,7 +2351,7 @@ namespace ts {
* Returns the containing object literal property declaration given a possible name node, e.g. "a" in x = { "a": 1 }
*/
/* @internal */
export function getContainingObjectLiteralElement(node: Node): ObjectLiteralElement {
export function getContainingObjectLiteralElement(node: Node): ObjectLiteralElement | undefined {
switch (node.kind) {
case SyntaxKind.StringLiteral:
case SyntaxKind.NumericLiteral:
@@ -2363,8 +2370,8 @@ namespace ts {
/* @internal */
export function getPropertySymbolsFromContextualType(typeChecker: TypeChecker, node: ObjectLiteralElement): Symbol[] {
const objectLiteral = <ObjectLiteralExpression | JsxAttributes>node.parent;
const contextualType = typeChecker.getContextualType(objectLiteral);
return getPropertySymbolsFromType(contextualType, node.name);
const contextualType = typeChecker.getContextualType(objectLiteral)!; // TODO: GH#18217
return getPropertySymbolsFromType(contextualType, node.name!)!; // TODO: GH#18217
}
/* @internal */