From 15fd2e884e6c41df94f3978cf49e6bc7c99536ca Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Wed, 18 Jan 2023 13:04:10 +0100 Subject: [PATCH] Add printing exact source code location on networking bindings generation for C# types --- .../Build/Plugins/NetworkingPlugin.cs | 25 +++++---- .../Tools/Flax.Build/Utilities/MonoCecil.cs | 52 +++++++++++++++++++ 2 files changed, 67 insertions(+), 10 deletions(-) diff --git a/Source/Tools/Flax.Build/Build/Plugins/NetworkingPlugin.cs b/Source/Tools/Flax.Build/Build/Plugins/NetworkingPlugin.cs index 47be906d9..41ed23eab 100644 --- a/Source/Tools/Flax.Build/Build/Plugins/NetworkingPlugin.cs +++ b/Source/Tools/Flax.Build/Build/Plugins/NetworkingPlugin.cs @@ -805,13 +805,13 @@ namespace Flax.Build.Plugins { if (property.GetMethod == null) { - Log.Error($"Missing getter method for property '{property.Name}' of type {valueType.FullName} in {type.FullName} for automatic replication."); + MonoCecil.CompilationError($"Missing getter method for property '{property.Name}' of type {valueType.FullName} in {type.FullName} for automatic replication.", property); failed = true; return; } if (property.SetMethod == null) { - Log.Error($"Missing setter method for property '{property.Name}' of type {valueType.FullName} in {type.FullName} for automatic replication."); + MonoCecil.CompilationError($"Missing setter method for property '{property.Name}' of type {valueType.FullName} in {type.FullName} for automatic replication.", property); failed = true; return; } @@ -1090,7 +1090,12 @@ namespace Flax.Build.Plugins else { // Unknown type - Log.Error($"Not supported type '{valueType.FullName}' on {(field?.Name ?? property.Name)} in {type.FullName} for automatic replication."); + if (property != null) + MonoCecil.CompilationError($"Not supported type '{valueType.FullName}' on {property.Name} in {type.FullName} for automatic replication.", property); + else if (field != null) + MonoCecil.CompilationError($"Not supported type '{valueType.FullName}' on {field.Name} in {type.FullName} for automatic replication.", field.Resolve()); + else + MonoCecil.CompilationError($"Not supported type '{valueType.FullName}' for automatic replication."); failed = true; } } @@ -1212,13 +1217,13 @@ namespace Flax.Build.Plugins // Validate RPC usage if (method.IsAbstract) { - Log.Error($"Not supported abstract RPC method '{method.FullName}'."); + MonoCecil.CompilationError($"Not supported abstract RPC method '{method.FullName}'.", method); failed = true; return; } if (method.IsVirtual) { - Log.Error($"Not supported virtual RPC method '{method.FullName}'."); + MonoCecil.CompilationError($"Not supported virtual RPC method '{method.FullName}'.", method); failed = true; return; } @@ -1226,13 +1231,13 @@ namespace Flax.Build.Plugins var voidType = module.TypeSystem.Void; if (method.ReturnType != voidType) { - Log.Error($"Not supported non-void RPC method '{method.FullName}'."); + MonoCecil.CompilationError($"Not supported non-void RPC method '{method.FullName}'.", method); failed = true; return; } if (method.IsStatic) { - Log.Error($"Not supported static RPC method '{method.FullName}'."); + MonoCecil.CompilationError($"Not supported static RPC method '{method.FullName}'.", method); failed = true; return; } @@ -1243,13 +1248,13 @@ namespace Flax.Build.Plugins methodRPC.IsClient = (bool)attribute.GetFieldValue("Client", false); if (methodRPC.IsServer && methodRPC.IsClient) { - Log.Error($"Network RPC {method.Name} in {type.FullName} cannot be both Server and Client."); + MonoCecil.CompilationError($"Network RPC {method.Name} in {type.FullName} cannot be both Server and Client.", method); failed = true; return; } if (!methodRPC.IsServer && !methodRPC.IsClient) { - Log.Error($"Network RPC {method.Name} in {type.FullName} needs to have Server or Client specifier."); + MonoCecil.CompilationError($"Network RPC {method.Name} in {type.FullName} needs to have Server or Client specifier.", method); failed = true; return; } @@ -1289,7 +1294,7 @@ namespace Flax.Build.Plugins var parameter = method.Parameters[i]; if (parameter.IsOut) { - Log.Error($"Network RPC {method.Name} in {type.FullName} parameter {parameter.Name} cannot be 'out'."); + MonoCecil.CompilationError($"Network RPC {method.Name} in {type.FullName} parameter {parameter.Name} cannot be 'out'.", method); failed = true; return; } diff --git a/Source/Tools/Flax.Build/Utilities/MonoCecil.cs b/Source/Tools/Flax.Build/Utilities/MonoCecil.cs index 444cbf6ec..43c1de4ba 100644 --- a/Source/Tools/Flax.Build/Utilities/MonoCecil.cs +++ b/Source/Tools/Flax.Build/Utilities/MonoCecil.cs @@ -11,6 +11,58 @@ namespace Flax.Build /// internal static class MonoCecil { + public static void CompilationError(string message) + { + Log.Error(message); + } + + public static void CompilationError(string message, MethodDefinition method) + { + if (method != null && method.DebugInformation.HasSequencePoints) + { + var sp = method.DebugInformation.SequencePoints[0]; + message = $"{sp.Document.Url}({sp.StartLine},{sp.StartColumn},{sp.EndLine},{sp.EndColumn}): error: {message}"; + } + Log.Error(message); + } + + public static void CompilationError(string message, PropertyDefinition property) + { + if (property != null) + { + if (property.GetMethod != null) + { + CompilationError(message, property.GetMethod); + return; + } + else if (property.SetMethod != null) + { + CompilationError(message, property.SetMethod); + return; + } + } + Log.Error(message); + } + + public static void CompilationError(string message, FieldDefinition field) + { + if (field != null && field.DeclaringType != null) + { + // Just include potential filename + var methods = field.DeclaringType.Methods; + if (methods != null && methods.Count != 0) + { + var method = methods[0]; + if (method != null && method.DebugInformation.HasSequencePoints) + { + var sp = method.DebugInformation.SequencePoints[0]; + message = $"{sp.Document.Url}({0},{0},{0},{0}): error: {message}"; + } + } + } + Log.Error(message); + } + public static bool HasAttribute(this ICustomAttributeProvider type, string fullName) { return type.CustomAttributes.Any(x => x.AttributeType.FullName == fullName);