diff --git a/build/Project.csproj.props b/build/Project.csproj.props
index 1d004b4..c1df222 100644
--- a/build/Project.csproj.props
+++ b/build/Project.csproj.props
@@ -1,5 +1,2 @@
-
- annotations
-
\ No newline at end of file
diff --git a/src/Firmware.cs b/src/Firmware.cs
index d3e78b0..6992162 100644
--- a/src/Firmware.cs
+++ b/src/Firmware.cs
@@ -169,7 +169,7 @@ public class PortPinInfo
/// Specifies the microcontroller port where the pin is located.
///
[YamlMember(Order = -1)]
- public string Port;
+ public string Port = "";
///
/// Specifies the unique pin number in the defined port.
@@ -357,12 +357,9 @@ class PortPinInfoTypeConverter(IDeserializer deserializer) : IYamlTypeConverter
public IDeserializer Deserializer { get; } = deserializer ?? throw new ArgumentNullException(nameof(deserializer));
- public bool Accepts(Type type)
- {
- return type == typeof(PortPinInfo);
- }
+ public bool Accepts(Type type) => type == typeof(PortPinInfo);
- public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer)
+ public object? ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer)
{
var portPin = Deserializer.Deserialize>(parser);
if (portPin.TryGetValue(DirectionProperty, out object value))
@@ -381,7 +378,7 @@ public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeseria
throw new YamlException($"Required property '{DirectionProperty}' not found when deserializing type '{typeof(PortPinInfo)}'.");
}
- public void WriteYaml(IEmitter emitter, object value, Type type, ObjectSerializer serializer)
+ public void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
{
throw new NotImplementedException();
}
@@ -397,6 +394,9 @@ class LowerCaseEnumTypeConverter : IYamlTypeConverter
public void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
{
+ if (value is null)
+ return;
+
var scalarStyle = ScalarStyle.Any;
var scalarValue = LowerCaseNamingConvention.Instance.Apply(value.ToString());
if (scalarValue == "off")
@@ -415,6 +415,9 @@ class CamelCaseEnumTypeConverter : IYamlTypeConverter
public void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
{
+ if (value is null)
+ return;
+
emitter.Emit(new Scalar(CamelCaseNamingConvention.Instance.Apply(value.ToString())));
}
}
diff --git a/src/Interface.cs b/src/Interface.cs
index b000b0c..c35e682 100644
--- a/src/Interface.cs
+++ b/src/Interface.cs
@@ -18,7 +18,7 @@ public class DeviceInfo
///
/// Specifies the name of the device.
///
- public string Device;
+ public string Device = "";
///
/// Specifies the unique identifier for this device type.
@@ -28,12 +28,12 @@ public class DeviceInfo
///
/// Specifies the version of the device firmware.
///
- public HarpVersion FirmwareVersion;
+ public HarpVersion? FirmwareVersion;
///
/// Specifies the version of the device hardware.
///
- public HarpVersion HardwareTargets;
+ public HarpVersion? HardwareTargets;
///
/// Specifies the collection of registers implementing the device function.
@@ -151,7 +151,7 @@ public class RegisterInfo
///
/// Specifies the name of the bit mask or group mask used to represent the payload value.
///
- public string MaskType;
+ public string MaskType = "";
///
/// Specifies the minimum allowable value for the payload.
@@ -171,7 +171,7 @@ public class RegisterInfo
///
/// Specifies the name of the type used to represent the payload value in the high-level interface.
///
- public string InterfaceType;
+ public string InterfaceType = "";
///
/// Specifies a custom converter which will be used to parse or format the payload value.
@@ -187,7 +187,7 @@ public class RegisterInfo
/// Specifies a collection of payload members describing the contents
/// of the raw payload value.
///
- public Dictionary PayloadSpec;
+ public Dictionary? PayloadSpec;
///
/// Gets a value indicating whether a custom converter will be used to parse or
@@ -229,7 +229,7 @@ public class PayloadMemberInfo
///
/// Specifies the name of the bit mask or group mask used to represent this payload member.
///
- public string MaskType;
+ public string MaskType = "";
///
/// Specifies the minimum allowable value for this payload member.
@@ -249,7 +249,7 @@ public class PayloadMemberInfo
///
/// Specifies the name of the type used to represent this payload member in the high-level interface.
///
- public string InterfaceType;
+ public string InterfaceType = "";
///
/// Specifies a custom converter which will be used to parse or format this payload member.
@@ -350,7 +350,7 @@ public class MaskValue
///
/// Specifies a summary description of the mask value function.
///
- public string Description;
+ public string Description = "";
}
internal static partial class TemplateHelper
@@ -478,7 +478,9 @@ public static string GetParseConversion(RegisterInfo register, string expression
else if (register.InterfaceType == "string")
return $"PayloadMarshal.ReadUtf8String({expression})";
else
- return GetConversionToInterfaceType(register.InterfaceType ?? register.MaskType, expression);
+ return GetConversionToInterfaceType(
+ string.IsNullOrEmpty(register.InterfaceType) ? register.MaskType : register.InterfaceType,
+ expression);
}
public static string GetFormatConversion(RegisterInfo register, string expression)
@@ -486,7 +488,10 @@ public static string GetFormatConversion(RegisterInfo register, string expressio
if (register.PayloadSpec != null || register.InterfaceType == "string" || register.HasConverter)
return $"FormatPayload({expression})";
else
- return GetConversionFromInterfaceType(register.InterfaceType ?? register.MaskType, register.PayloadInterfaceType, expression);
+ return GetConversionFromInterfaceType(
+ string.IsNullOrEmpty(register.InterfaceType) ? register.MaskType : register.InterfaceType,
+ register.PayloadInterfaceType,
+ expression);
}
public static string GetConversionToInterfaceType(string interfaceType, string expression)
@@ -608,7 +613,9 @@ public static string GetPayloadMemberParser(
{
return $"ParsePayload{name}({expression})";
}
- return GetConversionToInterfaceType(member.InterfaceType ?? member.MaskType, expression);
+ return GetConversionToInterfaceType(
+ string.IsNullOrEmpty(member.InterfaceType) ? member.MaskType : member.InterfaceType,
+ expression);
}
public static string GetPayloadMemberAssignmentFormatter(
@@ -661,7 +668,8 @@ public static string GetPayloadMemberValueFormatter(
var isBoolean = member.InterfaceType == "bool" && !member.HasConverter;
var payloadInterfaceType = GetInterfaceType(payloadType);
- if (!string.IsNullOrEmpty(member.InterfaceType ?? member.MaskType))
+ var memberInterfaceType = string.IsNullOrEmpty(member.InterfaceType) ? member.MaskType : member.InterfaceType;
+ if (!string.IsNullOrEmpty(memberInterfaceType))
{
if (isBoolean)
{
@@ -697,10 +705,7 @@ class HarpVersionTypeConverter : IYamlTypeConverter
{
public static readonly HarpVersionTypeConverter Instance = new();
- public bool Accepts(Type type)
- {
- return type == typeof(HarpVersion);
- }
+ public bool Accepts(Type type) => type == typeof(HarpVersion);
public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer)
{
@@ -708,12 +713,15 @@ public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeseria
return HarpVersion.Parse(scalar.Value);
}
- public void WriteYaml(IEmitter emitter, object value, Type type, ObjectSerializer serializer)
+ public void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
{
+ if (value is not HarpVersion version)
+ return;
+
var scalar = new Scalar(
AnchorName.Empty,
TagName.Empty,
- ((HarpVersion)value).ToString(),
+ version.ToString(),
ScalarStyle.DoubleQuoted,
isPlainImplicit: false,
isQuotedImplicit: true);
@@ -727,12 +735,12 @@ class HexValueTypeConverter : IYamlTypeConverter
public bool Accepts(Type type) => false;
- public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer)
+ public object? ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer)
{
return rootDeserializer(type);
}
- public void WriteYaml(IEmitter emitter, object value, Type type, ObjectSerializer serializer)
+ public void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
{
emitter.Emit(new Scalar(string.Format($"0x{value:X}")));
}
@@ -750,17 +758,14 @@ class MaskValueTypeConverter : IYamlTypeConverter
.WithTypeConverter(HexValueTypeConverter.Instance)
.BuildValueSerializer();
- public bool Accepts(Type type)
- {
- return type == typeof(MaskValue);
- }
+ public bool Accepts(Type type) => type == typeof(MaskValue);
- public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer)
+ public object? ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer)
{
- if (parser.TryConsume(out MappingStart _))
+ if (parser.TryConsume(out var _))
{
var maskValue = new MaskValue();
- while (!parser.TryConsume(out MappingEnd _))
+ while (!parser.TryConsume(out var _))
{
var key = parser.Consume();
var value = parser.Consume();
@@ -786,9 +791,11 @@ public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeseria
}
}
- public void WriteYaml(IEmitter emitter, object value, Type type, ObjectSerializer serializer)
+ public void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
{
- var maskValue = (MaskValue)value;
+ if (value is not MaskValue maskValue)
+ return;
+
if (string.IsNullOrEmpty(maskValue.Description))
HexValueTypeConverter.Instance.WriteYaml(emitter, maskValue.Value, typeof(int), serializer);
else
@@ -800,17 +807,14 @@ class RegisterAccessTypeConverter : IYamlTypeConverter
{
public static readonly RegisterAccessTypeConverter Instance = new();
- public bool Accepts(Type type)
- {
- return type == typeof(RegisterAccess);
- }
+ public bool Accepts(Type type) => type == typeof(RegisterAccess);
- public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer)
+ public object? ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer)
{
- if (parser.TryConsume(out SequenceStart _))
+ if (parser.TryConsume(out var _))
{
RegisterAccess value = 0;
- while (parser.TryConsume(out Scalar scalar))
+ while (parser.TryConsume(out var scalar))
{
value |= (RegisterAccess)Enum.Parse(typeof(RegisterAccess), scalar.Value);
}
@@ -824,9 +828,11 @@ public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeseria
}
}
- public void WriteYaml(IEmitter emitter, object value, Type type, ObjectSerializer serializer)
+ public void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
{
- var access = (RegisterAccess)value;
+ if (value is not RegisterAccess access)
+ return;
+
switch (access)
{
case RegisterAccess.Read:
diff --git a/src/TemplateBase.cs b/src/TemplateBase.cs
index 61f4fdd..aae5471 100644
--- a/src/TemplateBase.cs
+++ b/src/TemplateBase.cs
@@ -7,12 +7,12 @@ namespace Harp.Generators;
internal abstract class TemplateBase
{
- private StringBuilder builder;
- private CompilerErrorCollection errors;
+ private StringBuilder? builder;
+ private CompilerErrorCollection? errors;
private string currentIndent = string.Empty;
- private Stack indents;
+ private Stack? indents;
- public virtual IDictionary Session { get; set; }
+ public virtual IDictionary? Session { get; set; }
public string FileName { get; set; } = string.Empty;
diff --git a/tests/FirmwareGeneratorTests.cs b/tests/FirmwareGeneratorTests.cs
index 7de67c3..a7d364c 100644
--- a/tests/FirmwareGeneratorTests.cs
+++ b/tests/FirmwareGeneratorTests.cs
@@ -5,7 +5,7 @@ namespace Harp.Generators.Tests;
[TestClass]
public sealed class FirmwareGeneratorTests
{
- DirectoryInfo outputDirectory;
+ DirectoryInfo? outputDirectory;
[TestInitialize]
public void Initialize()
@@ -49,14 +49,17 @@ public void FirmwareTemplate_GenerateAndBuild(string metadataFileName, params st
}
catch (AssertFailedException)
{
- outputDirectory.Create();
- File.WriteAllText(Path.Combine(outputDirectory.FullName, appOutputFileName), headers.App);
- File.WriteAllText(Path.Combine(outputDirectory.FullName, appImplOutputFileName), implementation.App);
- File.WriteAllText(Path.Combine(outputDirectory.FullName, appFuncsOutputFileName), headers.AppFuncs);
- File.WriteAllText(Path.Combine(outputDirectory.FullName, appFuncsImplOutputFileName), implementation.AppFuncs);
- File.WriteAllText(Path.Combine(outputDirectory.FullName, appRegsOutputFileName), headers.AppRegs);
- File.WriteAllText(Path.Combine(outputDirectory.FullName, appRegsImplOutputFileName), implementation.AppRegs);
- File.WriteAllText(Path.Combine(outputDirectory.FullName, interruptsOutputFileName), implementation.Interrupts);
+ if (outputDirectory is not null)
+ {
+ outputDirectory.Create();
+ File.WriteAllText(Path.Combine(outputDirectory.FullName, appOutputFileName), headers.App);
+ File.WriteAllText(Path.Combine(outputDirectory.FullName, appImplOutputFileName), implementation.App);
+ File.WriteAllText(Path.Combine(outputDirectory.FullName, appFuncsOutputFileName), headers.AppFuncs);
+ File.WriteAllText(Path.Combine(outputDirectory.FullName, appFuncsImplOutputFileName), implementation.AppFuncs);
+ File.WriteAllText(Path.Combine(outputDirectory.FullName, appRegsOutputFileName), headers.AppRegs);
+ File.WriteAllText(Path.Combine(outputDirectory.FullName, appRegsImplOutputFileName), implementation.AppRegs);
+ File.WriteAllText(Path.Combine(outputDirectory.FullName, interruptsOutputFileName), implementation.Interrupts);
+ }
throw;
}
}
diff --git a/tests/InterfaceGeneratorTests.cs b/tests/InterfaceGeneratorTests.cs
index a9eda41..4998b8c 100644
--- a/tests/InterfaceGeneratorTests.cs
+++ b/tests/InterfaceGeneratorTests.cs
@@ -5,8 +5,8 @@ namespace Harp.Generators.Tests;
[TestClass]
public sealed class InterfaceGeneratorTests
{
- DirectoryInfo outputDirectory;
- string payloadExtensions;
+ DirectoryInfo? outputDirectory;
+ string payloadExtensions = "";
[TestInitialize]
public void Initialize()
@@ -24,7 +24,7 @@ public void DeviceTemplate_GenerateAndBuildWithoutErrors(string metadataFileName
{
metadataFileName = TestHelper.GetMetadataPath(metadataFileName);
var deviceMetadata = TestHelper.ReadDeviceMetadata(metadataFileName);
- var generator = new InterfaceGenerator(deviceMetadata, typeof(InterfaceGeneratorTests).Namespace);
+ var generator = new InterfaceGenerator(deviceMetadata, typeof(InterfaceGeneratorTests).Namespace ?? "");
var implementation = generator.GenerateImplementation();
var outputFileName = Path.GetFileNameWithoutExtension(metadataFileName);
var deviceOutputFileName = $"{outputFileName}.cs";
@@ -32,16 +32,18 @@ public void DeviceTemplate_GenerateAndBuildWithoutErrors(string metadataFileName
var customImplementation = TestHelper.GetManifestResourceText($"EmbeddedSources.{outputFileName}.cs");
try
{
- TestHelper.AssertNoGeneratorErrors(generator.Errors);
CompilerTestHelper.CompileFromSource(implementation.Device, implementation.AsyncDevice, payloadExtensions, customImplementation);
TestHelper.AssertExpectedOutput(implementation.Device, deviceOutputFileName);
TestHelper.AssertExpectedOutput(implementation.AsyncDevice, asyncDeviceOutputFileName);
}
catch (AssertFailedException)
{
- outputDirectory.Create();
- File.WriteAllText(Path.Combine(outputDirectory.FullName, deviceOutputFileName), implementation.Device);
- File.WriteAllText(Path.Combine(outputDirectory.FullName, asyncDeviceOutputFileName), implementation.AsyncDevice);
+ if (outputDirectory is not null)
+ {
+ outputDirectory.Create();
+ File.WriteAllText(Path.Combine(outputDirectory.FullName, deviceOutputFileName), implementation.Device);
+ File.WriteAllText(Path.Combine(outputDirectory.FullName, asyncDeviceOutputFileName), implementation.AsyncDevice);
+ }
throw;
}
}
diff --git a/tests/MetadataSerializerTests.cs b/tests/MetadataSerializerTests.cs
index f5bb566..83f6c2d 100644
--- a/tests/MetadataSerializerTests.cs
+++ b/tests/MetadataSerializerTests.cs
@@ -6,7 +6,7 @@ namespace Harp.Generators.Tests;
[TestClass]
public sealed class MetadataSerializerTests
{
- DirectoryInfo outputDirectory;
+ DirectoryInfo? outputDirectory;
[TestInitialize]
public void Initialize()
@@ -51,9 +51,13 @@ public void Metadata_RoundTripSerializes(string metadataFileName, Type type)
}
catch (AssertFailedException)
{
- outputDirectory.Create();
- File.WriteAllText(Path.Combine(outputDirectory.FullName, Path.GetFileName(metadataFileName)), roundTripContents);
- File.WriteAllText(Path.Combine(outputDirectory.FullName, $"{Path.GetFileNameWithoutExtension(metadataFileName)}_orig.yml"), metadataContents);
+ if (outputDirectory is not null)
+ {
+ outputDirectory.Create();
+ var originalMetadataFileName = $"{Path.GetFileNameWithoutExtension(metadataFileName)}_orig.yml";
+ File.WriteAllText(Path.Combine(outputDirectory.FullName, Path.GetFileName(metadataFileName)), roundTripContents);
+ File.WriteAllText(Path.Combine(outputDirectory.FullName, originalMetadataFileName), metadataContents);
+ }
throw;
}
}
diff --git a/tests/PayloadMarshal.cs b/tests/PayloadMarshal.cs
index 83caaa0..e266ab7 100644
--- a/tests/PayloadMarshal.cs
+++ b/tests/PayloadMarshal.cs
@@ -9,13 +9,16 @@ internal static partial class PayloadMarshal
{
internal static HarpVersion ReadHarpVersion(ArraySegment segment)
{
- var major = segment.Array[segment.Offset];
- var minor = segment.Array[segment.Offset + 1];
+ var major = segment.Array?[segment.Offset];
+ var minor = segment.Array?[segment.Offset + 1];
return new HarpVersion(major, minor);
}
internal static void Write(ArraySegment segment, HarpVersion value)
{
+ if (segment.Array is null)
+ return;
+
segment.Array[segment.Offset] = (byte)value.Major.GetValueOrDefault();
segment.Array[segment.Offset + 1] = (byte)value.Minor.GetValueOrDefault();
}
diff --git a/tests/YamlStream.cs b/tests/YamlStream.cs
index 87e571e..97bcdc7 100644
--- a/tests/YamlStream.cs
+++ b/tests/YamlStream.cs
@@ -55,8 +55,8 @@ internal class YamlSequenceNode : YamlNode
internal YamlSequenceNode(IParser parser)
{
Start = parser.Consume();
- SequenceEnd end;
- while (!parser.TryConsume(out end))
+ SequenceEnd? end;
+ while (!parser.TryConsume(out end))
{
Children.Add(Parse(parser));
}
@@ -83,8 +83,8 @@ internal class YamlMappingNode : YamlNode
internal YamlMappingNode(IParser parser)
{
Start = parser.Consume();
- MappingEnd end;
- while (!parser.TryConsume(out end))
+ MappingEnd? end;
+ while (!parser.TryConsume(out end))
{
var key = new YamlScalarNode(parser);
var value = Parse(parser);
@@ -114,9 +114,9 @@ class YamlScalarNodeEqualityComparer : IEqualityComparer
{
public static readonly YamlScalarNodeEqualityComparer Default = new();
- public bool Equals(YamlScalarNode x, YamlScalarNode y)
+ public bool Equals(YamlScalarNode? x, YamlScalarNode? y)
{
- return x.Event.Value == y.Event.Value;
+ return x?.Event.Value == y?.Event.Value;
}
public int GetHashCode([DisallowNull] YamlScalarNode obj)