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

[dotnet] Annotate Nullable Reference Types on OpenQA.Selenium.Internal #14840

Merged
merged 1 commit into from
Dec 1, 2024
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
4 changes: 3 additions & 1 deletion dotnet/src/webdriver/ICapabilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

using System;

#nullable enable

namespace OpenQA.Selenium
{
/// <summary>
Expand Down Expand Up @@ -49,6 +51,6 @@ public interface ICapabilities
/// <param name="capability">The capability to get.</param>
/// <returns>An object associated with the capability, or <see langword="null"/>
/// if the capability is not set on the browser.</returns>
object GetCapability(string capability);
object? GetCapability(string capability);
}
}
26 changes: 7 additions & 19 deletions dotnet/src/webdriver/Internal/AndroidOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,55 +19,43 @@

using System;

#nullable enable

namespace OpenQA.Selenium.Internal
{
/// <summary>
/// Provides a base class for options for browsers to be automated on Android.
/// </summary>
public class AndroidOptions
{
private string androidPackage;
private string androidDeviceSerial;
private string androidActivity;

/// <summary>
/// Initializes a new instance of the <see cref="AndroidOptions"/> class.
/// </summary>
/// <param name="androidPackage"></param>
/// <exception cref="ArgumentException">If <paramref name="androidPackage"/> is <see langword="null"/> or <see cref="string.Empty"/>.</exception>
protected AndroidOptions(string androidPackage)
{
if (string.IsNullOrEmpty(androidPackage))
{
throw new ArgumentException("The Android package cannot be null or the empty string", nameof(androidPackage));
}

this.androidPackage = androidPackage;
this.AndroidPackage = androidPackage;
}

/// <summary>
/// The package name of the application to automate.
/// </summary>
public string AndroidPackage
{
get { return this.androidPackage; }
}
public string AndroidPackage { get; }

/// <summary>
/// The serial number of the device on which to launch the application.
/// </summary>
public string AndroidDeviceSerial
{
get { return this.androidDeviceSerial; }
set { this.androidDeviceSerial = value; }
}
public string? AndroidDeviceSerial { get; set; }

/// <summary>
/// Gets or sets the name of the Activity hosting the app.
/// </summary>
public string AndroidActivity
{
get { return this.androidActivity; }
set { this.androidActivity = value; }
}
public string? AndroidActivity { get; set; }
}
}
12 changes: 7 additions & 5 deletions dotnet/src/webdriver/Internal/FileUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
using System.IO;
using System.Reflection;

#nullable enable

