Skip to content

Commit 8805fc0

Browse files
RenderMichaelsandeepsuryaprasad
authored andcommitted
[dotnet] Finalize nullability in internal devtools generator (SeleniumHQ#15088)
* [dotnet] Move devtools generator into a specific project * rename generator name in generate_devtools * Revert "rename generator name in generate_devtools" This reverts commit efc80ed. * Revert "[dotnet] Move devtools generator into a specific project" This reverts commit c1c4441. * Modernize and prepare devtools generator for source generation * Enable nullability in devtools generator in bazel build.
1 parent c653d35 commit 8805fc0

22 files changed

+133
-171
lines changed

third_party/dotnet/devtools/src/generator/BUILD.bazel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ load("//dotnet:defs.bzl", "csharp_binary", "framework")
33
csharp_binary(
44
name = "generator",
55
srcs = glob(["**/*.cs"]),
6-
nullable = "annotations",
6+
nullable = "enable",
77
# Used as a tool in our build, so just target one framework
88
target_frameworks = ["net8.0"],
99
visibility = [

third_party/dotnet/devtools/src/generator/CodeGen/CodeGenerationSettings.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public sealed class CodeGenerationSettings
3636
/// Gets the version number of the runtime.
3737
/// </summary>
3838
[JsonPropertyName("runtimeVersion")]
39-
public string RuntimeVersion { get; set; }
39+
public string? RuntimeVersion { get; set; }
4040

4141
[JsonPropertyName("definitionTemplates")]
4242
public CodeGenerationDefinitionTemplateSettings DefinitionTemplates { get; set; } = new CodeGenerationDefinitionTemplateSettings();

third_party/dotnet/devtools/src/generator/CodeGen/CodeGenerationTemplateSettings.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ namespace OpenQA.Selenium.DevToolsGenerator.CodeGen
88
public class CodeGenerationTemplateSettings
99
{
1010
[JsonPropertyName("templatePath")]
11-
public string TemplatePath { get; set; }
11+
[JsonRequired]
12+
public string TemplatePath { get; set; } = null!;
1213

1314
[JsonPropertyName("outputPath")]
14-
public string OutputPath { get; set; }
15+
[JsonRequired]
16+
public string OutputPath { get; set; } = null!;
1517
}
1618
}

third_party/dotnet/devtools/src/generator/CodeGen/CodeGeneratorBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace OpenQA.Selenium.DevToolsGenerator.CodeGen
1010
/// </summary>
1111
/// <typeparam name="T"></typeparam>
1212
public abstract class CodeGeneratorBase<T> : ICodeGenerator<T>
13-
where T : IDefinition
13+
where T : class, IDefinition
1414
{
1515
private readonly Lazy<CodeGenerationSettings> m_settings;
1616
private readonly Lazy<TemplatesManager> m_templatesManager;

third_party/dotnet/devtools/src/generator/CodeGen/CodeGeneratorContext.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ namespace OpenQA.Selenium.DevToolsGenerator.CodeGen
66
/// <summary>
77
/// Represents the current context of the code generator.
88
/// </summary>
9-
public sealed class CodeGeneratorContext
9+
public sealed class CodeGeneratorContext(DomainDefinition domain, Dictionary<string, TypeInfo> knownTypes)
1010
{
11-
public DomainDefinition Domain { get; set; }
11+
public DomainDefinition Domain { get; } = domain;
1212

13-
public Dictionary<string, TypeInfo> KnownTypes { get; set; }
13+
public Dictionary<string, TypeInfo> KnownTypes { get; } = knownTypes;
1414
}
1515
}

third_party/dotnet/devtools/src/generator/CodeGen/CommandInfo.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ namespace OpenQA.Selenium.DevToolsGenerator.CodeGen
33
/// <summary>
44
/// Represents information about a Chrome Debugger Protocol command.
55
/// </summary>
6-
public sealed class CommandInfo
6+
public sealed class CommandInfo(string commandName, string fullTypeName, string fullResponseTypeName)
77
{
8-
public string CommandName { get; set; }
8+
public string CommandName { get; } = commandName;
99

10-
public string FullTypeName { get; set; }
10+
public string FullTypeName { get; } = fullTypeName;
1111

12-
public string FullResponseTypeName { get; set; }
12+
public string FullResponseTypeName { get; } = fullResponseTypeName;
1313
}
1414
}

third_party/dotnet/devtools/src/generator/CodeGen/EventInfo.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ namespace OpenQA.Selenium.DevToolsGenerator.CodeGen
33
/// <summary>
44
/// Represents information about a Chrome Debugger Protocol event.
55
/// </summary>
6-
public sealed class EventInfo
6+
public sealed class EventInfo(string eventName, string fullTypeName)
77
{
8-
public string EventName { get; set; }
8+
public string EventName { get; } = eventName;
99

10-
public string FullTypeName { get; set; }
10+
public string FullTypeName { get; } = fullTypeName;
1111
}
1212
}

