Repository: OmniSharp/omnisharp-vscode
Pull request #5349 (2022-08-19 06:21:19)

Observer nullability fixes
Changes are pretty straightforward. No behavioral changes (except possibly returning the empty string instead of undefined for SolutionId in telemetry).

Brings the number of strict errors down from 403 to 378.


Patch:
diff --git a/src/observers/BackgroundWorkStatusBarObserver.ts b/src/observers/BackgroundWorkStatusBarObserver.ts
index c49a419f..46cddee1 100644
--- a/src/observers/BackgroundWorkStatusBarObserver.ts
+++ b/src/observers/BackgroundWorkStatusBarObserver.ts
@@ -15,7 +15,7 @@ export class BackgroundWorkStatusBarObserver extends BaseStatusBarItemObserver {
 
             if (asProjectEvent.message.Status === DiagnosticStatus.Processing) {
                 let projectFile = asProjectEvent.message.ProjectFilePath.replace(/^.*[\\\/]/, '');
-                this.SetAndShowStatusBar(`$(sync~spin) Analyzing ${projectFile}`, 'o.showOutput', null, `Analyzing ${projectFile}`);
+                this.SetAndShowStatusBar(`$(sync~spin) Analyzing ${projectFile}`, 'o.showOutput', undefined, `Analyzing ${projectFile}`);
             }
             else {
                 this.ResetAndHideStatusBar();
@@ -23,4 +23,3 @@ export class BackgroundWorkStatusBarObserver extends BaseStatusBarItemObserver {
         }
     }
 }
