Skip to content

Commit

Permalink
[dotnet] Annotate Nullable Reference Types on `OpenQA.Selenium.Intern…
Browse files Browse the repository at this point in the history
…al` (#14840)
  • Loading branch information
RenderMichael authored Dec 1, 2024
1 parent b256c5f commit 51e7267
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 79 deletions.
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

0 comments on commit 51e7267

Please sign in to comment.