Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,19 @@ protected override void ProcessClass(SourceProductionContext spc, INamedTypeSymb
return;
}

var namespaces = new[] {
var namespaces = new[]
{
"using System;",
"using System.Diagnostics.CodeAnalysis;",
"using AtemSharp;",
"using AtemSharp.State.Info;",
"using AtemSharp.Lib;"
"using AtemSharp.Lib;",
"using System.CodeDom.Compiler;"
}.Concat(fields.Select(x => x!.NamespaceCode)).Distinct();

var internalDeserialization = GetInternalDeserializationMethod(classDecl);



var fileContent = $$"""
{{string.Join("\n", namespaces)}}

Expand All @@ -69,6 +70,7 @@ namespace {{ns}};
{
{{string.Join("\n", fields.Select(x => x!.PropertyCode))}}

{{Helpers.CodeGeneratorAttribute}}
public static IDeserializedCommand Deserialize(ReadOnlySpan<byte> rawCommand, ProtocolVersion protocolVersion)
{
var result = new {{className}} {
Expand All @@ -79,6 +81,7 @@ public static IDeserializedCommand Deserialize(ReadOnlySpan<byte> rawCommand, Pr
return result;
}
}

#nullable restore
""";

Expand All @@ -100,7 +103,8 @@ private static string GetInternalDeserializationMethod(ClassDeclarationSyntax cl
continue;
}

if (!method.Modifiers.Any(m => m.IsKind(SyntaxKind.PublicKeyword) || m.IsKind(SyntaxKind.PrivateKeyword) || m.IsKind(SyntaxKind.InternalKeyword)))
if (!method.Modifiers.Any(m => m.IsKind(SyntaxKind.PublicKeyword) || m.IsKind(SyntaxKind.PrivateKeyword) ||
m.IsKind(SyntaxKind.InternalKeyword)))
{
continue;
}
Expand All @@ -121,7 +125,6 @@ private static string GetInternalDeserializationMethod(ClassDeclarationSyntax cl
{
return "result.DeserializeInternal(rawCommand, protocolVersion);";
}

}

return string.Empty;
Expand All @@ -140,7 +143,7 @@ private static string CreatePropertyCode(IFieldSymbol f)

return $$"""
{{Helpers.GetFieldMsDocComment(f)}}
[ExcludeFromCodeCoverage]
{{Helpers.CodeGeneratorAttribute}}
public {{fieldType}} {{propertyName}}
{
get => {{f.Name}};
Expand Down
3 changes: 3 additions & 0 deletions AtemSharp.CodeGenerators/Helpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -349,5 +349,8 @@ public static string CreateNamespaceCode(IFieldSymbol fieldSymbol)

return $"using {ns};";
}

public static string CodeGeneratorAttribute =>
$"[GeneratedCode(\"{typeof(Helpers).Assembly.FullName}\",\"{typeof(Helpers).Assembly.ImageRuntimeVersion}\")]";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ protected override void ProcessClass(SourceProductionContext spc, INamedTypeSymb
"using System.Diagnostics.CodeAnalysis;",
"using AtemSharp;",
"using AtemSharp.State.Info;",
"using static AtemSharp.Commands.SerializationExtensions;"
"using static AtemSharp.Commands.SerializationExtensions;",
"using System.CodeDom.Compiler;"
}.Concat(fields.Select(x => x!.NamespaceCode)).Distinct();

var fileContent = $$"""
Expand All @@ -71,6 +72,7 @@ public partial class {{className}}
{{string.Join("\n", fields.Select(x => x!.PropertyCode))}}

/// <inheritdoc />
{{Helpers.CodeGeneratorAttribute}}
public override byte[] Serialize(ProtocolVersion version) {
var commandVersion = typeof({{className}}).GetCustomAttribute<CommandAttribute>()?.MinimumVersion;
if (commandVersion is not null && commandVersion < version) {
Expand All @@ -87,6 +89,7 @@ public override byte[] Serialize(ProtocolVersion version) {
return buffer;
}
}

#nullable restore
""";

Expand Down Expand Up @@ -130,18 +133,18 @@ private static string GetPropertyCode(IFieldSymbol f)
var setter = f.IsReadOnly
? string.Empty
: $$"""
set {
{{validationCode}}
{{f.Name}} = value;
{{flagCode}}
}
""";
set {
{{validationCode}}
{{f.Name}} = value;
{{flagCode}}
}
""";

return $$"""
{{docComment}}
{{Helpers.CodeGeneratorAttribute}}
{{visibility}} {{fieldType}} {{propertyName}}
{
[ExcludeFromCodeCoverage]
get => {{f.Name}};
{{setter}}
}
Expand All @@ -157,7 +160,7 @@ private static string GetPropertyCode(IFieldSymbol f)

var offset = Helpers.GetSerializationOffest(f);
var fieldType = Helpers.GetFieldType(f);
var isDouble = fieldType == "double" || fieldType == "System.Double";
var isDouble = fieldType is "double" or "System.Double";
var extensionMethod = Helpers.GetSerializationMethod(f);
var scalingFactor = Helpers.GetScalingFactor(f);

Expand Down
6 changes: 5 additions & 1 deletion AtemSharp.CodeGenerators/State/StateGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ public class StateGenerator : CodeGeneratorBase
private static readonly string[] HardCodedNamespaces =
{
"System.ComponentModel",
"System.Runtime.CompilerServices"
"System.Runtime.CompilerServices",
"System.CodeDom.Compiler"
};

protected override void ProcessClass(SourceProductionContext spc, INamedTypeSymbol classSymbol, ClassDeclarationSyntax classDecl)
Expand Down Expand Up @@ -43,6 +44,7 @@ partial class {{classSymbol.Name}} : INotifyPropertyChanged {

public event PropertyChangedEventHandler? PropertyChanged;

{{Helpers.CodeGeneratorAttribute}}
protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
Expand Down Expand Up @@ -71,11 +73,13 @@ private ProcessedField ProcessField(IFieldSymbol field)
var sendUpdateDeclaration = isReadOnly ? string.Empty : $"private partial void Send{propertyName}UpdateCommand({type} value);";

var code = $$"""
{{Helpers.CodeGeneratorAttribute}}
public {{type}} {{propertyName}} {
get => {{field.Name}};
{{setterCode}}
}

{{Helpers.CodeGeneratorAttribute}}
internal void Update{{propertyName}}({{type}} value) {
{{field.Name}} = value;
{{propertyName}}Changed?.Invoke(this, EventArgs.Empty);
Expand Down
29 changes: 11 additions & 18 deletions AtemSharp.Tests/AtemSwitcherTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using AtemSharp.Commands.Macro;
using AtemSharp.Commands.MixEffects.Transition;
using AtemSharp.Lib;
using AtemSharp.State.Macro;
using AtemSharp.State.Video.MixEffect;
using AtemSharp.Tests.TestUtilities;

Expand All @@ -15,7 +14,7 @@ public class AtemSwitcherTests
private class TestData : IAsyncDisposable
{
public AtemSwitcher Atem;
public TestServices Services;
public readonly TestServices Services;

public TestData()
{
Expand Down Expand Up @@ -84,8 +83,7 @@ public async Task ConnectAsync_WhileConnected_ShouldThrow()
data.Services.ClientFake.SimulateReceivedCommand(new InitCompleteCommand());
await data.Atem.ConnectAsync().WithTimeout();

var ex = Assert.ThrowsAsync<InvalidOperationException>(() => data.Atem.ConnectAsync());
Assert.That(ex!.Message, Does.Contain("Can not connect while"));
Assert.ThrowsAsync<InvalidOperationException>(() => data.Atem.ConnectAsync());
}

[Test]
Expand All @@ -95,8 +93,7 @@ public async Task ConnectAsync_WhileConnecting_ShouldThrow()

_ = data.Atem.ConnectAsync();

var ex = Assert.ThrowsAsync<InvalidOperationException>(async () => await data.Atem.ConnectAsync().WithTimeout());
Assert.That(ex!.Message, Does.Contain("Can not connect while"));
Assert.ThrowsAsync<InvalidOperationException>(async () => await data.Atem.ConnectAsync().WithTimeout());
}

[Test]
Expand Down Expand Up @@ -187,8 +184,7 @@ public async Task DisconnectAsync_WhileConnecting_ShouldThrow()
await using var data = new TestData();

_ = data.Atem.ConnectAsync();
var ex = Assert.ThrowsAsync<InvalidOperationException>(() => data.Atem.DisconnectAsync().WithTimeout());
Assert.That(ex.Message, Contains.Substring("while transitioning connection states"));
Assert.ThrowsAsync<InvalidOperationException>(() => data.Atem.DisconnectAsync().WithTimeout());
Assert.That(data.Atem.ConnectionState, Is.EqualTo(ConnectionState.Connecting));
}

Expand All @@ -204,8 +200,7 @@ public async Task DisconnectAsync_WhileDisconnecting_ShouldThrow()
var disconnectTask = data.Atem.DisconnectAsync();
Assert.That(disconnectTask.IsCompleted, Is.False);

var ex = Assert.ThrowsAsync<InvalidOperationException>(() => data.Atem.DisconnectAsync().WithTimeout());
Assert.That(ex.Message, Contains.Substring("while transitioning connection states"));
Assert.ThrowsAsync<InvalidOperationException>(() => data.Atem.DisconnectAsync().WithTimeout());
}

[Test]
Expand Down Expand Up @@ -255,9 +250,8 @@ public async Task SendCommandAsync_WhileNotConnected_ShouldThrow()
{
await using var data = new TestData();

var sendTask = data.Atem.SendCommandAsync(new MacroActionCommand(new Macro(data.Atem), MacroAction.Run));
var ex = Assert.ThrowsAsync<InvalidOperationException>(async () => await sendTask.WithTimeout());
Assert.That(ex.Message, Contains.Substring("while not connected"));
var sendTask = data.Atem.SendCommandAsync(MacroActionCommand.Stop());
Assert.ThrowsAsync<InvalidOperationException>(async () => await sendTask.WithTimeout());
}

[Test]
Expand All @@ -269,7 +263,7 @@ public async Task SendCommandsAsync()
data.Services.ClientFake.SimulateReceivedCommand(new InitCompleteCommand());
await data.Atem.ConnectAsync().WithTimeout();

MacroActionCommand[] commands = [new(new Macro(data.Atem), MacroAction.Run), new(new Macro(data.Atem), MacroAction.Stop)];
MacroActionCommand[] commands = [MacroActionCommand.Stop(), MacroActionCommand.Continue()];
await data.Atem.SendCommandsAsync(commands).WithTimeout();

Assert.That(data.Services.ClientFake.SentCommands, Is.EquivalentTo(commands));
Expand All @@ -280,10 +274,9 @@ public async Task SendCommandsAsync_WhileNotConnected_ShouldThrow()
{
await using var data = new TestData();

MacroActionCommand[] commands = [new(new Macro(data.Atem), MacroAction.Run), new(new Macro(data.Atem), MacroAction.Stop)];
MacroActionCommand[] commands = [MacroActionCommand.Stop(), MacroActionCommand.Continue()];
var sendTask = data.Atem.SendCommandsAsync(commands);
var ex = Assert.ThrowsAsync<InvalidOperationException>(async () => await sendTask.WithTimeout());
Assert.That(ex.Message, Contains.Substring("while not connected"));
Assert.ThrowsAsync<InvalidOperationException>(async () => await sendTask.WithTimeout());
}

[Test]
Expand Down Expand Up @@ -321,7 +314,7 @@ public async Task ReceiveCommand_ShouldUpdateState()
{
Assert.That(data.Atem.Macros.Player.CurrentlyPlaying, Is.SameAs(data.Atem.Macros[2]));
Assert.That(data.Atem.Macros.Player.PlayLooped, Is.True);
Assert.That(data.Atem.Macros.Player.PlaybackIsWaiting, Is.False);
Assert.That(data.Atem.Macros.Player.PlaybackIsWaitingForUserAction, Is.False);
});
}