namespace OpenQA.Selenium.Internal
{
/// <summary>
Expand All @@ -40,7 +42,7 @@ internal static class FileUtilities
/// <returns><see langword="true"/> if the copy is completed; otherwise <see langword="false"/>.</returns>
public static bool CopyDirectory(string sourceDirectory, string destinationDirectory)
{
bool copyComplete = false;
bool copyComplete;
DirectoryInfo sourceDirectoryInfo = new DirectoryInfo(sourceDirectory);
DirectoryInfo destinationDirectoryInfo = new DirectoryInfo(destinationDirectory);

Expand Down Expand Up @@ -132,7 +134,7 @@ public static string FindFile(string fileName)

// If it's not in the same directory as the executing assembly,
// try looking in the system path.
string systemPath = Environment.GetEnvironmentVariable("PATH");
string? systemPath = Environment.GetEnvironmentVariable("PATH");
if (!string.IsNullOrEmpty(systemPath))
{
string expandedPath = Environment.ExpandEnvironmentVariables(systemPath);
Expand Down Expand Up @@ -165,7 +167,7 @@ public static string FindFile(string fileName)
public static string GetCurrentDirectory()
{
Assembly executingAssembly = typeof(FileUtilities).Assembly;
string location = null;
string? location = null;

// Make sure not to call Path.GetDirectoryName if assembly location is null or empty
if (!string.IsNullOrEmpty(executingAssembly.Location))
Expand All @@ -184,13 +186,13 @@ public static string GetCurrentDirectory()
location = Directory.GetCurrentDirectory();
}

string currentDirectory = location;
string currentDirectory = location!;

// If we're shadow copying, get the directory from the codebase instead
if (AppDomain.CurrentDomain.ShadowCopyFiles)
{
Uri uri = new Uri(executingAssembly.CodeBase);
currentDirectory = Path.GetDirectoryName(uri.LocalPath);
currentDirectory = Path.GetDirectoryName(uri.LocalPath)!;
}

return currentDirectory;
Expand Down
2 changes: 2 additions & 0 deletions dotnet/src/webdriver/Internal/IFindsElement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

using System.Collections.ObjectModel;

#nullable enable

namespace OpenQA.Selenium.Internal
{
/// <summary>
Expand Down
2 changes: 2 additions & 0 deletions dotnet/src/webdriver/Internal/IHasCapabilitiesDictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

using System.Collections.Generic;

#nullable enable

namespace OpenQA.Selenium.Internal
{
/// <summary>
Expand Down
33 changes: 13 additions & 20 deletions dotnet/src/webdriver/Internal/ResourceUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,17 @@
using System.Reflection;
using System.Runtime.InteropServices;

#nullable enable

namespace OpenQA.Selenium.Internal
{
/// <summary>
/// Encapsulates methods for finding and extracting WebDriver resources.
/// </summary>
internal static class ResourceUtilities
{
private static string productVersion;
private static string platformFamily;
private static string? productVersion;
private static string? platformFamily;

/// <summary>
/// Gets a string representing the informational version of the Selenium product.
Expand Down Expand Up @@ -60,18 +62,7 @@ public static string ProductVersion
/// <summary>
/// Gets a string representing the platform family on which the Selenium assembly is executing.
/// </summary>
public static string PlatformFamily
{
get
{
if (string.IsNullOrEmpty(platformFamily))
{
platformFamily = GetPlatformString();
}

return platformFamily;
}
}
public static string PlatformFamily => platformFamily ??= GetPlatformString();

/// <summary>
/// Gets a <see cref="Stream"/> that contains the resource to use.
Expand All @@ -94,7 +85,7 @@ public static string PlatformFamily
/// </remarks>
public static Stream GetResourceStream(string fileName, string resourceId)
{
Stream resourceStream = null;
Stream? resourceStream;
string resourceFilePath = Path.Combine(FileUtilities.GetCurrentDirectory(), Path.GetFileName(fileName));
if (File.Exists(resourceFilePath))
{
Expand Down Expand Up @@ -125,20 +116,22 @@ public static Stream GetResourceStream(string fileName, string resourceId)

private static string GetPlatformString()
{
string platformName = "unknown";
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
platformName = "windows";
return "windows";
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
platformName = "linux";
return "linux";
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
platformName = "mac";
return "mac";
}
else
{
return "unknown";
}
return platformName;
}
}
}
14 changes: 8 additions & 6 deletions dotnet/src/webdriver/Internal/ResponseValueJsonConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,16 @@
using System.Text.Json;
using System.Text.Json.Serialization;

#nullable enable

namespace OpenQA.Selenium.Internal
{
/// <summary>
/// Converts the response to JSON
/// </summary>
internal class ResponseValueJsonConverter : JsonConverter<object>
{
public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
public override object? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return ProcessReadToken(ref reader, options);
}
Expand Down Expand Up @@ -67,19 +69,19 @@ public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOp
}
}

private static object ProcessReadToken(ref Utf8JsonReader reader, JsonSerializerOptions options)
private static object? ProcessReadToken(ref Utf8JsonReader reader, JsonSerializerOptions options)
{
// Recursively processes a token. This is required for elements that next other elements.
object processedObject;
object? processedObject;

switch (reader.TokenType)
{
case JsonTokenType.StartObject:
{
Dictionary<string, object> dictionaryValue = [];
Dictionary<string, object?> dictionaryValue = [];
while (reader.Read() && reader.TokenType != JsonTokenType.EndObject)
{
string elementKey = reader.GetString();
string elementKey = reader.GetString()!;
reader.Read();
dictionaryValue.Add(elementKey, ProcessReadToken(ref reader, options));
}
Expand All @@ -90,7 +92,7 @@ private static object ProcessReadToken(ref Utf8JsonReader reader, JsonSerializer

case JsonTokenType.StartArray:
{
List<object> arrayValue = [];
List<object?> arrayValue = [];
while (reader.Read() && reader.TokenType != JsonTokenType.EndArray)
{
arrayValue.Add(ProcessReadToken(ref reader, options));
Expand Down
45 changes: 17 additions & 28 deletions dotnet/src/webdriver/Internal/ReturnedCapabilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@
using System.Collections.ObjectModel;
using System.Globalization;

#nullable enable

namespace OpenQA.Selenium.Internal
{
/// <summary>
/// Class to Create the capabilities of the browser you require for <see cref="IWebDriver"/>.
/// If you wish to use default values use the static methods
/// </summary>
internal class ReturnedCapabilities : ICapabilities, IHasCapabilitiesDictionary
internal sealed class ReturnedCapabilities : ICapabilities, IHasCapabilitiesDictionary
{
private readonly Dictionary<string, object> capabilities = new Dictionary<string, object>();

Expand All @@ -43,32 +45,26 @@ public ReturnedCapabilities()
/// Initializes a new instance of the <see cref="ReturnedCapabilities"/> class
/// </summary>
/// <param name="rawMap">Dictionary of items for the remote driver</param>
public ReturnedCapabilities(Dictionary<string, object> rawMap)
public ReturnedCapabilities(Dictionary<string, object>? rawMap)
{
if (rawMap != null)
{
foreach (string key in rawMap.Keys)
foreach (KeyValuePair<string, object> rawItem in rawMap)
{
this.capabilities[key] = rawMap[key];
this.capabilities[rawItem.Key] = rawItem.Value;
}
}
}

/// <summary>
/// Gets the browser name
/// Gets the browser name, or <see cref="string.Empty"/> if not specified.
/// </summary>
public string BrowserName
{
get
{
string name = string.Empty;
object capabilityValue = this.GetCapability(CapabilityType.BrowserName);
if (capabilityValue != null)
{
name = capabilityValue.ToString();
}

return name;
object? capabilityValue = this.GetCapability(CapabilityType.BrowserName);
return capabilityValue?.ToString() ?? string.Empty;
}
}

Expand All @@ -84,30 +80,24 @@ public object this[string capabilityName]
{
get
{
if (!this.capabilities.ContainsKey(capabilityName))
if (!this.capabilities.TryGetValue(capabilityName, out object? capabilityValue))
{
throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "The capability {0} is not present in this set of capabilities", capabilityName));
}

return this.capabilities[capabilityName];
return capabilityValue;
}
}

/// <summary>
/// Gets the underlying Dictionary for a given set of capabilities.
/// </summary>
IDictionary<string, object> IHasCapabilitiesDictionary.CapabilitiesDictionary
{
get { return this.CapabilitiesDictionary; }
}
IDictionary<string, object> IHasCapabilitiesDictionary.CapabilitiesDictionary => this.CapabilitiesDictionary;

/// <summary>
/// Gets the internal capabilities dictionary.
/// </summary>
internal IDictionary<string, object> CapabilitiesDictionary
{
get { return new ReadOnlyDictionary<string, object>(this.capabilities); }
}
internal IDictionary<string, object> CapabilitiesDictionary => new ReadOnlyDictionary<string, object>(this.capabilities);

/// <summary>
/// Gets a value indicating whether the browser has a given capability.
Expand All @@ -125,15 +115,14 @@ public bool HasCapability(string capability)
/// <param name="capability">The capability to get.</param>
/// <returns>An object associated with the capability, or <see langword="null"/>
/// if the capability is not set on the browser.</returns>
public object GetCapability(string capability)
public object? GetCapability(string capability)
{
object capabilityValue = null;
if (this.capabilities.ContainsKey(capability))
if (this.capabilities.TryGetValue(capability, out object? capabilityValue))
{
capabilityValue = this.capabilities[capability];
return capabilityValue;
}

return capabilityValue;
return null;
}

/// <summary>
Expand Down