From 94945006f48c486482a67a8c114a2fbe32c2aba4 Mon Sep 17 00:00:00 2001 From: James Frowen Date: Sun, 20 Jun 2021 14:31:06 +0100 Subject: [PATCH 001/166] feat: adding attribute to ignore extension method for read writer (#841) * feat: adding attibute to ignore extension method for read writer * tests * refactoring ReaderWriterProcessor adding SerailizeExtensionHelper to handle checking of types and methods to find extension methods making reflection and cecil methods have the same logic * adding better fail message to assert * fixing checking type is void * fixing code smell --- Assets/Mirage/Runtime/CustomAttributes.cs | 6 + .../Processors/ReaderWriterProcessor.cs | 268 +++++++++++------- .../Runtime/Serialization/WeaverIgnoreTest.cs | 53 ++++ .../Serialization/WeaverIgnoreTest.cs.meta | 11 + Assets/Tests/Weaver/Tests.cs | 2 +- 5 files changed, 237 insertions(+), 103 deletions(-) create mode 100644 Assets/Tests/Runtime/Serialization/WeaverIgnoreTest.cs create mode 100644 Assets/Tests/Runtime/Serialization/WeaverIgnoreTest.cs.meta diff --git a/Assets/Mirage/Runtime/CustomAttributes.cs b/Assets/Mirage/Runtime/CustomAttributes.cs index 7dd34553f72..bee5eecc05e 100644 --- a/Assets/Mirage/Runtime/CustomAttributes.cs +++ b/Assets/Mirage/Runtime/CustomAttributes.cs @@ -124,4 +124,10 @@ public sealed class ShowInInspectorAttribute : Attribute { } /// [AttributeUsage(AttributeTargets.Field)] public sealed class FoldoutEventAttribute : PropertyAttribute { } + + /// + /// Tells Weaver to ignore an Extension method + /// + [AttributeUsage(AttributeTargets.Method)] + public sealed class WeaverIgnoreAttribute : PropertyAttribute { } } diff --git a/Assets/Mirage/Weaver/Processors/ReaderWriterProcessor.cs b/Assets/Mirage/Weaver/Processors/ReaderWriterProcessor.cs index 373f5485aaa..a7a6f50e5ab 100644 --- a/Assets/Mirage/Weaver/Processors/ReaderWriterProcessor.cs +++ b/Assets/Mirage/Weaver/Processors/ReaderWriterProcessor.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using System.Runtime.CompilerServices; using Mirage.Serialization; using Mono.Cecil; using Mono.Cecil.Cil; @@ -18,6 +19,7 @@ public class ReaderWriterProcessor private readonly ModuleDefinition module; private readonly Readers readers; private readonly Writers writers; + private readonly SerailizeExtensionHelper extensionHelper; /// /// Mirage's main module used to find built in extension methods and messages @@ -29,6 +31,7 @@ public ReaderWriterProcessor(ModuleDefinition module, Readers readers, Writers w this.module = module; this.readers = readers; this.writers = writers; + extensionHelper = new SerailizeExtensionHelper(module, readers, writers); } public bool Process() @@ -46,37 +49,18 @@ public bool Process() return writers.Count != writeCount || readers.Count != readCount; } - #region Load Mirage built in readers and writers private void LoadBuiltinExtensions() { // find all extension methods - IEnumerable types = MirageModule.GetTypes().Where(IsStatic); + IEnumerable types = MirageModule.GetTypes(); foreach (Type type in types) { - IEnumerable methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public) - .Where(IsExtension) - .Where(NotGeneric); - - foreach (MethodInfo method in methods) - { - RegisterReader(method); - RegisterWriter(method); - } + extensionHelper.RegisterExtensionMethodsInType(type); } } - /// - /// static classes are declared abstract and sealed at the IL level. - /// - /// - private static bool IsStatic(Type t) => t.IsSealed && t.IsAbstract; - - private static bool IsExtension(MethodInfo method) => Attribute.IsDefined(method, typeof(System.Runtime.CompilerServices.ExtensionAttribute)); - private static bool NotGeneric(MethodInfo method) => !method.IsGenericMethod; - - private void LoadBuiltinMessages() { IEnumerable types = MirageModule.GetTypes().Where(t => t.GetCustomAttribute() != null); @@ -88,35 +72,6 @@ private void LoadBuiltinMessages() messages.Add(typeReference); } } - - - private void RegisterReader(MethodInfo method) - { - if (method.GetParameters().Length != 1) - return; - - if (method.GetParameters()[0].ParameterType.FullName != typeof(NetworkReader).FullName) - return; - - if (method.ReturnType == typeof(void)) - return; - readers.Register(module.ImportReference(method.ReturnType), module.ImportReference(method)); - } - - private void RegisterWriter(MethodInfo method) - { - if (method.GetParameters().Length != 2) - return; - - if (method.GetParameters()[0].ParameterType.FullName != typeof(NetworkWriter).FullName) - return; - - if (method.ReturnType != typeof(void)) - return; - - Type dataType = method.GetParameters()[1].ParameterType; - writers.Register(module.ImportReference(dataType), module.ImportReference(method)); - } #endregion #region Assembly defined reader/writer @@ -128,11 +83,7 @@ void ProcessAssemblyClasses() { // extension methods only live in static classes // static classes are represented as sealed and abstract - if (klass.IsAbstract && klass.IsSealed) - { - LoadDeclaredWriters(klass); - LoadDeclaredReaders(klass); - } + extensionHelper.RegisterExtensionMethodsInType(klass); if (klass.GetCustomAttribute() != null) { @@ -255,54 +206,7 @@ private static bool IsReadWriteMethod(MethodReference method) method.Is(nameof(NetworkReader.Read)); } - void LoadDeclaredWriters(TypeDefinition klass) - { - // register all the writers in this class. Skip the ones with wrong signature - foreach (MethodDefinition method in klass.Methods) - { - if (method.Parameters.Count != 2) - continue; - - if (!method.Parameters[0].ParameterType.Is()) - continue; - - if (!method.ReturnType.Is(typeof(void))) - continue; - - if (!method.HasCustomAttribute()) - continue; - - if (method.HasGenericParameters) - continue; - - TypeReference dataType = method.Parameters[1].ParameterType; - writers.Register(dataType, module.ImportReference(method)); - } - } - - void LoadDeclaredReaders(TypeDefinition klass) - { - // register all the reader in this class. Skip the ones with wrong signature - foreach (MethodDefinition method in klass.Methods) - { - if (method.Parameters.Count != 1) - continue; - - if (!method.Parameters[0].ParameterType.Is()) - continue; - - if (method.ReturnType.Is(typeof(void))) - continue; - - if (!method.HasCustomAttribute()) - continue; - if (method.HasGenericParameters) - continue; - - readers.Register(method.ReturnType, module.ImportReference(method)); - } - } private static bool IsEditorAssembly(ModuleDefinition module) { @@ -364,4 +268,164 @@ private void RegisterMessages(ILProcessor worker) #endregion } + + /// + /// Helps get Extension methods using either reflection or cecil + /// + public class SerailizeExtensionHelper + { + private readonly ModuleDefinition module; + private readonly Readers readers; + private readonly Writers writers; + + public SerailizeExtensionHelper(ModuleDefinition module, Readers readers, Writers writers) + { + this.module = module; + this.readers = readers; + this.writers = writers; + } + + + public void RegisterExtensionMethodsInType(Type type) + { + // only check static types + if (!IsStatic(type)) + return; + + IEnumerable methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public) + .Where(IsExtension) + .Where(NotGeneric) + .Where(NotIgnored); + + foreach (MethodInfo method in methods) + { + if (IsWriterMethod(method)) + { + RegisterWriter(method); + } + + if (IsReaderMethod(method)) + { + RegisterReader(method); + } + } + } + public void RegisterExtensionMethodsInType(TypeDefinition type) + { + // only check static types + if (!IsStatic(type)) + return; + + IEnumerable methods = type.Methods + .Where(IsExtension) + .Where(NotGeneric) + .Where(NotIgnored); + + foreach (MethodDefinition method in methods) + { + if (IsWriterMethod(method)) + { + RegisterWriter(method); + } + + if (IsReaderMethod(method)) + { + RegisterReader(method); + } + } + } + + /// + /// static classes are declared abstract and sealed at the IL level. + /// + /// + private static bool IsStatic(Type t) => t.IsSealed && t.IsAbstract; + private static bool IsStatic(TypeDefinition t) => t.IsSealed && t.IsAbstract; + + private static bool IsExtension(MethodInfo method) => Attribute.IsDefined(method, typeof(ExtensionAttribute)); + private static bool IsExtension(MethodDefinition method) => method.HasCustomAttribute(); + private static bool NotGeneric(MethodInfo method) => !method.IsGenericMethod; + private static bool NotGeneric(MethodDefinition method) => !method.IsGenericInstance; + + /// true if method does not have + private static bool NotIgnored(MethodInfo method) => !Attribute.IsDefined(method, typeof(WeaverIgnoreAttribute)); + /// true if method does not have + private static bool NotIgnored(MethodDefinition method) => !method.HasCustomAttribute(); + + + private static bool IsWriterMethod(MethodInfo method) + { + if (method.GetParameters().Length != 2) + return false; + + if (method.GetParameters()[0].ParameterType.FullName != typeof(NetworkWriter).FullName) + return false; + + if (method.ReturnType != typeof(void)) + return false; + + return true; + } + private bool IsWriterMethod(MethodDefinition method) + { + if (method.Parameters.Count != 2) + return false; + + if (method.Parameters[0].ParameterType.FullName != typeof(NetworkWriter).FullName) + return false; + + if (!method.ReturnType.Is(typeof(void))) + return false; + + return true; + } + + private static bool IsReaderMethod(MethodInfo method) + { + if (method.GetParameters().Length != 1) + return false; + + if (method.GetParameters()[0].ParameterType.FullName != typeof(NetworkReader).FullName) + return false; + + if (method.ReturnType == typeof(void)) + return false; + + return true; + } + private bool IsReaderMethod(MethodDefinition method) + { + if (method.Parameters.Count != 1) + return false; + + if (method.Parameters[0].ParameterType.FullName != typeof(NetworkReader).FullName) + return false; + + if (method.ReturnType.Is(typeof(void))) + return false; + + return true; + } + + private void RegisterWriter(MethodInfo method) + { + Type dataType = method.GetParameters()[1].ParameterType; + writers.Register(module.ImportReference(dataType), module.ImportReference(method)); + } + private void RegisterWriter(MethodDefinition method) + { + TypeReference dataType = method.Parameters[1].ParameterType; + writers.Register(module.ImportReference(dataType), module.ImportReference(method)); + } + + + private void RegisterReader(MethodInfo method) + { + readers.Register(module.ImportReference(method.ReturnType), module.ImportReference(method)); + } + private void RegisterReader(MethodDefinition method) + { + readers.Register(module.ImportReference(method.ReturnType), module.ImportReference(method)); + } + } } diff --git a/Assets/Tests/Runtime/Serialization/WeaverIgnoreTest.cs b/Assets/Tests/Runtime/Serialization/WeaverIgnoreTest.cs new file mode 100644 index 00000000000..dfefe8e9165 --- /dev/null +++ b/Assets/Tests/Runtime/Serialization/WeaverIgnoreTest.cs @@ -0,0 +1,53 @@ +using System; +using Mirage.Serialization; +using NUnit.Framework; + +namespace Mirage.Tests.Runtime.Serialization +{ + public class WeaverIgnoreTest + { + [Test] + public void DoesNotUseCustomWriter() + { + // check method names + Assert.That(Writer.Write.Method.Name, Is.Not.EqualTo(new Action(MyCustomTypeExtension.WriteOnlyPartOfCustom).Method.Name)); + Assert.That(Reader.Read.Method.Name, Is.Not.EqualTo(new Func(MyCustomTypeExtension.ReadOnlyPartOfCustom).Method.Name)); + + // check writing and reading + var data = new MyCustomType + { + first = 10, + second = 20, + }; + var writer = new NetworkWriter(); + writer.Write(data); + var reader = new NetworkReader(writer.ToArraySegment()); + MyCustomType copy = reader.Read(); + + // should have copied both fields, + // if it uses custom extension methods it will only write first + Assert.That(copy.first, Is.EqualTo(data.first)); + Assert.That(copy.second, Is.EqualTo(data.second)); + } + + } + public struct MyCustomType + { + public int first; + public int second; + } + public static class MyCustomTypeExtension + { + [WeaverIgnore] + public static void WriteOnlyPartOfCustom(this NetworkWriter writer, MyCustomType value) + { + writer.WriteInt32(value.first); + } + [WeaverIgnore] + + public static MyCustomType ReadOnlyPartOfCustom(this NetworkReader reader) + { + return new MyCustomType { first = reader.ReadInt32() }; + } + } +} diff --git a/Assets/Tests/Runtime/Serialization/WeaverIgnoreTest.cs.meta b/Assets/Tests/Runtime/Serialization/WeaverIgnoreTest.cs.meta new file mode 100644 index 00000000000..c5ddff0b9bc --- /dev/null +++ b/Assets/Tests/Runtime/Serialization/WeaverIgnoreTest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2e9ee5990fd72af43b067517fad704cf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Tests/Weaver/Tests.cs b/Assets/Tests/Weaver/Tests.cs index 8245d4877e5..c94d3bfd283 100644 --- a/Assets/Tests/Weaver/Tests.cs +++ b/Assets/Tests/Weaver/Tests.cs @@ -24,7 +24,7 @@ public virtual void TestSetup() [AssertionMethod] protected void IsSuccess() { - Assert.That(weaverLog.Diagnostics, Is.Empty); + Assert.That(weaverLog.Diagnostics, Is.Empty, $"Failed because there are Diagnostics message: \n {string.Join("\n ", weaverLog.Diagnostics.Select(x => x.MessageData))}\n"); } [AssertionMethod] From 039b2c4735171c71752373ec105da43e72bf19ee Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 20 Jun 2021 13:45:16 +0000 Subject: [PATCH 002/166] chore(release): 96.4.0 [skip ci] # [96.4.0](https://github.com/MirageNet/Mirage/compare/v96.3.1...v96.4.0) (2021-06-20) ### Features * adding attribute to ignore extension method for read writer ([#841](https://github.com/MirageNet/Mirage/issues/841)) ([9494500](https://github.com/MirageNet/Mirage/commit/94945006f48c486482a67a8c114a2fbe32c2aba4)) --- Assets/Mirage/Authenticators/AssemblyInfo.cs | 2 +- Assets/Mirage/CHANGELOG.md | 7 +++++++ Assets/Mirage/Components/AssemblyInfo.cs | 2 +- Assets/Mirage/Runtime/AssemblyInfo.cs | 2 +- Assets/Mirage/Runtime/SocketLayer/AssemblyInfo.cs | 2 +- Assets/Mirage/Samples~/AssemblyInfo.cs | 2 +- .../Samples~/RigidbodyPhysics/Scripts/AssemblyInfo.cs | 2 +- Assets/Mirage/package.json | 2 +- 8 files changed, 14 insertions(+), 7 deletions(-) diff --git a/Assets/Mirage/Authenticators/AssemblyInfo.cs b/Assets/Mirage/Authenticators/AssemblyInfo.cs index 1467dac044e..92c5c974d14 100644 --- a/Assets/Mirage/Authenticators/AssemblyInfo.cs +++ b/Assets/Mirage/Authenticators/AssemblyInfo.cs @@ -1,3 +1,3 @@ using System.Reflection; -[assembly: AssemblyVersion("96.3.1")] +[assembly: AssemblyVersion("96.4.0")] diff --git a/Assets/Mirage/CHANGELOG.md b/Assets/Mirage/CHANGELOG.md index fa59dc2c920..829105f67ba 100644 --- a/Assets/Mirage/CHANGELOG.md +++ b/Assets/Mirage/CHANGELOG.md @@ -1,3 +1,10 @@ +# [96.4.0](https://github.com/MirageNet/Mirage/compare/v96.3.1...v96.4.0) (2021-06-20) + + +### Features + +* adding attribute to ignore extension method for read writer ([#841](https://github.com/MirageNet/Mirage/issues/841)) ([9494500](https://github.com/MirageNet/Mirage/commit/94945006f48c486482a67a8c114a2fbe32c2aba4)) + ## [96.3.1](https://github.com/MirageNet/Mirage/compare/v96.3.0...v96.3.1) (2021-06-17) diff --git a/Assets/Mirage/Components/AssemblyInfo.cs b/Assets/Mirage/Components/AssemblyInfo.cs index 691d1538f04..89c31162046 100644 --- a/Assets/Mirage/Components/AssemblyInfo.cs +++ b/Assets/Mirage/Components/AssemblyInfo.cs @@ -1,6 +1,6 @@ using System.Reflection; using System.Runtime.CompilerServices; -[assembly: AssemblyVersion("96.3.1")] +[assembly: AssemblyVersion("96.4.0")] [assembly: InternalsVisibleTo("Mirage.Tests.Runtime")] diff --git a/Assets/Mirage/Runtime/AssemblyInfo.cs b/Assets/Mirage/Runtime/AssemblyInfo.cs index 7e2385ac1e4..09809e2b7a6 100644 --- a/Assets/Mirage/Runtime/AssemblyInfo.cs +++ b/Assets/Mirage/Runtime/AssemblyInfo.cs @@ -1,7 +1,7 @@ using System.Reflection; using System.Runtime.CompilerServices; -[assembly: AssemblyVersion("96.3.1")] +[assembly: AssemblyVersion("96.4.0")] [assembly: InternalsVisibleTo("Mirage.Tests.Common")] [assembly: InternalsVisibleTo("Mirage.Tests")] diff --git a/Assets/Mirage/Runtime/SocketLayer/AssemblyInfo.cs b/Assets/Mirage/Runtime/SocketLayer/AssemblyInfo.cs index 0e45715bd20..645d247fa9e 100644 --- a/Assets/Mirage/Runtime/SocketLayer/AssemblyInfo.cs +++ b/Assets/Mirage/Runtime/SocketLayer/AssemblyInfo.cs @@ -1,6 +1,6 @@ using System.Reflection; using System.Runtime.CompilerServices; -[assembly: AssemblyVersion("96.3.1")] +[assembly: AssemblyVersion("96.4.0")] [assembly: InternalsVisibleTo("Mirage.SocketLayer.Tests")] diff --git a/Assets/Mirage/Samples~/AssemblyInfo.cs b/Assets/Mirage/Samples~/AssemblyInfo.cs index 1467dac044e..92c5c974d14 100644 --- a/Assets/Mirage/Samples~/AssemblyInfo.cs +++ b/Assets/Mirage/Samples~/AssemblyInfo.cs @@ -1,3 +1,3 @@ using System.Reflection; -[assembly: AssemblyVersion("96.3.1")] +[assembly: AssemblyVersion("96.4.0")] diff --git a/Assets/Mirage/Samples~/RigidbodyPhysics/Scripts/AssemblyInfo.cs b/Assets/Mirage/Samples~/RigidbodyPhysics/Scripts/AssemblyInfo.cs index 1467dac044e..92c5c974d14 100644 --- a/Assets/Mirage/Samples~/RigidbodyPhysics/Scripts/AssemblyInfo.cs +++ b/Assets/Mirage/Samples~/RigidbodyPhysics/Scripts/AssemblyInfo.cs @@ -1,3 +1,3 @@ using System.Reflection; -[assembly: AssemblyVersion("96.3.1")] +[assembly: AssemblyVersion("96.4.0")] diff --git a/Assets/Mirage/package.json b/Assets/Mirage/package.json index 10642f5262b..047a4e0cd72 100644 --- a/Assets/Mirage/package.json +++ b/Assets/Mirage/package.json @@ -1,7 +1,7 @@ { "name": "com.miragenet.mirage", "displayName": "Mirage", - "version": "96.3.1", + "version": "96.4.0", "unity": "2019.1", "description": "Mirage is a high level Networking API for Unity, supporting different low level Transports.", "author": "Mirage", From a18784451fb8b4711964ee9ef6c19c161a02059b Mon Sep 17 00:00:00 2001 From: dragonslaya84 Date: Mon, 21 Jun 2021 03:44:39 -0400 Subject: [PATCH 003/166] fix: welcome window fixes (#845) * fix: paths for welcome window changelog. fix: allow 2019 and up for welcome window. Signed-off-by: dragonslaya * fix: this fixes styling and error on 2019+ editors. Signed-off-by: dragonslaya * fix: Welcome window now searches for existing file of the changelog to know which mirage install was done. Signed-off-by: dragonslaya * fix: proper fix using current welcome window script path to get changelog path. fix: fixed code smells Signed-off-by: dragonslaya Co-authored-by: dragonslaya --- .../WelcomeWindow/Resources/WelcomeWindow.uxml | 6 ++++-- .../Mirage/Editor/WelcomeWindow/WelcomeWindow.cs | 16 +++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Assets/Mirage/Editor/WelcomeWindow/Resources/WelcomeWindow.uxml b/Assets/Mirage/Editor/WelcomeWindow/Resources/WelcomeWindow.uxml index 5e3c467597d..c371a818001 100644 --- a/Assets/Mirage/Editor/WelcomeWindow/Resources/WelcomeWindow.uxml +++ b/Assets/Mirage/Editor/WelcomeWindow/Resources/WelcomeWindow.uxml @@ -1,5 +1,6 @@ - -