diff --git a/.vscode/launch.json b/.vscode/launch.json
index b3837e3..6381c20 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -6,7 +6,7 @@
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
- "program": "${workspaceFolder}/Chickensoft.LogicBlocks.Example/bin/Debug/net7.0/Chickensoft.LogicBlocks.Example.dll",
+ "program": "${workspaceFolder}/Chickensoft.LogicBlocks.Example/bin/Debug/net8.0/Chickensoft.LogicBlocks.Example.dll",
"args": [
// "${input:args}"
],
@@ -17,4 +17,4 @@
"enableStepFiltering": false,
},
]
-}
\ No newline at end of file
+}
diff --git a/Chickensoft.LogicBlocks.CodeFixes/Chickensoft.LogicBlocks.CodeFixes.csproj b/Chickensoft.LogicBlocks.CodeFixes/Chickensoft.LogicBlocks.CodeFixes.csproj
index 7b7ef98..06bfd18 100644
--- a/Chickensoft.LogicBlocks.CodeFixes/Chickensoft.LogicBlocks.CodeFixes.csproj
+++ b/Chickensoft.LogicBlocks.CodeFixes/Chickensoft.LogicBlocks.CodeFixes.csproj
@@ -25,21 +25,21 @@
LogicBlocks CodeFixes release.
icon.png
state management;bloc;godot;game;state machine
- README.md
+ README.md
LICENSE
https://github.com/chickensoft-games/LogicBlocks
-
+
-
+
diff --git a/Chickensoft.LogicBlocks.DiagramGenerator.Tests/test_cases/OverriddenHandlers.cs b/Chickensoft.LogicBlocks.DiagramGenerator.Tests/test_cases/OverriddenHandlers.cs
new file mode 100644
index 0000000..2b4f82d
--- /dev/null
+++ b/Chickensoft.LogicBlocks.DiagramGenerator.Tests/test_cases/OverriddenHandlers.cs
@@ -0,0 +1,43 @@
+namespace Chickensoft.LogicBlocks.ScratchPad;
+
+using Chickensoft.Introspection;
+
+[Meta, LogicBlock(typeof(State), Diagram = true)]
+public partial class OverriddenHandlers : LogicBlock {
+ public override Transition GetInitialState() => To();
+
+ public static class Input {
+ public readonly record struct SomeInput();
+ public readonly record struct SomeOtherInput();
+
+ }
+
+ public static class Output {
+ public readonly record struct SomeOutput();
+ public readonly record struct SomeOtherOutput();
+ }
+
+ public abstract record State : StateLogic,
+ IGet, IGet {
+
+ public virtual Transition On(in Input.SomeInput input) {
+ Output(new Output.SomeOutput());
+
+ return ToSelf();
+ }
+
+ public Transition On(in Input.SomeOtherInput input) {
+ Output(new Output.SomeOtherOutput());
+
+ return ToSelf();
+ }
+
+ public record Idle : State {
+ public override Transition On(in Input.SomeInput input) {
+ Output(new Output.SomeOtherOutput());
+
+ return ToSelf();
+ }
+ }
+ }
+}
diff --git a/Chickensoft.LogicBlocks.DiagramGenerator.Tests/test_cases/OverriddenHandlers.g.puml b/Chickensoft.LogicBlocks.DiagramGenerator.Tests/test_cases/OverriddenHandlers.g.puml
new file mode 100644
index 0000000..4317ae5
--- /dev/null
+++ b/Chickensoft.LogicBlocks.DiagramGenerator.Tests/test_cases/OverriddenHandlers.g.puml
@@ -0,0 +1,15 @@
+@startuml OverriddenHandlers
+state "OverriddenHandlers State" as Chickensoft_LogicBlocks_ScratchPad_OverriddenHandlers_State {
+ state "Idle" as Chickensoft_LogicBlocks_ScratchPad_OverriddenHandlers_State_Idle
+}
+
+Chickensoft_LogicBlocks_ScratchPad_OverriddenHandlers_State --> Chickensoft_LogicBlocks_ScratchPad_OverriddenHandlers_State : SomeInput
+Chickensoft_LogicBlocks_ScratchPad_OverriddenHandlers_State --> Chickensoft_LogicBlocks_ScratchPad_OverriddenHandlers_State : SomeOtherInput
+Chickensoft_LogicBlocks_ScratchPad_OverriddenHandlers_State_Idle --> Chickensoft_LogicBlocks_ScratchPad_OverriddenHandlers_State_Idle : SomeInput
+
+Chickensoft_LogicBlocks_ScratchPad_OverriddenHandlers_State : OnSomeInput → SomeOutput
+Chickensoft_LogicBlocks_ScratchPad_OverriddenHandlers_State : OnSomeOtherInput → SomeOtherOutput
+Chickensoft_LogicBlocks_ScratchPad_OverriddenHandlers_State_Idle : OnSomeInput → SomeOtherOutput
+
+[*] --> Chickensoft_LogicBlocks_ScratchPad_OverriddenHandlers_State_Idle
+@enduml
\ No newline at end of file
diff --git a/Chickensoft.LogicBlocks.DiagramGenerator/src/Diagrammer.cs b/Chickensoft.LogicBlocks.DiagramGenerator/src/Diagrammer.cs
index 8761f81..c73827d 100644
--- a/Chickensoft.LogicBlocks.DiagramGenerator/src/Diagrammer.cs
+++ b/Chickensoft.LogicBlocks.DiagramGenerator/src/Diagrammer.cs
@@ -499,7 +499,7 @@ INamedTypeSymbol stateBaseType
// Get all of the handled inputs by looking at the implemented input
// handler interfaces.
- var handledInputInterfaces = type.Interfaces.Where(
+ var handledInputInterfaces = type.AllInterfaces.Where(
(interfaceType) => CodeService.GetNameFullyQualifiedWithoutGenerics(
interfaceType, interfaceType.Name
) is
@@ -507,6 +507,10 @@ INamedTypeSymbol stateBaseType
interfaceType.TypeArguments.Length == 1
);
+ var interfaces = new HashSet(
+ type.Interfaces, SymbolEqualityComparer.Default
+ );
+
// Get all syntax nodes comprising this type declaration.
var syntaxNodes = type.DeclaringSyntaxReferences
.Select(syntaxRef => syntaxRef.GetSyntax(token));
@@ -542,16 +546,37 @@ INamedTypeSymbol stateBaseType
continue;
}
+ var onTypeItself = interfaces.Contains(handledInputInterface);
+
+ if (!onTypeItself) {
+ // method is not on the current type (so it must be implemented on a
+ // base type).
+ //
+ // we have to check for this case since Roslyn doesn't return
+ // overridden methods on the derived type when asking for an interface's
+ // member implementation method — we have to look up the overrides
+ // ourselves :/
+
+ // find any equivalent, overridden method on the current derived type
+ methodSymbol = type.GetMembers()
+ .OfType()
+ .FirstOrDefault(
+ member => SymbolEqualityComparer.Default.Equals(
+ member.OverriddenMethod, methodSymbol
+ )
+ );
+
+ if (methodSymbol is null) {
+ continue;
+ }
+ }
+
var handlerMethodSyntaxes = methodSymbol
.DeclaringSyntaxReferences
.Select(syntaxRef => syntaxRef.GetSyntax(token))
.OfType()
.ToImmutableArray();
- if (handlerMethodSyntaxes.Length == 0) {
- continue;
- }
-
foreach (var methodSyntax in handlerMethodSyntaxes) {
inputHandlerMethods.Add(methodSyntax);
var inputId = CodeService.GetNameFullyQualifiedWithoutGenerics(