Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable nullables on CoreUtilities #3751

Merged
merged 2 commits into from
Jun 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions src/Microsoft.TestPlatform.CoreUtilities/Constants.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#nullable disable

namespace Microsoft.VisualStudio.TestPlatform.CoreUtilities;

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
using System;
using System.Text;

#nullable disable

namespace Microsoft.VisualStudio.TestPlatform.CoreUtilities.Extensions;

public static class StringBuilderExtensions
Expand All @@ -16,26 +14,28 @@ public static class StringBuilderExtensions
/// <param name="result">string builder</param>
/// <param name="data">data to be appended.</param>
/// <returns></returns>
public static void AppendSafeWithNewLine(this StringBuilder result, string data)
public static void AppendSafeWithNewLine(this StringBuilder result, string? data)
{
if (!string.IsNullOrEmpty(data))
if (data.IsNullOrEmpty())
{
// Don't append more data if already reached max length.
if (result.Length >= result.MaxCapacity)
{
return;
}
return;
}

// Add newline for readability.
data += Environment.NewLine;
// Don't append more data if already reached max length.
if (result.Length >= result.MaxCapacity)
{
return;
}

// Append sub string of data if appending all the data exceeds max capacity.
if (result.Length + data.Length >= result.MaxCapacity)
{
data = data.Substring(0, result.MaxCapacity - result.Length);
}
// Add newline for readability.
data += Environment.NewLine;

result.Append(data);
// Append sub string of data if appending all the data exceeds max capacity.
if (result.Length + data.Length >= result.MaxCapacity)
{
data = data.Substring(0, result.MaxCapacity - result.Length);
}

result.Append(data);
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#nullable disable

namespace Microsoft.VisualStudio.TestPlatform.CoreUtilities.Extensions;

public static class StringExtensions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ namespace Microsoft.VisualStudio.TestPlatform.Utilities;

/// <summary>
/// !!!NEVER USE A FLAG TO ENABLE FUNCTIONALITY!!!
///
///
/// The reasoning is:
///
///
/// * New version will automatically ship with the feature enabled. There is no action needed to be done just before release.
/// * Anyone interested in the new feature will get it automatically by grabbing our preview.
/// * Anyone who needs more time before using the new feature can disable it in the released package.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
using System;
using System.Collections.Generic;

#nullable disable

namespace Microsoft.VisualStudio.TestPlatform.CoreUtilities.Helpers;

/// <summary>
Expand All @@ -18,9 +16,9 @@ public class CommandLineArgumentsHelper
/// </summary>
/// <param name="args">Command line arguments. Ex: <c>{ "--port", "12312", "--parentprocessid", "2312", "--testsourcepath", "C:\temp\1.dll" }</c></param>
/// <returns>Dictionary of arguments keys and values.</returns>
public static IDictionary<string, string> GetArgumentsDictionary(string[] args)
public static IDictionary<string, string?> GetArgumentsDictionary(string[]? args)
{
var argsDictionary = new Dictionary<string, string>();
var argsDictionary = new Dictionary<string, string?>();
if (args == null)
{
return argsDictionary;
Expand Down Expand Up @@ -52,7 +50,7 @@ public static IDictionary<string, string> GetArgumentsDictionary(string[] args)
/// <param name="fullname">The full name for required argument. Ex: "--port"</param>
/// <returns>Value of the argument.</returns>
/// <exception cref="ArgumentException">Thrown if value of an argument is not an integer.</exception>
public static int GetIntArgFromDict(IDictionary<string, string> argsDictionary, string fullname)
public static int GetIntArgFromDict(IDictionary<string, string?> argsDictionary, string fullname)
{
var found = TryGetIntArgFromDict(argsDictionary, fullname, out var value);
return found ? value : 0;
Expand All @@ -65,7 +63,7 @@ public static int GetIntArgFromDict(IDictionary<string, string> argsDictionary,
/// <param name="fullname">The full name for required argument. Ex: "--port"</param>
/// <returns>Value of the argument.</returns>
/// <exception cref="ArgumentException">Thrown if value of an argument is not an integer.</exception>
public static bool TryGetIntArgFromDict(IDictionary<string, string> argsDictionary, string fullname, out int value)
public static bool TryGetIntArgFromDict(IDictionary<string, string?> argsDictionary, string fullname, out int value)
{
var found = argsDictionary.TryGetValue(fullname, out var optionValue);
if (!found)
Expand All @@ -86,7 +84,7 @@ public static bool TryGetIntArgFromDict(IDictionary<string, string> argsDictiona
/// <param name="fullname">The full name for required argument. Ex: "--port"</param>
/// <returns>Value of the argument.</returns>
/// <exception cref="ArgumentException">Thrown if value of an argument is not an integer.</exception>
public static string GetStringArgFromDict(IDictionary<string, string> argsDictionary, string fullname)
public static string? GetStringArgFromDict(IDictionary<string, string?> argsDictionary, string fullname)
{
return argsDictionary.TryGetValue(fullname, out var optionValue) ? optionValue : string.Empty;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#if !NETSTANDARD1_0

using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Reflection.PortableExecutable;

Expand All @@ -17,8 +18,6 @@
using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces;
using Microsoft.Win32;

#nullable disable

namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Helpers;

public class DotnetHostHelper : IDotnetHostHelper
Expand Down Expand Up @@ -120,12 +119,12 @@ private bool TryGetExecutablePath(string executableBaseName, out string executab
return false;
}

public bool TryGetDotnetPathByArchitecture(PlatformArchitecture targetArchitecture, out string muxerPath)
public bool TryGetDotnetPathByArchitecture(PlatformArchitecture targetArchitecture, [NotNullWhen(true)] out string? muxerPath)
{
// If current process is the same as the target architecture we return the current process filename.
if (_processHelper.GetCurrentProcessArchitecture() == targetArchitecture)
{
string currentProcessFileName = _processHelper.GetCurrentProcessFileName();
string currentProcessFileName = _processHelper.GetCurrentProcessFileName()!;
if (Path.GetFileName(currentProcessFileName) == _muxerName)
{
muxerPath = currentProcessFileName;
Expand Down Expand Up @@ -279,48 +278,40 @@ public bool TryGetDotnetPathByArchitecture(PlatformArchitecture targetArchitectu
return true;
}

private string GetMuxerFromGlobalRegistrationWin(PlatformArchitecture targetArchitecture)
private string? GetMuxerFromGlobalRegistrationWin(PlatformArchitecture targetArchitecture)
{
// Installed version are always in 32-bit view of registry
// https://github.com/dotnet/designs/blob/main/accepted/2020/install-locations.md#globally-registered-install-location-new
// "Note that this registry key is "redirected" that means that 32-bit processes see different copy of the key than 64bit processes.
// So it's important that both installers and the host access only the 32-bit view of the registry."
using (IRegistryKey hklm = _windowsRegistryHelper.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32))
using IRegistryKey? hklm = _windowsRegistryHelper.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32);
if (hklm == null)
{
if (hklm != null)
{
using IRegistryKey dotnetInstalledVersion = hklm.OpenSubKey(@"SOFTWARE\dotnet\Setup\InstalledVersions");
if (dotnetInstalledVersion != null)
{
using IRegistryKey nativeArch = dotnetInstalledVersion.OpenSubKey(targetArchitecture.ToString().ToLowerInvariant());
string installLocation = nativeArch?.GetValue("InstallLocation")?.ToString();

if (installLocation != null)
{
string path = Path.Combine(installLocation.Trim(), _muxerName);
EqtTrace.Verbose($@"DotnetHostHelper.GetMuxerFromGlobalRegistrationWin: Muxer resolved using win registry key 'SOFTWARE\dotnet\Setup\InstalledVersions\{targetArchitecture.ToString().ToLowerInvariant()}\InstallLocation' in '{path}'");
return path;
}
else
{
EqtTrace.Verbose($@"DotnetHostHelper.GetMuxerFromGlobalRegistrationWin: Missing registry InstallLocation");
}
}
else
{
EqtTrace.Verbose($@"DotnetHostHelper.GetMuxerFromGlobalRegistrationWin: Missing RegistryHive.LocalMachine for RegistryView.Registry32");
}
}
else
{
EqtTrace.Verbose($@"DotnetHostHelper.GetMuxerFromGlobalRegistrationWin: Missing SOFTWARE\dotnet\Setup\InstalledVersions subkey");
}
EqtTrace.Verbose($@"DotnetHostHelper.GetMuxerFromGlobalRegistrationWin: Missing SOFTWARE\dotnet\Setup\InstalledVersions subkey");
return null;
}

return null;
using IRegistryKey? dotnetInstalledVersion = hklm.OpenSubKey(@"SOFTWARE\dotnet\Setup\InstalledVersions");
if (dotnetInstalledVersion == null)
{
EqtTrace.Verbose($@"DotnetHostHelper.GetMuxerFromGlobalRegistrationWin: Missing RegistryHive.LocalMachine for RegistryView.Registry32");
return null;
}

using IRegistryKey? nativeArch = dotnetInstalledVersion.OpenSubKey(targetArchitecture.ToString().ToLowerInvariant());
string? installLocation = nativeArch?.GetValue("InstallLocation")?.ToString();
if (installLocation == null)
{
EqtTrace.Verbose($@"DotnetHostHelper.GetMuxerFromGlobalRegistrationWin: Missing registry InstallLocation");
return null;
}

string path = Path.Combine(installLocation.Trim(), _muxerName);
EqtTrace.Verbose($@"DotnetHostHelper.GetMuxerFromGlobalRegistrationWin: Muxer resolved using win registry key 'SOFTWARE\dotnet\Setup\InstalledVersions\{targetArchitecture.ToString().ToLowerInvariant()}\InstallLocation' in '{path}'");
return path;
}

private string GetMuxerFromGlobalRegistrationOnUnix(PlatformArchitecture targetArchitecture)
private string? GetMuxerFromGlobalRegistrationOnUnix(PlatformArchitecture targetArchitecture)
{
string baseInstallLocation = "/etc/dotnet/";

Expand All @@ -333,22 +324,24 @@ private string GetMuxerFromGlobalRegistrationOnUnix(PlatformArchitecture targetA
installLocation = $"{baseInstallLocation}install_location";
}

if (_fileHelper.Exists(installLocation))
if (!_fileHelper.Exists(installLocation))
{
try
{
using Stream stream = _fileHelper.GetStream(installLocation, FileMode.Open, FileAccess.Read);
using StreamReader streamReader = new(stream);
string content = streamReader.ReadToEnd().Trim();
EqtTrace.Verbose($"DotnetHostHelper: '{installLocation}' content '{content}'");
string path = Path.Combine(content, _muxerName);
EqtTrace.Verbose($"DotnetHostHelper: Muxer resolved using '{installLocation}' in '{path}'");
return path;
}
catch (Exception ex)
{
EqtTrace.Error($"DotnetHostHelper.GetMuxerFromGlobalRegistrationOnUnix: Exception during '{installLocation}' muxer resolution.\n{ex}");
}
return null;
}

try
{
using Stream stream = _fileHelper.GetStream(installLocation, FileMode.Open, FileAccess.Read);
using StreamReader streamReader = new(stream);
string content = streamReader.ReadToEnd().Trim();
EqtTrace.Verbose($"DotnetHostHelper: '{installLocation}' content '{content}'");
string path = Path.Combine(content, _muxerName);
EqtTrace.Verbose($"DotnetHostHelper: Muxer resolved using '{installLocation}' in '{path}'");
return path;
}
catch (Exception ex)
{
EqtTrace.Error($"DotnetHostHelper.GetMuxerFromGlobalRegistrationOnUnix: Exception during '{installLocation}' muxer resolution.\n{ex}");
}

return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@

using Microsoft.VisualStudio.TestPlatform.ObjectModel;

#nullable disable

namespace Microsoft.VisualStudio.TestPlatform.CoreUtilities.Helpers;

public class EnvironmentHelper
Expand All @@ -28,7 +26,7 @@ public static int GetConnectionTimeout()
var envVarValue = Environment.GetEnvironmentVariable(VstestConnectionTimeout);
#endif

if (!string.IsNullOrEmpty(envVarValue) && int.TryParse(envVarValue, out int value) && value >= 0)
if (!envVarValue.IsNullOrEmpty() && int.TryParse(envVarValue, out int value) && value >= 0)
{
EqtTrace.Info("EnvironmentHelper.GetConnectionTimeout: {0} value set to {1}.", VstestConnectionTimeout, value);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@

using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces;

#nullable disable

namespace Microsoft.VisualStudio.TestPlatform.CoreUtilities.Helpers;

internal class EnvironmentVariableHelper : IEnvironmentVariableHelper
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@

using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces;

#nullable disable

namespace Microsoft.VisualStudio.TestPlatform.Utilities.Helpers;

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,20 @@

using Microsoft.Win32;

#nullable disable

namespace Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces;

internal interface IWindowsRegistryHelper
{
IRegistryKey OpenBaseKey(RegistryHive hKey, RegistryView view);
IRegistryKey? OpenBaseKey(RegistryHive hKey, RegistryView view);
}

internal interface IRegistryKey : IDisposable
{
IRegistryKey OpenSubKey(string name);
IRegistryKey? OpenSubKey(string name);

object GetValue(string name);
object? GetValue(string name);

string[] GetSubKeyNames();
string[]? GetSubKeyNames();
}

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@

using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces;

#nullable disable

namespace Microsoft.VisualStudio.TestPlatform.Utilities.Helpers;

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,11 @@

using Microsoft.Win32;

#nullable disable

namespace Microsoft.VisualStudio.TestPlatform.Utilities.Helpers;

internal class WindowsRegistryHelper : IWindowsRegistryHelper
{
public IRegistryKey OpenBaseKey(RegistryHive hKey, RegistryView view)
public IRegistryKey? OpenBaseKey(RegistryHive hKey, RegistryView view)
{
var keyRegistry = RegistryKey.OpenBaseKey(hKey, view);
return keyRegistry is null ? null : new RegistryKeyWrapper(keyRegistry);
Expand All @@ -29,18 +27,18 @@ public RegistryKeyWrapper(RegistryKey registryKey)
_registryKey = registryKey;
}

public object GetValue(string name)
public object? GetValue(string name)
{
return _registryKey?.GetValue(name)?.ToString();
}

public IRegistryKey OpenSubKey(string name)
public IRegistryKey? OpenSubKey(string name)
{
var keyRegistry = _registryKey.OpenSubKey(name);
return keyRegistry is null ? null : new RegistryKeyWrapper(keyRegistry);
}

public string[] GetSubKeyNames()
public string[]? GetSubKeyNames()
=> _registryKey?.GetSubKeyNames();

public void Dispose()
Expand Down
Loading