-
diff --git a/src/observers/BaseStatusBarItemObserver.ts b/src/observers/BaseStatusBarItemObserver.ts
index 3919f163..825afc70 100644
--- a/src/observers/BaseStatusBarItemObserver.ts
+++ b/src/observers/BaseStatusBarItemObserver.ts
@@ -20,7 +20,7 @@ export abstract class BaseStatusBarItemObserver {
     }
 
     public ResetAndHideStatusBar() {
-        this.statusBarItem.text = undefined;
+        this.statusBarItem.text = '';
         this.statusBarItem.command = undefined;
         this.statusBarItem.color = undefined;
         this.statusBarItem.tooltip = undefined;
@@ -28,4 +28,4 @@ export abstract class BaseStatusBarItemObserver {
     }
 
     abstract post: (event: BaseEvent) => void;
-}
\ No newline at end of file
+}
diff --git a/src/observers/CsharpLoggerObserver.ts b/src/observers/CsharpLoggerObserver.ts
index 07ae6911..831d501d 100644
--- a/src/observers/CsharpLoggerObserver.ts
+++ b/src/observers/CsharpLoggerObserver.ts
@@ -9,7 +9,7 @@ import { PackageError } from "../packageManager/PackageError";
 import { EventType } from "../omnisharp/EventType";
 
 export class CsharpLoggerObserver extends BaseLoggerObserver {
-    private dots: number;
+    private dots: number = 0;
 
     public post = (event: Event.BaseEvent) => {
         switch (event.type) {
@@ -146,4 +146,4 @@ export class CsharpLoggerObserver extends BaseLoggerObserver {
     private handleDocumentSynchronizationFailure(event: Event.DocumentSynchronizationFailure) {
         this.logger.appendLine(`Failed to synchronize document '${event.documentPath}': ${event.errorMessage}`);
     }
-}
\ No newline at end of file
+}
diff --git a/src/observers/OmnisharpLoggerObserver.ts b/src/observers/OmnisharpLoggerObserver.ts
index 664f8c1c..b5ef3c32 100644
--- a/src/observers/OmnisharpLoggerObserver.ts
+++ b/src/observers/OmnisharpLoggerObserver.ts
@@ -83,7 +83,7 @@ export class OmnisharpLoggerObserver extends BaseLoggerObserver {
         this.logger.append(`OmniSharp server started`);
         if (event.hostVersion) {
             this.logger.append(` with ${event.hostIsMono ? 'Mono' : '.NET'} ${event.hostVersion}`);
-            if (event.hostPath?.length > 0) {
+            if (event.hostPath && event.hostPath.length > 0) {
                 this.logger.append(` (${event.hostPath})`);
             }
         }
diff --git a/src/observers/OptionProvider.ts b/src/observers/OptionProvider.ts
index e8eeec80..1b1d0b26 100644
--- a/src/observers/OptionProvider.ts
+++ b/src/observers/OptionProvider.ts
@@ -6,7 +6,7 @@
 import { Options } from "../omnisharp/options";
 import { Subscription, Observable } from "rxjs";
 export default class OptionProvider {
-    private options: Options;
+    private options?: Options;
     private subscription: Subscription;
 
     constructor(optionObservable: Observable<Options>) {
@@ -24,4 +24,4 @@ export default class OptionProvider {
     public dispose = () => {
         this.subscription.unsubscribe();
     }
-}
\ No newline at end of file
+}
diff --git a/src/observers/TelemetryObserver.ts b/src/observers/TelemetryObserver.ts
index fd7f8889..3c93663a 100644
--- a/src/observers/TelemetryObserver.ts
+++ b/src/observers/TelemetryObserver.ts
@@ -19,8 +19,8 @@ export interface ITelemetryReporter {
 export class TelemetryObserver {
     private reporter: ITelemetryReporter;
     private platformInfo: PlatformInformation;
-    private solutionId: string;
-    private dotnetInfo: DotnetInfo;
+    private solutionId?: string;
+    private dotnetInfo?: DotnetInfo;
 
     constructor(platformInfo: PlatformInformation, reporterCreator: () => ITelemetryReporter) {
         this.platformInfo = platformInfo;
@@ -64,7 +64,7 @@ export class TelemetryObserver {
     }
 
     private handleTelemetryEventMeasures(event: TelemetryEventWithMeasures) {
-        this.reporter.sendTelemetryEvent(event.eventName, null, event.measures);
+        this.reporter.sendTelemetryEvent(event.eventName, undefined, event.measures);
     }
 
     private async handleOmnisharpInitialisation(event: OmnisharpInitialisation) {
@@ -90,16 +90,16 @@ export class TelemetryObserver {
 
     private handleTestExecutionCountReport(event: TestExecutionCountReport) {
         if (event.debugCounts) {
-            this.reporter.sendTelemetryEvent('DebugTest', null, event.debugCounts);
+            this.reporter.sendTelemetryEvent('DebugTest', undefined, event.debugCounts);
         }
         if (event.runCounts) {
-            this.reporter.sendTelemetryEvent('RunTest', null, event.runCounts);
+            this.reporter.sendTelemetryEvent('RunTest', undefined, event.runCounts);
         }
     }
 
     private handleProjectConfigurationReceived(event: ProjectConfiguration, telemetryProps: { [key: string]: string }) {
         let projectConfig = event.projectConfiguration;
-        telemetryProps['SolutionId'] = this.solutionId;
+        telemetryProps['SolutionId'] = this.solutionId ?? "";
         telemetryProps['ProjectId'] = projectConfig.ProjectId;
         telemetryProps['SessionId'] = projectConfig.SessionId;
         telemetryProps['OutputType'] = projectConfig.OutputKind?.toString() ?? "";
diff --git a/src/observers/utils/ShowInformationMessage.ts b/src/observers/utils/ShowInformationMessage.ts
index 02537f3e..9e4a94c3 100644
--- a/src/observers/utils/ShowInformationMessage.ts
+++ b/src/observers/utils/ShowInformationMessage.ts
@@ -8,12 +8,12 @@ import MessageItemWithCommand from "./MessageItemWithCommand";
 
 export default async function showInformationMessage(vscode: vscode, message: string, ...items: MessageItemWithCommand[]) {
     try {
-        let value = await vscode.window.showInformationMessage<MessageItemWithCommand>(message, ...items);
-        if (value && value.command) {
+        const value = await vscode.window.showInformationMessage<MessageItemWithCommand>(message, ...items);
+        if (value?.command) {
             vscode.commands.executeCommand(value.command);
         }
     }
     catch (err) {
         console.log(err);
     }
-}
\ No newline at end of file
+}
diff --git a/src/observers/utils/ShowWarningMessage.ts b/src/observers/utils/ShowWarningMessage.ts
index 563caff4..9bf6bc60 100644
--- a/src/observers/utils/ShowWarningMessage.ts
+++ b/src/observers/utils/ShowWarningMessage.ts
@@ -8,12 +8,12 @@ import MessageItemWithCommand from "./MessageItemWithCommand";
 
 export default async function showWarningMessage(vscode: vscode, message: string, ...items: MessageItemWithCommand[]) {
     try {
-        let value = await vscode.window.showWarningMessage<MessageItemWithCommand>(message, ...items);
-        if (value && value.command) {
+        const value = await vscode.window.showWarningMessage<MessageItemWithCommand>(message, ...items);
+        if (value?.command) {
             await vscode.commands.executeCommand<string>(value.command);
         }
     }
     catch (err) {
         console.log(err);
     }
-}
\ No newline at end of file
+}


Test patch:
diff --git a/test/unitTests/logging/BackgroundWorkStatusBarObserver.test.ts b/test/unitTests/logging/BackgroundWorkStatusBarObserver.test.ts
index 1a29ccef..24840441 100644
--- a/test/unitTests/logging/BackgroundWorkStatusBarObserver.test.ts
+++ b/test/unitTests/logging/BackgroundWorkStatusBarObserver.test.ts
@@ -38,6 +38,6 @@ suite('BackgroundWorkStatusBarObserver', () => {
         observer.post(event);
         expect(hideCalled).to.be.true;
         expect(showCalled).to.be.false;
-        expect(statusBarItem.text).to.be.undefined;
+        expect(statusBarItem.text).to.be.equal('');
     });
-});
\ No newline at end of file
+});
diff --git a/test/unitTests/logging/OmnisharpStatusBarObserver.test.ts b/test/unitTests/logging/OmnisharpStatusBarObserver.test.ts
index 703062a8..e6d1041f 100644
--- a/test/unitTests/logging/OmnisharpStatusBarObserver.test.ts
+++ b/test/unitTests/logging/OmnisharpStatusBarObserver.test.ts
@@ -14,7 +14,7 @@ suite('OmnisharpStatusBarObserver', () => {
     let hideCalled: boolean;
 
     setup(() => {
-        statusBarItem.text = undefined;
+        statusBarItem.text = '';
         statusBarItem.color = undefined;
         statusBarItem.command = undefined;
         statusBarItem.tooltip = undefined;
@@ -84,7 +84,7 @@ suite('OmnisharpStatusBarObserver', () => {
         let event = new OmnisharpServerOnStop();
         observer.post(event);
         expect(hideCalled).to.be.true;
-        expect(statusBarItem.text).to.be.undefined;
+        expect(statusBarItem.text).to.be.equal('');
         expect(statusBarItem.command).to.be.undefined;
         expect(statusBarItem.color).to.be.undefined;
     });
@@ -118,8 +118,8 @@ suite('OmnisharpStatusBarObserver', () => {
         observer.post(successEvent);
 
         expect(hideCalled).to.be.true;
-        expect(statusBarItem.text).to.be.undefined;
+        expect(statusBarItem.text).to.be.equal('');
         expect(statusBarItem.command).to.be.undefined;
         expect(statusBarItem.color).to.be.undefined;
     });
-});
\ No newline at end of file
+});
diff --git a/test/unitTests/logging/ProjectStatusBarObserver.test.ts b/test/unitTests/logging/ProjectStatusBarObserver.test.ts
index 156dd91f..bceb1b80 100644
--- a/test/unitTests/logging/ProjectStatusBarObserver.test.ts
+++ b/test/unitTests/logging/ProjectStatusBarObserver.test.ts
@@ -29,7 +29,7 @@ suite('ProjectStatusBarObserver', () => {
         let event = new OmnisharpServerOnStop();
         observer.post(event);
         expect(hideCalled).to.be.true;
-        expect(statusBarItem.text).to.be.undefined;
+        expect(statusBarItem.text).to.be.equal('');
         expect(statusBarItem.command).to.be.undefined;
         expect(statusBarItem.color).to.be.undefined;
     });
@@ -44,10 +44,10 @@ suite('ProjectStatusBarObserver', () => {
 
     suite('WorkspaceInformationUpdated', () => {
         test('Project status is hidden if there is no MSBuild Object', () => {
-            let event = getWorkspaceInformationUpdated(null);
+            let event = getWorkspaceInformationUpdated(undefined);
             observer.post(event);
             expect(hideCalled).to.be.true;
-            expect(statusBarItem.text).to.be.undefined;
+            expect(statusBarItem.text).to.be.equal('');
             expect(statusBarItem.command).to.be.undefined;
         });
 
@@ -55,8 +55,8 @@ suite('ProjectStatusBarObserver', () => {
             let event = getWorkspaceInformationUpdated(getMSBuildWorkspaceInformation("somePath", []));
             observer.post(event);
             expect(showCalled).to.be.true;
-            expect(statusBarItem.text).to.contain(event.info.MsBuild.SolutionPath);
+            expect(statusBarItem.text).to.contain(event.info.MsBuild?.SolutionPath);
             expect(statusBarItem.command).to.equal('o.pickProjectAndStart');
         });
     });
-});
\ No newline at end of file
+});
diff --git a/test/unitTests/options.test.ts b/test/unitTests/options.test.ts
index 611363eb..71879ce0 100644
--- a/test/unitTests/options.test.ts
+++ b/test/unitTests/options.test.ts
@@ -40,7 +40,7 @@ suite("Options tests", () => {
 
     test('Verify return no excluded paths when files.exclude empty', () => {
         const vscode = getVSCodeWithConfig();
-        updateConfig(vscode, null, 'files.exclude', {});
+        updateConfig(vscode, undefined, 'files.exclude', {});
 
         const excludedPaths = Options.getExcludedPaths(vscode);
         expect(excludedPaths).to.be.empty;
@@ -48,7 +48,7 @@ suite("Options tests", () => {
 
     test('Verify return excluded paths when files.exclude populated', () => {
         const vscode = getVSCodeWithConfig();
-        updateConfig(vscode, null, 'files.exclude', { "**/node_modules": true, "**/assets": false });
+        updateConfig(vscode, undefined, 'files.exclude', { "**/node_modules": true, "**/assets": false });
 
         const excludedPaths = Options.getExcludedPaths(vscode);
         expect(excludedPaths).to.equalTo(["**/node_modules"]);
@@ -56,8 +56,8 @@ suite("Options tests", () => {
 
     test('Verify return no excluded paths when files.exclude and search.exclude empty', () => {
         const vscode = getVSCodeWithConfig();
-        updateConfig(vscode, null, 'files.exclude', {});
-        updateConfig(vscode, null, 'search.exclude', {});
+        updateConfig(vscode, undefined, 'files.exclude', {});
+        updateConfig(vscode, undefined, 'search.exclude', {});
 
         const excludedPaths = Options.getExcludedPaths(vscode, true);
         expect(excludedPaths).to.be.empty;
@@ -65,8 +65,8 @@ suite("Options tests", () => {
 
     test('Verify return excluded paths when files.exclude and search.exclude populated', () => {
         const vscode = getVSCodeWithConfig();
-        updateConfig(vscode, null, 'files.exclude', { "/Library": true });
-        updateConfig(vscode, null, 'search.exclude', { "**/node_modules": true, "**/assets": false });
+        updateConfig(vscode, undefined, 'files.exclude', { "/Library": true });
+        updateConfig(vscode, undefined, 'search.exclude', { "**/node_modules": true, "**/assets": false });
 
         const excludedPaths = Options.getExcludedPaths(vscode, true);
         expect(excludedPaths).to.be.equalTo(["/Library", "**/node_modules"]);
diff --git a/test/unitTests/testAssets/Fakes.ts b/test/unitTests/testAssets/Fakes.ts
index d293b9be..3a8973c2 100644
--- a/test/unitTests/testAssets/Fakes.ts
+++ b/test/unitTests/testAssets/Fakes.ts
@@ -38,9 +38,7 @@ export const getWorkspaceConfiguration = (): vscode.WorkspaceConfiguration => {
     let configuration: vscode.WorkspaceConfiguration = {
         get<T>(section: string, defaultValue?: T): T | undefined {
             let result = <T>values[section];
-            return result === undefined && defaultValue !== undefined
-                ? defaultValue
-                : result;
+            return result ?? defaultValue;
         },
         has: (section: string) => {
             return values[section] !== undefined;
@@ -148,9 +146,9 @@ export function getFakeVsCode(): vscode.vscode {
         },
         version: "",
         env: {
-            appName: null,
-            appRoot: null,
-            language: null,
+            appName: "",
+            appRoot: "",
+            language: "",
             clipboard: {
                 writeText: () => {
                     throw new Error("Not Implemented");
@@ -159,8 +157,8 @@ export function getFakeVsCode(): vscode.vscode {
                     throw new Error("Not Implemented");
                 }
             },
-            machineId: null,
-            sessionId: null,
+            machineId: "",
+            sessionId: "",
             openExternal: () => {
                 throw new Error("Not Implemented");
             }
@@ -175,12 +173,10 @@ export function getMSBuildWorkspaceInformation(msBuildSolutionPath: string, msBu
     };
 }
 
-export function getWorkspaceInformationUpdated(msbuild: protocol.MsBuildWorkspaceInformation): WorkspaceInformationUpdated {
-    let a: protocol.WorkspaceInformationResponse = {
-        MsBuild: msbuild
-    };
-
-    return new WorkspaceInformationUpdated(a);
+export function getWorkspaceInformationUpdated(MsBuild: protocol.MsBuildWorkspaceInformation | undefined): WorkspaceInformationUpdated {
+    return new WorkspaceInformationUpdated({
+        MsBuild,
+    });
 }
 
 export function getVSCodeWithConfig() {
@@ -189,27 +185,26 @@ export function getVSCodeWithConfig() {
     const _vscodeConfig = getWorkspaceConfiguration();
     const _omnisharpConfig = getWorkspaceConfiguration();
     const _csharpConfig = getWorkspaceConfiguration();
+    const _razorConfig = getWorkspaceConfiguration();
 
-    vscode.workspace.getConfiguration = (section?, resource?) => {
-        if (!section) {
+    vscode.workspace.getConfiguration = (section, resource) => {
+        if (section === undefined) {
             return _vscodeConfig;
-        }
-
-        if (section === 'omnisharp') {
+        } else if (section === 'omnisharp') {
             return _omnisharpConfig;
-        }
-
-        if (section === 'csharp') {
+        } else if (section === 'csharp') {
             return _csharpConfig;
+        } else if (section === 'razor') {
+            return _razorConfig;
         }
 
-        return undefined;
+        throw new Error(`Unexpected section ${section}`);
     };
 
     return vscode;
 }
 
-export function updateConfig(vscode: vscode.vscode, section: string, config: string, value: any) {
-    let workspaceConfig = vscode.workspace.getConfiguration(section);
+export function updateConfig(vscode: vscode.vscode, section: string | undefined, config: string, value: any) {
+    const workspaceConfig = vscode.workspace.getConfiguration(section);
     workspaceConfig.update(config, value);
-}
\ No newline at end of file
+}