third_party/dotnet/devtools/src/generator/CodeGen/ICodeGenerator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace OpenQA.Selenium.DevToolsGenerator.CodeGen
88
/// </summary>
99
/// <typeparam name="T"></typeparam>
1010
public interface ICodeGenerator<T>
11-
where T : IDefinition
11+
where T : class, IDefinition
1212
{
1313
/// <summary>
1414
/// Generates one or more code files for the specified IDefinition item

third_party/dotnet/devtools/src/generator/CodeGen/ProtocolGenerator.cs

Lines changed: 35 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using OpenQA.Selenium.DevToolsGenerator.ProtocolDefinition;
44
using System;
55
using System.Collections.Generic;
6+
using System.Data;
67
using System.IO;
78
using System.Linq;
89

@@ -22,7 +23,7 @@ public override IDictionary<string, string> GenerateCode(ProtocolDefinition.Prot
2223
{
2324
if (string.IsNullOrWhiteSpace(Settings.TemplatesPath))
2425
{
25-
Settings.TemplatesPath = Path.GetDirectoryName(Settings.TemplatesPath);
26+
Settings.TemplatesPath = Path.GetDirectoryName(Settings.TemplatesPath)!;
2627
}
2728

2829
ICollection<DomainDefinition> domains = protocolDefinition.Domains;
@@ -44,11 +45,11 @@ public override IDictionary<string, string> GenerateCode(ProtocolDefinition.Prot
4445
foreach (var command in domain.Commands)
4546
{
4647
commands.Add(new CommandInfo
47-
{
48-
CommandName = $"{domain.Name}.{command.Name}",
49-
FullTypeName = $"{domain.Name.Dehumanize()}.{command.Name.Dehumanize()}CommandSettings",
50-
FullResponseTypeName = $"{domain.Name.Dehumanize()}.{command.Name.Dehumanize()}CommandResponse"
51-
});
48+
(
49+
commandName: $"{domain.Name}.{command.Name}",
50+
fullTypeName: $"{domain.Name.Dehumanize()}.{command.Name.Dehumanize()}CommandSettings",
51+
fullResponseTypeName: $"{domain.Name.Dehumanize()}.{command.Name.Dehumanize()}CommandResponse"
52+
));
5253
}
5354
}
5455

@@ -60,10 +61,10 @@ public override IDictionary<string, string> GenerateCode(ProtocolDefinition.Prot
6061
foreach (var @event in domain.Events)
6162
{
6263
events.Add(new EventInfo
63-
{
64-
EventName = $"{domain.Name}.{@event.Name}",
65-
FullTypeName = $"{domain.Name.Dehumanize()}.{@event.Name.Dehumanize()}EventArgs"
66-
});
64+
(
65+
eventName: $"{domain.Name}.{@event.Name}",
66+
fullTypeName: $"{domain.Name.Dehumanize()}.{@event.Name.Dehumanize()}EventArgs")
67+
);
6768
}
6869
}
6970

@@ -102,7 +103,7 @@ public override IDictionary<string, string> GenerateCode(ProtocolDefinition.Prot
102103
return result;
103104
}
104105

105-
private Dictionary<string, TypeInfo> GetTypesInDomain(ICollection<DomainDefinition> domains)
106+
private static Dictionary<string, TypeInfo> GetTypesInDomain(ICollection<DomainDefinition> domains)
106107
{
107108
var knownTypes = new Dictionary<string, TypeInfo>(StringComparer.OrdinalIgnoreCase);
108109

@@ -116,9 +117,9 @@ private Dictionary<string, TypeInfo> GetTypesInDomain(ICollection<DomainDefiniti
116117
{
117118
if (propertyType.Type == "string" && type.Enum != null && propertyType.Enum.Count > 0)
118119
{
119-
TypeDefinition propertyTypeDefinition = new TypeDefinition()
120+
string id = $"{type.Id.Dehumanize()}{propertyType.Name.Dehumanize()}Values";
121+
TypeDefinition propertyTypeDefinition = new TypeDefinition(id)
120122
{
121-
Id = type.Id.Dehumanize() + propertyType.Name.Dehumanize() + "Values",
122123
Type = propertyType.Type,
123124
Description = $"Enumerated values for {domain.Name}.{type.Id}.{propertyType.Name}"
124125
};
@@ -136,35 +137,33 @@ private Dictionary<string, TypeInfo> GetTypesInDomain(ICollection<DomainDefiniti
136137
switch (type.Type)
137138
{
138139
case "object":
139-
typeInfo = new TypeInfo
140-
{
141-
IsPrimitive = false,
142-
TypeName = type.Id.Dehumanize(),
143-
};
140+
typeInfo = new TypeInfo(typeName: type.Id.Dehumanize(), isPrimitive: false);
144141
break;
142+
145143
case "string":
146144
if (type.Enum != null && type.Enum.Count > 0)
147145
{
148-
typeInfo = new TypeInfo
146+
typeInfo = new TypeInfo(typeName: type.Id.Dehumanize(), isPrimitive: false)
149147
{
150148
ByRef = true,
151-
IsPrimitive = false,
152-
TypeName = type.Id.Dehumanize(),
153149
};
154150
}
155151
else
156152
{
157-
typeInfo = new TypeInfo
158-
{
159-
IsPrimitive = true,
160-
TypeName = "string"
161-
};
153+
typeInfo = new TypeInfo("string", isPrimitive: true);
162154
}
163155

164156
break;
157+
165158
case "array":
166-
if ((type.Items == null || string.IsNullOrWhiteSpace(type.Items.Type)) &&
167-
type.Items.TypeReference != "StringIndex" && type.Items.TypeReference != "FilterEntry")
159+
if (type.Items is null)
160+
{
161+
throw new InvalidOperationException("Type definition's Type was array but Items is missing");
162+
}
163+
164+
if (string.IsNullOrWhiteSpace(type.Items.Type) &&
165+
type.Items.TypeReference != "StringIndex" &&
166+
type.Items.TypeReference != "FilterEntry")
168167
{
169168
throw new NotImplementedException("Did not expect a top-level domain array type to specify a TypeReference");
170169
}
@@ -199,28 +198,23 @@ private Dictionary<string, TypeInfo> GetTypesInDomain(ICollection<DomainDefiniti
199198
default:
200199
throw new NotImplementedException($"Did not expect a top-level domain array type to specify items of type {type.Items.Type}");
201200
}
202-
typeInfo = new TypeInfo
203-
{
204-
IsPrimitive = true,
205-
TypeName = $"{itemType}[]"
206-
};
201+
typeInfo = new TypeInfo(typeName: $"{itemType}[]", isPrimitive: true);
207202
break;
203+
208204
case "number":
209-
typeInfo = new TypeInfo
205+
typeInfo = new TypeInfo("double", isPrimitive: true)
210206
{
211207
ByRef = true,
212-
IsPrimitive = true,
213-
TypeName = "double"
214208
};
215209
break;
210+
216211
case "integer":
217-
typeInfo = new TypeInfo
212+
typeInfo = new TypeInfo("long", isPrimitive: true)
218213
{
219214
ByRef = true,
220-
IsPrimitive = true,
221-
TypeName = "long"
222215
};
223216
break;
217+
224218
default:
225219
throw new InvalidOperationException($"Unknown Type Definition Type: {type.Id}");
226220
}
@@ -232,11 +226,9 @@ private Dictionary<string, TypeInfo> GetTypesInDomain(ICollection<DomainDefiniti
232226

233227
foreach (var embeddedEnumType in embeddedTypes)
234228
{
235-
TypeInfo propertyTypeInfo = new TypeInfo
229+
TypeInfo propertyTypeInfo = new TypeInfo(typeName: embeddedEnumType.Id, isPrimitive: false)
236230
{
237-
TypeName = embeddedEnumType.Id,
238231
ByRef = true,
239-
IsPrimitive = false,
240232
Namespace = domain.Name.Dehumanize(),
241233
SourcePath = $"{domain.Name}.{embeddedEnumType.Id}"
242234
};
@@ -257,7 +249,7 @@ private Dictionary<string, string> GenerateCode(ICollection<DomainDefinition> do
257249
//Generate types/events/commands for all domains.
258250
foreach (var domain in domains)
259251
{
260-
var context = new CodeGeneratorContext { Domain = domain, KnownTypes = knownTypes };
252+
var context = new CodeGeneratorContext(domain, knownTypes);
261253
foreach (KeyValuePair<string, string> x in domainGenerator.GenerateCode(domain, context))
262254
{
263255
result.Add(x.Key, x.Value);

third_party/dotnet/devtools/src/generator/CodeGen/TemplatesManager.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ public TemplatesManager(CodeGenerationSettings settings)
3434
public Func<object, string> GetGeneratorForTemplate(CodeGenerationTemplateSettings templateSettings)
3535
{
3636
var templatePath = templateSettings.TemplatePath;
37-
if (m_templateGenerators.ContainsKey(templatePath))
37+
if (m_templateGenerators.TryGetValue(templatePath, out Func<object, string>? value))
3838
{
39-
return m_templateGenerators[templatePath];
39+
return value;
4040
}
4141

4242
var targetTemplate = templatePath;
@@ -47,7 +47,7 @@ public Func<object, string> GetGeneratorForTemplate(CodeGenerationTemplateSettin
4747

4848
if (!File.Exists(targetTemplate))
4949
{
50-
throw new FileNotFoundException($"Unable to locate a template at {targetTemplate} - please ensure that a template file exists at this location.");
50+
throw new FileNotFoundException($"Unable to locate a template at {targetTemplate} - please ensure that a template file exists at this location.", targetTemplate);
5151
}
5252

5353
var templateContents = File.ReadAllText(targetTemplate);
@@ -59,7 +59,7 @@ public Func<object, string> GetGeneratorForTemplate(CodeGenerationTemplateSettin
5959
throw new HandlebarsException("{{humanize}} helper must have exactly one argument");
6060
}
6161

62-
var str = arguments[0].ToString();
62+
var str = arguments[0].ToString()!;
6363

6464
//Some overrides for values that start with '-' -- this fixes two instances in Runtime.UnserializableValue
6565
if (str.StartsWith("-"))

0 commit comments

Comments
 (0)