From 12f3d0d54c8dbdd0ffe996561c8da6f9370fd3d9 Mon Sep 17 00:00:00 2001 From: Andy Date: Fri, 16 Nov 2018 16:02:23 -0800 Subject: [PATCH] Enable --strictPropertyInitialization (#27558) * Enable --strictPropertyInitialization * Code review --- src/harness/client.ts | 4 +- src/harness/fakes.ts | 2 +- src/harness/fourslash.ts | 8 +- src/harness/harnessLanguageService.ts | 6 +- src/harness/typeWriter.ts | 2 +- src/harness/virtualFileSystemWithWatch.ts | 2 +- src/server/editorServices.ts | 6 +- src/server/project.ts | 40 ++--- src/server/scriptInfo.ts | 8 +- src/server/scriptVersionCache.ts | 6 +- src/server/session.ts | 2 +- src/services/formatting/formattingContext.ts | 26 ++- src/services/services.ts | 150 +++++++++--------- src/services/shims.ts | 16 +- src/services/types.ts | 2 +- src/testRunner/compilerRunner.ts | 2 +- src/testRunner/fourslashRunner.ts | 2 + src/testRunner/parallel/host.ts | 4 +- src/testRunner/projectsRunner.ts | 2 +- .../unittests/reuseProgramStructure.ts | 2 +- src/testRunner/unittests/session.ts | 6 +- .../unittests/tsserverProjectSystem.ts | 24 +-- src/tsconfig-base.json | 1 + src/tsserver/server.ts | 6 +- .../reference/api/tsserverlibrary.d.ts | 2 +- tests/baselines/reference/api/typescript.d.ts | 2 +- 26 files changed, 168 insertions(+), 165 deletions(-) diff --git a/src/harness/client.ts b/src/harness/client.ts index 2035802ca67..27365e3ecf1 100644 --- a/src/harness/client.ts +++ b/src/harness/client.ts @@ -37,7 +37,7 @@ namespace ts.server { private sequence = 0; private lineMaps: Map = createMap(); private messages: string[] = []; - private lastRenameEntry: RenameEntry; + private lastRenameEntry: RenameEntry | undefined; constructor(private host: SessionClientHost) { } @@ -431,7 +431,7 @@ namespace ts.server { this.getRenameInfo(fileName, position, findInStrings, findInComments); } - return this.lastRenameEntry.locations; + return this.lastRenameEntry!.locations; } private decodeNavigationBarItems(items: protocol.NavigationBarItem[] | undefined, fileName: string, lineMap: number[]): NavigationBarItem[] { diff --git a/src/harness/fakes.ts b/src/harness/fakes.ts index bd9d62f90e5..d25211d36d3 100644 --- a/src/harness/fakes.ts +++ b/src/harness/fakes.ts @@ -215,7 +215,7 @@ namespace fakes { private _setParentNodes: boolean; private _sourceFiles: collections.SortedMap; - private _parseConfigHost: ParseConfigHost; + private _parseConfigHost: ParseConfigHost | undefined; private _newLine: string; constructor(sys: System | vfs.FileSystem, options = ts.getDefaultCompilerOptions(), setParentNodes = false) { diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 6cd24358556..34fedccc19c 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -158,7 +158,7 @@ namespace FourSlash { public lastKnownMarker = ""; // The file that's currently 'opened' - public activeFile: FourSlashFile; + public activeFile!: FourSlashFile; // Whether or not we should format on keystrokes public enableFormatting = true; @@ -855,9 +855,9 @@ namespace FourSlash { } /** Use `getProgram` instead of accessing this directly. */ - private _program: ts.Program; + private _program: ts.Program | undefined; /** Use `getChecker` instead of accessing this directly. */ - private _checker: ts.TypeChecker; + private _checker: ts.TypeChecker | undefined; private getProgram(): ts.Program { return this._program || (this._program = this.languageService.getProgram()!); // TODO: GH#18217 @@ -3734,7 +3734,7 @@ namespace FourSlashInterface { } export class VerifyNegatable { - public not: VerifyNegatable; + public not: VerifyNegatable | undefined; constructor(protected state: FourSlash.TestState, private negative = false) { if (!negative) { diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index ccad290aed7..581d5cc045d 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -289,8 +289,8 @@ namespace Harness.LanguageService { class ShimLanguageServiceHost extends LanguageServiceAdapterHost implements ts.LanguageServiceShimHost, ts.CoreServicesShimHost { private nativeHost: NativeLanguageServiceHost; - public getModuleResolutionsForFile: (fileName: string) => string; - public getTypeReferenceDirectiveResolutionsForFile: (fileName: string) => string; + public getModuleResolutionsForFile: ((fileName: string) => string) | undefined; + public getTypeReferenceDirectiveResolutionsForFile: ((fileName: string) => string) | undefined; constructor(preprocessToResolve: boolean, cancellationToken?: ts.HostCancellationToken, options?: ts.CompilerOptions) { super(cancellationToken, options); @@ -639,7 +639,7 @@ namespace Harness.LanguageService { // Server adapter class SessionClientHost extends NativeLanguageServiceHost implements ts.server.SessionClientHost { - private client: ts.server.SessionClient; + private client!: ts.server.SessionClient; constructor(cancellationToken: ts.HostCancellationToken | undefined, settings: ts.CompilerOptions | undefined) { super(cancellationToken, settings); diff --git a/src/harness/typeWriter.ts b/src/harness/typeWriter.ts index 67f79a1a1a3..b0b20c92e64 100644 --- a/src/harness/typeWriter.ts +++ b/src/harness/typeWriter.ts @@ -21,7 +21,7 @@ interface TypeWriterResult { } class TypeWriterWalker { - currentSourceFile: ts.SourceFile; + currentSourceFile!: ts.SourceFile; private checker: ts.TypeChecker; diff --git a/src/harness/virtualFileSystemWithWatch.ts b/src/harness/virtualFileSystemWithWatch.ts index 9b030e212f1..e82ee36f8fe 100644 --- a/src/harness/virtualFileSystemWithWatch.ts +++ b/src/harness/virtualFileSystemWithWatch.ts @@ -341,7 +341,7 @@ interface Array {}` private readonly currentDirectory: string; private readonly dynamicPriorityWatchFile: HostWatchFile | undefined; private readonly customRecursiveWatchDirectory: HostWatchDirectory | undefined; - public require: (initialPath: string, moduleName: string) => server.RequireResult; + public require: ((initialPath: string, moduleName: string) => server.RequireResult) | undefined; constructor(public withSafeList: boolean, public useCaseSensitiveFileNames: boolean, executingFilePath: string, currentDirectory: string, fileOrFolderorSymLinkList: ReadonlyArray, public readonly newLine = "\n", public readonly useWindowsStylePath?: boolean, private readonly environmentVariables?: Map) { this.getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames); diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 23baa9119bf..90b516dadfc 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -479,7 +479,7 @@ namespace ts.server { */ private readonly openFilesWithNonRootedDiskPath = createMap(); - private compilerOptionsForInferredProjects: CompilerOptions; + private compilerOptionsForInferredProjects: CompilerOptions | undefined; private compilerOptionsForInferredProjectsPerProjectRoot = createMap(); /** * Project size for configured or external projects @@ -501,7 +501,7 @@ namespace ts.server { private pendingProjectUpdates = createMap(); /* @internal */ - pendingEnsureProjectForOpenFiles: boolean; + pendingEnsureProjectForOpenFiles = false; readonly currentDirectory: NormalizedPath; readonly toCanonicalFileName: (f: string) => string; @@ -1936,7 +1936,7 @@ namespace ts.server { } private createInferredProject(currentDirectory: string | undefined, isSingleInferredProject?: boolean, projectRootPath?: NormalizedPath): InferredProject { - const compilerOptions = projectRootPath && this.compilerOptionsForInferredProjectsPerProjectRoot.get(projectRootPath) || this.compilerOptionsForInferredProjects; + const compilerOptions = projectRootPath && this.compilerOptionsForInferredProjectsPerProjectRoot.get(projectRootPath) || this.compilerOptionsForInferredProjects!; // TODO: GH#18217 const project = new InferredProject(this, this.documentRegistry, compilerOptions, projectRootPath, currentDirectory, this.currentPluginConfigOverrides); if (isSingleInferredProject) { this.inferredProjects.unshift(project); diff --git a/src/server/project.ts b/src/server/project.ts index 45d932abc3e..fa39aa4abe9 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -112,9 +112,9 @@ namespace ts.server { export abstract class Project implements LanguageServiceHost, ModuleResolutionHost { private rootFiles: ScriptInfo[] = []; private rootFilesMap: Map = createMap(); - private program: Program; - private externalFiles: SortedReadonlyArray; - private missingFilesMap: Map; + private program: Program | undefined; + private externalFiles: SortedReadonlyArray | undefined; + private missingFilesMap: Map | undefined; private plugins: PluginModuleWithName[] = []; /*@internal*/ @@ -141,7 +141,7 @@ namespace ts.server { readonly realpath?: (path: string) => string; /*@internal*/ - hasInvalidatedResolution: HasInvalidatedResolution; + hasInvalidatedResolution: HasInvalidatedResolution | undefined; /*@internal*/ resolutionCache: ResolutionCache; @@ -154,7 +154,7 @@ namespace ts.server { /** * Set of files that was returned from the last call to getChangesSinceVersion. */ - private lastReportedFileNames: Map; + private lastReportedFileNames: Map | undefined; /** * Last version that was reported. */ @@ -512,8 +512,8 @@ namespace ts.server { return []; } updateProjectIfDirty(this); - 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)), // TODO: GH#18217 + 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)), // TODO: GH#18217 sourceFile => this.shouldEmitFile(this.projectService.getScriptInfoForPath(sourceFile.path)!) ? sourceFile.fileName : undefined); } @@ -594,7 +594,7 @@ namespace ts.server { /* @internal */ getSourceFileOrConfigFile(path: Path): SourceFile | undefined { - const options = this.program.getCompilerOptions(); + const options = this.program!.getCompilerOptions(); return path === options.configFilePath ? options.configFile : this.getSourceFile(path); } @@ -681,7 +681,7 @@ namespace ts.server { // if language service is not enabled - return just root files return this.rootFiles; } - return map(this.program.getSourceFiles(), sourceFile => { + return map(this.program!.getSourceFiles(), sourceFile => { const scriptInfo = this.projectService.getScriptInfoForPath(sourceFile.resolvedPath); Debug.assert(!!scriptInfo, "getScriptInfo", () => `scriptInfo for a file '${sourceFile.fileName}' Path: '${sourceFile.path}' / '${sourceFile.resolvedPath}' is missing.`); return scriptInfo!; @@ -749,7 +749,7 @@ namespace ts.server { } containsScriptInfo(info: ScriptInfo): boolean { - return this.isRoot(info) || (this.program && this.program.getSourceFileByPath(info.path) !== undefined); + return this.isRoot(info) || (!!this.program && this.program.getSourceFileByPath(info.path) !== undefined); } containsFile(filename: NormalizedPath, requireOpen?: boolean): boolean { @@ -845,7 +845,7 @@ namespace ts.server { // (can reuse cached imports for files that were not changed) // 4. compilation settings were changed in the way that might affect module resolution - drop all caches and collect all data from the scratch if (hasNewProgram || changedFiles.length) { - this.lastCachedUnresolvedImportsList = getUnresolvedImports(this.program, this.cachedUnresolvedImportsPerFile); + this.lastCachedUnresolvedImportsList = getUnresolvedImports(this.program!, this.cachedUnresolvedImportsPerFile); } this.projectService.typingsCache.enqueueInstallTypingsForProject(this, this.lastCachedUnresolvedImportsList, hasAddedorRemovedFiles); @@ -872,7 +872,7 @@ namespace ts.server { } /* @internal */ - getCurrentProgram() { + getCurrentProgram(): Program | undefined { return this.program; } @@ -911,7 +911,7 @@ namespace ts.server { } oldProgram.forEachResolvedProjectReference((resolvedProjectReference, resolvedProjectReferencePath) => { - if (resolvedProjectReference && !this.program.getResolvedProjectReferenceByPath(resolvedProjectReferencePath)) { + if (resolvedProjectReference && !this.program!.getResolvedProjectReferenceByPath(resolvedProjectReferencePath)) { this.detachScriptInfoFromProject(resolvedProjectReference.sourceFile.fileName); } }); @@ -967,8 +967,8 @@ namespace ts.server { this.getCachedDirectoryStructureHost().addOrDeleteFile(fileName, missingFilePath, eventKind); } - if (eventKind === FileWatcherEventKind.Created && this.missingFilesMap.has(missingFilePath)) { - this.missingFilesMap.delete(missingFilePath); + if (eventKind === FileWatcherEventKind.Created && this.missingFilesMap!.has(missingFilePath)) { + this.missingFilesMap!.delete(missingFilePath); fileWatcher.close(); // When a missing file is created, we should update the graph. @@ -983,7 +983,7 @@ namespace ts.server { } private isWatchedMissingFile(path: Path) { - return this.missingFilesMap && this.missingFilesMap.has(path); + return !!this.missingFilesMap && this.missingFilesMap.has(path); } getScriptInfoForNormalizedPath(fileName: NormalizedPath): ScriptInfo | undefined { @@ -1344,14 +1344,14 @@ namespace ts.server { * Otherwise it will create an InferredProject. */ export class ConfiguredProject extends Project { - private typeAcquisition: TypeAcquisition; + private typeAcquisition!: TypeAcquisition; // TODO: GH#18217 /* @internal */ configFileWatcher: FileWatcher | undefined; private directoriesWatchedForWildcards: Map | undefined; readonly canonicalConfigFilePath: NormalizedPath; /* @internal */ - pendingReload: ConfigFileProgramReloadLevel; + pendingReload: ConfigFileProgramReloadLevel | undefined; /* @internal */ pendingReloadReason: string | undefined; @@ -1359,7 +1359,7 @@ namespace ts.server { configFileSpecs: ConfigFileSpecs | undefined; /*@internal*/ - canConfigFileJsonReportNoInputFiles: boolean; + canConfigFileJsonReportNoInputFiles = false; /** Ref count to the project when opened from external project */ private externalProjectRefCount = 0; @@ -1590,7 +1590,7 @@ namespace ts.server { */ export class ExternalProject extends Project { excludedFiles: ReadonlyArray = []; - private typeAcquisition: TypeAcquisition; + private typeAcquisition!: TypeAcquisition; // TODO: GH#18217 /*@internal*/ constructor(public externalProjectName: string, projectService: ProjectService, diff --git a/src/server/scriptInfo.ts b/src/server/scriptInfo.ts index 77329099871..c090b4b14d0 100644 --- a/src/server/scriptInfo.ts +++ b/src/server/scriptInfo.ts @@ -36,15 +36,15 @@ namespace ts.server { /** * True if the text is for the file thats open in the editor */ - public isOpen: boolean; + public isOpen = false; /** * True if the text present is the text from the file on the disk */ - private ownFileText: boolean; + private ownFileText = false; /** * True when reloading contents of file from the disk is pending */ - private pendingReloadFromDisk: boolean; + private pendingReloadFromDisk = false; constructor(private readonly host: ServerHost, private readonly fileName: NormalizedPath, initialVersion: ScriptInfoVersion | undefined, private readonly info: ScriptInfo) { this.version = initialVersion || { svc: 0, text: 0 }; @@ -279,7 +279,7 @@ namespace ts.server { private realpath: Path | undefined; /*@internal*/ - cacheSourceFile: DocumentRegistrySourceFileCache; + cacheSourceFile: DocumentRegistrySourceFileCache | undefined; /*@internal*/ mTime?: number; diff --git a/src/server/scriptVersionCache.ts b/src/server/scriptVersionCache.ts index 0ffb3a195ad..a350ed99f71 100644 --- a/src/server/scriptVersionCache.ts +++ b/src/server/scriptVersionCache.ts @@ -41,11 +41,11 @@ namespace ts.server { // path to start of range private readonly startPath: LineCollection[]; private readonly endBranch: LineCollection[] = []; - private branchNode: LineNode; + private branchNode: LineNode | undefined; // path to current node private readonly stack: LineNode[]; private state = CharRangeSection.Entire; - private lineCollectionAtBranch: LineCollection; + private lineCollectionAtBranch: LineCollection | undefined; private initialText = ""; private trailingText = ""; @@ -383,7 +383,7 @@ namespace ts.server { } export class LineIndex { - root: LineNode; + root!: LineNode; // set this to true to check each edit for accuracy checkEdits = false; diff --git a/src/server/session.ts b/src/server/session.ts index ffc9dc75506..0b9ad913f8a 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -516,7 +516,7 @@ namespace ts.server { protected projectService: ProjectService; private changeSeq = 0; - private currentRequestId: number; + private currentRequestId!: number; private errorCheck: MultistepOperation; protected host: ServerHost; diff --git a/src/services/formatting/formattingContext.ts b/src/services/formatting/formattingContext.ts index 0ccf87680fe..e5a1ff5d4ac 100644 --- a/src/services/formatting/formattingContext.ts +++ b/src/services/formatting/formattingContext.ts @@ -10,11 +10,11 @@ namespace ts.formatting { } export class FormattingContext { - public currentTokenSpan: TextRangeWithKind; - public nextTokenSpan: TextRangeWithKind; - public contextNode: Node; - public currentTokenParent: Node; - public nextTokenParent: Node; + public currentTokenSpan!: TextRangeWithKind; + public nextTokenSpan!: TextRangeWithKind; + public contextNode!: Node; + public currentTokenParent!: Node; + public nextTokenParent!: Node; private contextNodeAllOnSameLine: boolean | undefined; private nextNodeAllOnSameLine: boolean | undefined; @@ -26,17 +26,11 @@ namespace ts.formatting { } public updateContext(currentRange: TextRangeWithKind, currentTokenParent: Node, nextRange: TextRangeWithKind, nextTokenParent: Node, commonParent: Node) { - Debug.assert(currentRange !== undefined, "currentTokenSpan is null"); - Debug.assert(currentTokenParent !== undefined, "currentTokenParent is null"); - Debug.assert(nextRange !== undefined, "nextTokenSpan is null"); - Debug.assert(nextTokenParent !== undefined, "nextTokenParent is null"); - Debug.assert(commonParent !== undefined, "commonParent is null"); - - this.currentTokenSpan = currentRange; - this.currentTokenParent = currentTokenParent; - this.nextTokenSpan = nextRange; - this.nextTokenParent = nextTokenParent; - this.contextNode = commonParent; + this.currentTokenSpan = Debug.assertDefined(currentRange); + this.currentTokenParent = Debug.assertDefined(currentTokenParent); + this.nextTokenSpan = Debug.assertDefined(nextRange); + this.nextTokenParent = Debug.assertDefined(nextTokenParent); + this.contextNode = Debug.assertDefined(commonParent); // drop cached results this.contextNodeAllOnSameLine = undefined; diff --git a/src/services/services.ts b/src/services/services.ts index 2abfe7095ec..20400a3ec47 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -17,9 +17,9 @@ namespace ts { public end: number; public flags: NodeFlags; public parent: Node; - public symbol: Symbol; - public jsDoc: JSDoc[]; - public original: Node; + public symbol!: Symbol; // Actually optional, but it was too annoying to access `node.symbol!` everywhere since in many cases we know it must be defined + public jsDoc?: JSDoc[]; + public original?: Node; public transformFlags: TransformFlags; private _children: Node[] | undefined; @@ -196,14 +196,14 @@ namespace ts { } class TokenOrIdentifierObject implements Node { - public kind: SyntaxKind; + public kind!: SyntaxKind; public pos: number; public end: number; public flags: NodeFlags; public parent: Node; - public symbol: Symbol; - public jsDocComments: JSDoc[]; - public transformFlags: TransformFlags; + public symbol!: Symbol; + public jsDocComments?: JSDoc[]; + public transformFlags!: TransformFlags; constructor(pos: number, end: number) { // Set properties in same order as NodeObject @@ -280,8 +280,8 @@ namespace ts { class SymbolObject implements Symbol { flags: SymbolFlags; escapedName: __String; - declarations: Declaration[]; - valueDeclaration: 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. @@ -334,7 +334,7 @@ namespace ts { } class TokenObject extends TokenOrIdentifierObject implements Token { - public symbol: Symbol; + public symbol!: Symbol; public kind: TKind; constructor(kind: TKind, pos: number, end: number) { @@ -344,10 +344,10 @@ namespace ts { } class IdentifierObject extends TokenOrIdentifierObject implements Identifier { - public kind: SyntaxKind.Identifier; - public escapedText: __String; - public symbol: Symbol; - public autoGenerateFlags: GeneratedIdentifierFlags; + public kind!: SyntaxKind.Identifier; + public escapedText!: __String; + public symbol!: Symbol; + public autoGenerateFlags!: GeneratedIdentifierFlags; _primaryExpressionBrand: any; _memberExpressionBrand: any; _leftHandSideExpressionBrand: any; @@ -355,7 +355,7 @@ namespace ts { _unaryExpressionBrand: any; _expressionBrand: any; _declarationBrand: any; - /*@internal*/typeArguments: NodeArray; + /*@internal*/typeArguments!: NodeArray; constructor(_kind: SyntaxKind.Identifier, pos: number, end: number) { super(pos, end); } @@ -370,8 +370,8 @@ namespace ts { checker: TypeChecker; flags: TypeFlags; objectFlags?: ObjectFlags; - id: number; - symbol: Symbol; + id!: number; + symbol!: Symbol; constructor(checker: TypeChecker, flags: TypeFlags) { this.checker = checker; this.flags = flags; @@ -447,16 +447,16 @@ namespace ts { class SignatureObject implements Signature { checker: TypeChecker; - declaration: SignatureDeclaration; + declaration!: SignatureDeclaration; typeParameters?: TypeParameter[]; - parameters: Symbol[]; - thisParameter: Symbol; - resolvedReturnType: Type; + parameters!: Symbol[]; + thisParameter!: Symbol; + resolvedReturnType!: Type; resolvedTypePredicate: TypePredicate | undefined; - minTypeArgumentCount: number; - minArgumentCount: number; - hasRestParameter: boolean; - hasLiteralTypes: boolean; + minTypeArgumentCount!: number; + minArgumentCount!: number; + hasRestParameter!: boolean; + hasLiteralTypes!: boolean; // 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. @@ -536,55 +536,55 @@ namespace ts { } class SourceFileObject extends NodeObject implements SourceFile { - public kind: SyntaxKind.SourceFile; + public kind!: SyntaxKind.SourceFile; public _declarationBrand: any; - public fileName: string; - public path: Path; - public resolvedPath: Path; - public originalFileName: string; - public text: string; - public scriptSnapshot: IScriptSnapshot; - public lineMap: ReadonlyArray; + public fileName!: string; + public path!: Path; + public resolvedPath!: Path; + public originalFileName!: string; + public text!: string; + public scriptSnapshot!: IScriptSnapshot; + public lineMap!: ReadonlyArray; - public statements: NodeArray; - public endOfFileToken: Token; + public statements!: NodeArray; + public endOfFileToken!: Token; - public amdDependencies: { name: string; path: string }[]; - public moduleName: string; - public referencedFiles: FileReference[]; - public typeReferenceDirectives: FileReference[]; - public libReferenceDirectives: FileReference[]; + public amdDependencies!: { name: string; path: string }[]; + public moduleName!: string; + public referencedFiles!: FileReference[]; + public typeReferenceDirectives!: FileReference[]; + public libReferenceDirectives!: FileReference[]; - public syntacticDiagnostics: DiagnosticWithLocation[]; - public parseDiagnostics: DiagnosticWithLocation[]; - public bindDiagnostics: DiagnosticWithLocation[]; + public syntacticDiagnostics!: DiagnosticWithLocation[]; + public parseDiagnostics!: DiagnosticWithLocation[]; + public bindDiagnostics!: DiagnosticWithLocation[]; public bindSuggestionDiagnostics?: DiagnosticWithLocation[]; - public isDeclarationFile: boolean; - public isDefaultLib: boolean; - public hasNoDefaultLib: boolean; - public externalModuleIndicator: Node; // The first node that causes this file to be an external module - public commonJsModuleIndicator: Node; // The first node that causes this file to be a CommonJS module - public nodeCount: number; - public identifierCount: number; - public symbolCount: number; - public version: string; - public scriptKind: ScriptKind; - public languageVersion: ScriptTarget; - public languageVariant: LanguageVariant; - public identifiers: Map; - public nameTable: UnderscoreEscapedMap; - public resolvedModules: Map; - public resolvedTypeReferenceDirectiveNames: Map; - public imports: ReadonlyArray; - public moduleAugmentations: StringLiteral[]; - private namedDeclarations: Map; - public ambientModuleNames: string[]; + public isDeclarationFile!: boolean; + public isDefaultLib!: boolean; + public hasNoDefaultLib!: boolean; + public externalModuleIndicator!: Node; // The first node that causes this file to be an external module + public commonJsModuleIndicator!: Node; // The first node that causes this file to be a CommonJS module + public nodeCount!: number; + public identifierCount!: number; + public symbolCount!: number; + public version!: string; + public scriptKind!: ScriptKind; + public languageVersion!: ScriptTarget; + public languageVariant!: LanguageVariant; + public identifiers!: Map; + public nameTable: UnderscoreEscapedMap | undefined; + public resolvedModules: Map | undefined; + public resolvedTypeReferenceDirectiveNames!: Map; + public imports!: ReadonlyArray; + public moduleAugmentations!: StringLiteral[]; + private namedDeclarations: Map | undefined; + public ambientModuleNames!: string[]; public checkJsDirective: CheckJsDirective | undefined; - public possiblyContainDynamicImport: boolean; - public pragmas: PragmaMap; - public localJsxFactory: EntityName; - public localJsxNamespace: __String; + public possiblyContainDynamicImport?: boolean; + public pragmas!: PragmaMap; + public localJsxFactory: EntityName | undefined; + public localJsxNamespace: __String | undefined; constructor(kind: SyntaxKind, pos: number, end: number) { super(kind, pos, end); @@ -774,7 +774,7 @@ namespace ts { } class SourceMapSourceObject implements SourceMapSource { - lineMap: number[]; + lineMap!: number[]; constructor(public fileName: string, public text: string, public skipTrivia?: (pos: number) => number) { } public getLineAndCharacterOfPosition(pos: number): LineAndCharacter { @@ -955,10 +955,10 @@ namespace ts { class SyntaxTreeCache { // For our syntactic only features, we also keep a cache of the syntax tree for the // currently edited file. - private currentFileName: string; - private currentFileVersion: string; - private currentFileScriptSnapshot: IScriptSnapshot; - private currentSourceFile: SourceFile; + private currentFileName: string | undefined; + private currentFileVersion: string | undefined; + private currentFileScriptSnapshot: IScriptSnapshot | undefined; + private currentSourceFile: SourceFile | undefined; constructor(private host: LanguageServiceHost) { } @@ -980,8 +980,8 @@ namespace ts { } else if (this.currentFileVersion !== version) { // This is the same file, just a newer version. Incrementally parse the file. - const editRange = scriptSnapshot.getChangeRange(this.currentFileScriptSnapshot); - sourceFile = updateLanguageServiceSourceFile(this.currentSourceFile, scriptSnapshot, version, editRange); + const editRange = scriptSnapshot.getChangeRange(this.currentFileScriptSnapshot!); + sourceFile = updateLanguageServiceSourceFile(this.currentSourceFile!, scriptSnapshot, version, editRange); } if (sourceFile) { @@ -992,7 +992,7 @@ namespace ts { this.currentSourceFile = sourceFile; } - return this.currentSourceFile; + return this.currentSourceFile!; } } diff --git a/src/services/shims.ts b/src/services/shims.ts index 3ee11817c49..ff66680bdbc 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -331,9 +331,9 @@ namespace ts { private loggingEnabled = false; private tracingEnabled = false; - public resolveModuleNames: (moduleName: string[], containingFile: string) => (ResolvedModuleFull | undefined)[]; - public resolveTypeReferenceDirectives: (typeDirectiveNames: string[], containingFile: string) => (ResolvedTypeReferenceDirective | undefined)[]; - public directoryExists: (directoryName: string) => boolean; + public resolveModuleNames: ((moduleName: string[], containingFile: string) => (ResolvedModuleFull | undefined)[]) | undefined; + public resolveTypeReferenceDirectives: ((typeDirectiveNames: string[], containingFile: string) => (ResolvedTypeReferenceDirective | undefined)[]) | undefined; + public directoryExists: ((directoryName: string) => boolean) | undefined; constructor(private shimHost: LanguageServiceShimHost) { // if shimHost is a COM object then property check will become method call with no arguments. @@ -490,13 +490,19 @@ namespace ts { public useCaseSensitiveFileNames: boolean; constructor(private shimHost: CoreServicesShimHost) { - this.useCaseSensitiveFileNames = this.shimHost.useCaseSensitiveFileNames ? this.shimHost.useCaseSensitiveFileNames() : false; + this.useCaseSensitiveFileNames = this.shimHost.useCaseSensitiveFileNames ? this.shimHost.useCaseSensitiveFileNames() : false; if ("directoryExists" in this.shimHost) { this.directoryExists = directoryName => this.shimHost.directoryExists(directoryName); } + else { + this.directoryExists = undefined!; // TODO: GH#18217 + } if ("realpath" in this.shimHost) { this.realpath = path => this.shimHost.realpath!(path); // TODO: GH#18217 } + else { + this.realpath = undefined!; // TODO: GH#18217 + } } public readDirectory(rootDir: string, extensions: ReadonlyArray, exclude: ReadonlyArray, include: ReadonlyArray, depth?: number): string[] { @@ -1182,7 +1188,7 @@ namespace ts { export class TypeScriptServicesFactory implements ShimFactory { private _shims: Shim[] = []; - private documentRegistry: DocumentRegistry; + private documentRegistry: DocumentRegistry | undefined; /* * Returns script API version. diff --git a/src/services/types.ts b/src/services/types.ts index 0d14ad2b978..69f07b705a7 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -489,7 +489,7 @@ namespace ts { position: number; } - export class TextChange { + export interface TextChange { span: TextSpan; newText: string; } diff --git a/src/testRunner/compilerRunner.ts b/src/testRunner/compilerRunner.ts index bb481eca03e..c55cd1aa511 100644 --- a/src/testRunner/compilerRunner.ts +++ b/src/testRunner/compilerRunner.ts @@ -13,7 +13,7 @@ class CompilerBaselineRunner extends RunnerBase { private testSuiteName: TestRunnerKind; private emit: boolean; - public options: string; + public options: string | undefined; constructor(public testType: CompilerTestType) { super(); diff --git a/src/testRunner/fourslashRunner.ts b/src/testRunner/fourslashRunner.ts index 583311ba30e..f7d7bf621d5 100644 --- a/src/testRunner/fourslashRunner.ts +++ b/src/testRunner/fourslashRunner.ts @@ -21,6 +21,8 @@ class FourSlashRunner extends RunnerBase { this.basePath = "tests/cases/fourslash/server"; this.testSuiteName = "fourslash-server"; break; + default: + throw ts.Debug.assertNever(testType); } } diff --git a/src/testRunner/parallel/host.ts b/src/testRunner/parallel/host.ts index c10be2a9ff8..376896a4697 100644 --- a/src/testRunner/parallel/host.ts +++ b/src/testRunner/parallel/host.ts @@ -28,9 +28,9 @@ namespace Harness.Parallel.Host { let totalCost = 0; class RemoteSuite extends Mocha.Suite { - suites: RemoteSuite[]; + suites!: RemoteSuite[]; suiteMap = ts.createMap(); - tests: RemoteTest[]; + tests!: RemoteTest[]; constructor(title: string) { super(title); this.pending = false; diff --git a/src/testRunner/projectsRunner.ts b/src/testRunner/projectsRunner.ts index 457201c1387..f4e51afab4c 100644 --- a/src/testRunner/projectsRunner.ts +++ b/src/testRunner/projectsRunner.ts @@ -67,7 +67,7 @@ namespace project { class ProjectCompilerHost extends fakes.CompilerHost { private _testCase: ProjectRunnerTestCase & ts.CompilerOptions; - private _projectParseConfigHost: ProjectParseConfigHost; + private _projectParseConfigHost: ProjectParseConfigHost | undefined; constructor(sys: fakes.System | vfs.FileSystem, compilerOptions: ts.CompilerOptions, _testCaseJustName: string, testCase: ProjectRunnerTestCase & ts.CompilerOptions, _moduleKind: ts.ModuleKind) { super(sys, compilerOptions); diff --git a/src/testRunner/unittests/reuseProgramStructure.ts b/src/testRunner/unittests/reuseProgramStructure.ts index 0ab50a65105..9e56b48a911 100644 --- a/src/testRunner/unittests/reuseProgramStructure.ts +++ b/src/testRunner/unittests/reuseProgramStructure.ts @@ -27,7 +27,7 @@ namespace ts { } export class SourceText implements IScriptSnapshot { - private fullText: string; + private fullText: string | undefined; constructor(private references: string, private importsAndExports: string, diff --git a/src/testRunner/unittests/session.ts b/src/testRunner/unittests/session.ts index ac5d8093e31..bcbadac1d52 100644 --- a/src/testRunner/unittests/session.ts +++ b/src/testRunner/unittests/session.ts @@ -437,7 +437,7 @@ namespace ts.server { const command = "testhandler"; class TestSession extends Session { - lastSent: protocol.Message; + lastSent: protocol.Message | undefined; private exceptionRaisingHandler(_request: protocol.Request): { response?: any, responseRequired: boolean } { f1(); return Debug.fail(); // unreachable, throw to make compiler happy @@ -491,7 +491,7 @@ namespace ts.server { describe("how Session is extendable via subclassing", () => { class TestSession extends Session { - lastSent: protocol.Message; + lastSent: protocol.Message | undefined; customHandler = "testhandler"; constructor() { super({ @@ -610,7 +610,7 @@ namespace ts.server { } class InProcClient { - private server: InProcSession; + private server: InProcSession | undefined; private seq = 0; private callbacks: ((resp: protocol.Response) => void)[] = []; private eventHandlers = createMap<(args: any) => void>(); diff --git a/src/testRunner/unittests/tsserverProjectSystem.ts b/src/testRunner/unittests/tsserverProjectSystem.ts index cda60e9b5ff..6681b4bfa54 100644 --- a/src/testRunner/unittests/tsserverProjectSystem.ts +++ b/src/testRunner/unittests/tsserverProjectSystem.ts @@ -80,7 +80,7 @@ namespace ts.projectSystem { } export class TestTypingsInstaller extends TI.TypingsInstaller implements server.ITypingsInstaller { - protected projectService: server.ProjectService; + protected projectService!: server.ProjectService; constructor( readonly globalTypingsCacheLocation: string, throttleLimit: number, @@ -282,7 +282,7 @@ namespace ts.projectSystem { class TestSession extends server.Session { private seq = 0; public events: protocol.Event[] = []; - public host: TestServerHost; + public host!: TestServerHost; getProjectService() { return this.projectService; @@ -9396,16 +9396,16 @@ export const x = 10;` const project = getProject(service); const moduleInfo = service.getScriptInfo(moduleFile.path)!; - const sourceFile = moduleInfo.cacheSourceFile.sourceFile; + const sourceFile = moduleInfo.cacheSourceFile!.sourceFile; assert.equal(project.getSourceFile(moduleInfo.path), sourceFile); // edit file changeFileToNotImportModule(service); - assert.equal(moduleInfo.cacheSourceFile.sourceFile, sourceFile); + assert.equal(moduleInfo.cacheSourceFile!.sourceFile, sourceFile); // write content back changeFileToImportModule(service); - assert.equal(moduleInfo.cacheSourceFile.sourceFile, sourceFile); + assert.equal(moduleInfo.cacheSourceFile!.sourceFile, sourceFile); assert.equal(project.getSourceFile(moduleInfo.path), sourceFile); }); @@ -9414,21 +9414,21 @@ export const x = 10;` const project = getProject(service); const moduleInfo = service.getScriptInfo(moduleFile.path)!; - const sourceFile = moduleInfo.cacheSourceFile.sourceFile; + const sourceFile = moduleInfo.cacheSourceFile!.sourceFile; assert.equal(project.getSourceFile(moduleInfo.path), sourceFile); // edit file changeFileToNotImportModule(service); - assert.equal(moduleInfo.cacheSourceFile.sourceFile, sourceFile); + assert.equal(moduleInfo.cacheSourceFile!.sourceFile, sourceFile); const updatedModuleContent = moduleFile.content + "\nexport const b: number;"; host.writeFile(moduleFile.path, updatedModuleContent); // write content back changeFileToImportModule(service); - assert.notEqual(moduleInfo.cacheSourceFile.sourceFile, sourceFile); - assert.equal(project.getSourceFile(moduleInfo.path), moduleInfo.cacheSourceFile.sourceFile); - assert.equal(moduleInfo.cacheSourceFile.sourceFile.text, updatedModuleContent); + assert.notEqual(moduleInfo.cacheSourceFile!.sourceFile, sourceFile); + assert.equal(project.getSourceFile(moduleInfo.path), moduleInfo.cacheSourceFile!.sourceFile); + assert.equal(moduleInfo.cacheSourceFile!.sourceFile.text, updatedModuleContent); }); }); @@ -9457,7 +9457,7 @@ export const x = 10;` // large file for non ts file should be empty and for ts file should have content const service = session.getProjectService(); const info = service.getScriptInfo(largeFile.path)!; - assert.equal(info.cacheSourceFile.sourceFile.text, useLargeTsFile ? largeFile.content : ""); + assert.equal(info.cacheSourceFile!.sourceFile.text, useLargeTsFile ? largeFile.content : ""); assert.deepEqual(largeFileReferencedEvents, useLargeTsFile ? emptyArray : [{ eventName: server.LargeFileReferencedEvent, @@ -10970,7 +10970,7 @@ fn5();` function checkDeclarationFiles(file: File, session: TestSession, expectedFiles: ReadonlyArray): void { openFilesForSession([file], session); const project = Debug.assertDefined(session.getProjectService().getDefaultProjectForFile(file.path as server.NormalizedPath, /*ensureProject*/ false)); - const program = project.getCurrentProgram(); + const program = project.getCurrentProgram()!; const output = getFileEmitOutput(program, Debug.assertDefined(program.getSourceFile(file.path)), /*emitOnlyDtsFiles*/ true); closeFilesForSession([file], session); diff --git a/src/tsconfig-base.json b/src/tsconfig-base.json index a6df4100d9f..e9925f3a98b 100644 --- a/src/tsconfig-base.json +++ b/src/tsconfig-base.json @@ -14,6 +14,7 @@ "strictNullChecks": true, "noImplicitAny": true, "noImplicitThis": true, + "strictPropertyInitialization": true, "noUnusedLocals": true, "noUnusedParameters": true, diff --git a/src/tsserver/server.ts b/src/tsserver/server.ts index 8a5c5b50906..66574ceaac1 100644 --- a/src/tsserver/server.ts +++ b/src/tsserver/server.ts @@ -215,13 +215,13 @@ namespace ts.server { } class NodeTypingsInstaller implements ITypingsInstaller { - private installer: NodeChildProcess; - private projectService: ProjectService; + private installer!: NodeChildProcess; + private projectService!: ProjectService; private activeRequestCount = 0; private requestQueue: QueuedOperation[] = []; private requestMap = createMap(); // Maps operation ID to newest requestQueue entry with that ID /** We will lazily request the types registry on the first call to `isKnownTypesPackageName` and store it in `typesRegistryCache`. */ - private requestedRegistry: boolean; + private requestedRegistry = false; private typesRegistryCache: Map> | undefined; // This number is essentially arbitrary. Processing more than one typings request diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index c3076883b46..4aa83c7209c 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -4869,7 +4869,7 @@ declare namespace ts { message: string; position: number; } - class TextChange { + interface TextChange { span: TextSpan; newText: string; } diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index f4cebf2da7f..0702b175fb5 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -4869,7 +4869,7 @@ declare namespace ts { message: string; position: number; } - class TextChange { + interface TextChange { span: TextSpan; newText: string; }