Expand Down
11 changes: 10 additions & 1 deletion AtemSharp.Tests/Commands/Macro/MacroActionCommandTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@ public class CommandData : CommandDataBase
protected override MacroActionCommand CreateSut(TestUtilities.CommandTests.TestCaseData<CommandData> testCase)
{
var macro = new AtemSharp.State.Macro.Macro(Substitute.For<IAtemSwitcher>()) { Id = testCase.Command.Index };
return new MacroActionCommand(macro, testCase.Command.Action);
return testCase.Command.Action switch
{
MacroAction.Run => MacroActionCommand.Run(macro),
MacroAction.Stop => MacroActionCommand.Stop(),
MacroAction.StopRecord => MacroActionCommand.StopRecord(),
MacroAction.InsertUserWait => MacroActionCommand.InsertUserWait(),
MacroAction.Continue => MacroActionCommand.Continue(),
MacroAction.Delete => MacroActionCommand.Delete(macro),
_ => throw new ArgumentOutOfRangeException()
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,6 @@ protected override void CompareStateProperties(IStateHolder state, CommandData e
}

Assert.That(state.Macros.Player.PlayLooped, Is.EqualTo(expectedData.Loop));
Assert.That(state.Macros.Player.PlaybackIsWaiting, Is.EqualTo(expectedData.IsWaiting));
Assert.That(state.Macros.Player.PlaybackIsWaitingForUserAction, Is.EqualTo(expectedData.IsWaiting));
}
}
Loading