diff --git a/.editorconfig b/.editorconfig index fc9200a9..6967d7e7 100644 --- a/.editorconfig +++ b/.editorconfig @@ -71,3 +71,73 @@ csharp_space_between_method_call_parameter_list_parentheses = false csharp_space_between_parentheses = false csharp_preserve_single_line_statements = true csharp_preserve_single_line_blocks = true +csharp_using_directive_placement = outside_namespace:silent +csharp_prefer_simple_using_statement = true:warning +csharp_style_namespace_declarations = block_scoped:silent +csharp_style_prefer_method_group_conversion = true:silent +csharp_style_prefer_top_level_statements = true:silent +csharp_style_expression_bodied_lambdas = when_on_single_line:silent +csharp_style_expression_bodied_local_functions = when_on_single_line:silent + +[*.{cs,vb}] +#### Naming styles #### + +# Naming rules + +dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion +dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface +dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i + +dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.types_should_be_pascal_case.symbols = types +dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case + +# Symbol specifications + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = + +# Naming styles + +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.capitalization = pascal_case + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +dotnet_style_prefer_auto_properties = true:silent +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_prefer_simplified_boolean_expressions = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_operator_placement_when_wrapping = beginning_of_line +tab_width = 3 +indent_size = 3 diff --git a/Directory.Build.props b/Directory.Build.props index 6b354d0d..c891ff4d 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -2,7 +2,8 @@ 2.3.0.0 - 22.6.3.1 + -prerelease.2 + 1.0.0-prerelease.2 diff --git a/Harmony.sln b/Harmony.sln index 32b4cdf8..ca26eb78 100644 --- a/Harmony.sln +++ b/Harmony.sln @@ -16,7 +16,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Directory.Build.props = Directory.Build.props global.json = global.json LICENSE = LICENSE - nuget.config = nuget.config README.md = README.md EndProjectSection EndProject diff --git a/Harmony/Documentation/Documentation.csproj b/Harmony/Documentation/Documentation.csproj index ffae4392..d1b1ac8b 100644 --- a/Harmony/Documentation/Documentation.csproj +++ b/Harmony/Documentation/Documentation.csproj @@ -1,7 +1,7 @@ - net35;net45;net472;net48;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0 + net35;net452;net472;net48;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0;net7.0 preview false obj @@ -27,13 +27,14 @@ - - - - + - - + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + diff --git a/Harmony/Documentation/GlobalSuppressions.cs b/Harmony/Documentation/GlobalSuppressions.cs index 45ee5e7c..d023e715 100644 --- a/Harmony/Documentation/GlobalSuppressions.cs +++ b/Harmony/Documentation/GlobalSuppressions.cs @@ -1,21 +1,22 @@ using System.Diagnostics.CodeAnalysis; -[assembly: SuppressMessage("Design", "CA1034:Nested types should not be visible")] -[assembly: SuppressMessage("Design", "CA1052:Static holder types should be Static or NotInheritable")] -[assembly: SuppressMessage("Design", "CA1031:Do not catch general exception types")] +[assembly: SuppressMessage("Design", "CA1034")] +[assembly: SuppressMessage("Design", "CA1052")] +[assembly: SuppressMessage("Design", "CA1031")] -[assembly: SuppressMessage("Style", "IDE0058:Expression value is never used")] -[assembly: SuppressMessage("Style", "IDE0025:Use expression body for properties")] -[assembly: SuppressMessage("Style", "IDE0060:Remove unused parameter")] -[assembly: SuppressMessage("Style", "IDE0044:Add readonly modifier")] -[assembly: SuppressMessage("Style", "IDE0062:")] -[assembly: SuppressMessage("Style", "IDE0059:Unnecessary assignment of a value")] +[assembly: SuppressMessage("Style", "IDE0058")] +[assembly: SuppressMessage("Style", "IDE0025")] +[assembly: SuppressMessage("Style", "IDE0060")] +[assembly: SuppressMessage("Style", "IDE0044")] +[assembly: SuppressMessage("Style", "IDE0062")] +[assembly: SuppressMessage("Style", "IDE0059")] -[assembly: SuppressMessage("Usage", "CA2211:Non-constant fields should not be visible")] +[assembly: SuppressMessage("Usage", "CA2211")] -[assembly: SuppressMessage("CodeQuality", "IDE0051:Remove unused private members")] +[assembly: SuppressMessage("CodeQuality", "IDE0051")] -[assembly: SuppressMessage("Performance", "CA1822:Mark members as static")] -[assembly: SuppressMessage("Performance", "CA1806:Do not ignore method results")] +[assembly: SuppressMessage("Performance", "CA1822")] +[assembly: SuppressMessage("Performance", "CA1806")] -[assembly: SuppressMessage("", "CS0649:")] +[assembly: SuppressMessage("", "CS0649")] +[assembly: SuppressMessage("", "IDE0251")] diff --git a/Harmony/Documentation/examples/execution_with.cs b/Harmony/Documentation/examples/execution_with.cs index 46083ea3..ba1e6f9c 100644 --- a/Harmony/Documentation/examples/execution_with.cs +++ b/Harmony/Documentation/examples/execution_with.cs @@ -36,7 +36,7 @@ static R ReplacementMethod(T optionalThisArgument /*, ... arguments ... */ ) ex = EditFinalizer(ex, ref result); finalized = true; - if (ex is object) throw ex; + if (ex is not null) throw ex; return result; } catch (Exception e) @@ -61,7 +61,7 @@ static R ReplacementMethod(T optionalThisArgument /*, ... arguments ... */ ) else { // alternative 2: at least one non-void finalizer - if (ex is object) throw ex; + if (ex is not null) throw ex; } return result; diff --git a/Harmony/Extras/FastAccess.cs b/Harmony/Extras/FastAccess.cs index 49a3d1d8..b746fc5d 100644 --- a/Harmony/Extras/FastAccess.cs +++ b/Harmony/Extras/FastAccess.cs @@ -110,11 +110,11 @@ public static GetterHandler CreateFieldGetter(params string[] names) foreach (var name in names) { var field = typeof(T).GetField(name, AccessTools.all); - if (field is object) + if (field is not null) return CreateGetterHandler(field); var property = typeof(T).GetProperty(name, AccessTools.all); - if (property is object) + if (property is not null) return CreateGetterHandler(property); } diff --git a/Harmony/ForwardingAttributes/Mono.Cecil.Cil.cs b/Harmony/ForwardingAttributes/Mono.Cecil.Cil.cs new file mode 100644 index 00000000..deb0a665 --- /dev/null +++ b/Harmony/ForwardingAttributes/Mono.Cecil.Cil.cs @@ -0,0 +1,45 @@ +#if NETFRAMEWORK || NETSTANDARD2_0 +using System.Runtime.CompilerServices; + +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.Code))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.ConstantDebugInformation))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.CustomDebugInformation))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.CustomDebugInformationKind))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.DebugInformation))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.Document))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.DocumentHashAlgorithm))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.DocumentLanguage))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.DocumentLanguageVendor))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.DocumentType))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.ExceptionHandler))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.ExceptionHandlerType))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.FlowControl))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.ILProcessor))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.ImageDebugDirectory))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.ImageDebugHeader))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.ImageDebugHeaderEntry))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.ImageDebugType))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.ImportDebugInformation))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.ImportTarget))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.ImportTargetKind))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.Instruction))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.InstructionOffset))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.ISymbolReader))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.ISymbolReaderProvider))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.ISymbolWriter))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.ISymbolWriterProvider))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.MethodBody))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.MethodDebugInformation))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.OpCode))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.OpCodeType))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.OperandType))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.ScopeDebugInformation))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.SequencePoint))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.StackBehaviour))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.SymbolsNotFoundException))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.SymbolsNotMatchingException))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.VariableAttributes))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.VariableDebugInformation))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.VariableDefinition))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Cil.VariableReference))] +#endif diff --git a/Harmony/ForwardingAttributes/Mono.Cecil.Mdb.cs b/Harmony/ForwardingAttributes/Mono.Cecil.Mdb.cs new file mode 100644 index 00000000..f1b5a9ef --- /dev/null +++ b/Harmony/ForwardingAttributes/Mono.Cecil.Mdb.cs @@ -0,0 +1,5 @@ +#if NETFRAMEWORK || NETSTANDARD2_0 +using System.Runtime.CompilerServices; + +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Mdb.MdbReader))] +#endif diff --git a/Harmony/ForwardingAttributes/Mono.Cecil.Pdb.cs b/Harmony/ForwardingAttributes/Mono.Cecil.Pdb.cs new file mode 100644 index 00000000..f1a97474 --- /dev/null +++ b/Harmony/ForwardingAttributes/Mono.Cecil.Pdb.cs @@ -0,0 +1,6 @@ +#if NETFRAMEWORK || NETSTANDARD2_0 +using System.Runtime.CompilerServices; + +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Pdb.NativePdbReader))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Pdb.NativePdbWriter))] +#endif diff --git a/Harmony/ForwardingAttributes/Mono.Cecil.Rocks.cs b/Harmony/ForwardingAttributes/Mono.Cecil.Rocks.cs new file mode 100644 index 00000000..6b1f49b7 --- /dev/null +++ b/Harmony/ForwardingAttributes/Mono.Cecil.Rocks.cs @@ -0,0 +1,8 @@ +#if NETFRAMEWORK || NETSTANDARD2_0 +using System.Runtime.CompilerServices; + +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Rocks.IILVisitor))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Rocks.ILParser))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Rocks.ModuleDefinitionRocks))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Rocks.TypeDefinitionRocks))] +#endif diff --git a/Harmony/ForwardingAttributes/Mono.Cecil.cs b/Harmony/ForwardingAttributes/Mono.Cecil.cs new file mode 100644 index 00000000..7234828e --- /dev/null +++ b/Harmony/ForwardingAttributes/Mono.Cecil.cs @@ -0,0 +1,85 @@ +#if NETFRAMEWORK || NETSTANDARD2_0 +using System.Runtime.CompilerServices; + +[assembly: TypeForwardedTo(typeof(Mono.Cecil.AssemblyAttributes))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.AssemblyDefinition))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.AssemblyHashAlgorithm))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.AssemblyNameDefinition))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.AssemblyNameReference))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.AssemblyResolutionException))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.CallSite))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.CustomAttribute))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.CustomAttributeArgument))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.CustomAttributeNamedArgument))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.EventAttributes))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.EventDefinition))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.EventReference))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.ExportedType))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.FieldAttributes))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.FieldDefinition))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.FieldReference))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.GenericParameter))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.GenericParameterAttributes))] +#if NET472 +[assembly: TypeForwardedTo(typeof(Mono.Cecil.GenericParameterConstraint))] +#endif +[assembly: TypeForwardedTo(typeof(Mono.Cecil.GenericParameterType))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.IAssemblyResolver))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.ICustomAttributeProvider))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.IGenericParameterProvider))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.IMemberDefinition))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.IMetadataImporter))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.IMetadataImporterProvider))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.IMetadataResolver))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.IMetadataScope))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.IMetadataTokenProvider))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.IMethodSignature))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.InterfaceImplementation))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.IReflectionImporter))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.IReflectionImporterProvider))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.ManifestResourceAttributes))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.MarshalInfo))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.MemberReference))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.MetadataKind))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.MetadataScopeType))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.MetadataToken))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.MetadataType))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.MethodAttributes))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.MethodCallingConvention))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.MethodDefinition))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.MethodImplAttributes))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.MethodReference))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.MethodReturnType))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.MethodSemanticsAttributes))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.ModuleAttributes))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.ModuleCharacteristics))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.ModuleDefinition))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.ModuleKind))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.ModuleParameters))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.ModuleReference))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.NativeType))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.ParameterAttributes))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.ParameterDefinition))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.ParameterReference))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.PInvokeAttributes))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.PInvokeInfo))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.PropertyAttributes))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.PropertyDefinition))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.PropertyReference))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.ReaderParameters))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.ReadingMode))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.ResolutionException))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.Resource))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.ResourceType))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.SecurityAction))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.SecurityAttribute))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.SecurityDeclaration))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.TargetArchitecture))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.TargetRuntime))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.TokenType))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.TypeAttributes))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.TypeDefinition))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.TypeReference))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.TypeSystem))] +[assembly: TypeForwardedTo(typeof(Mono.Cecil.WriterParameters))] +#endif diff --git a/Harmony/ForwardingAttributes/Mono.Collections.Generic.cs b/Harmony/ForwardingAttributes/Mono.Collections.Generic.cs new file mode 100644 index 00000000..f4e63491 --- /dev/null +++ b/Harmony/ForwardingAttributes/Mono.Collections.Generic.cs @@ -0,0 +1,5 @@ +#if NETFRAMEWORK || NETSTANDARD2_0 +using System.Runtime.CompilerServices; + +[assembly: TypeForwardedTo(typeof(Mono.Collections.Generic.Collection<>))] +#endif diff --git a/Harmony/ForwardingAttributes/Mono.CompilerServices.SymbolWriter.cs b/Harmony/ForwardingAttributes/Mono.CompilerServices.SymbolWriter.cs new file mode 100644 index 00000000..41936421 --- /dev/null +++ b/Harmony/ForwardingAttributes/Mono.CompilerServices.SymbolWriter.cs @@ -0,0 +1,18 @@ +#if NETFRAMEWORK || NETSTANDARD2_0 +using System.Runtime.CompilerServices; + +[assembly: TypeForwardedTo(typeof(Mono.CompilerServices.SymbolWriter.AnonymousScopeEntry))] +[assembly: TypeForwardedTo(typeof(Mono.CompilerServices.SymbolWriter.CapturedScope))] +[assembly: TypeForwardedTo(typeof(Mono.CompilerServices.SymbolWriter.CapturedVariable))] +[assembly: TypeForwardedTo(typeof(Mono.CompilerServices.SymbolWriter.CodeBlockEntry))] +[assembly: TypeForwardedTo(typeof(Mono.CompilerServices.SymbolWriter.CompileUnitEntry))] +[assembly: TypeForwardedTo(typeof(Mono.CompilerServices.SymbolWriter.LineNumberEntry))] +[assembly: TypeForwardedTo(typeof(Mono.CompilerServices.SymbolWriter.LineNumberTable))] +[assembly: TypeForwardedTo(typeof(Mono.CompilerServices.SymbolWriter.LocalVariableEntry))] +[assembly: TypeForwardedTo(typeof(Mono.CompilerServices.SymbolWriter.MethodEntry))] +[assembly: TypeForwardedTo(typeof(Mono.CompilerServices.SymbolWriter.MonoSymbolFile))] +[assembly: TypeForwardedTo(typeof(Mono.CompilerServices.SymbolWriter.NamespaceEntry))] +[assembly: TypeForwardedTo(typeof(Mono.CompilerServices.SymbolWriter.OffsetTable))] +[assembly: TypeForwardedTo(typeof(Mono.CompilerServices.SymbolWriter.ScopeVariable))] +[assembly: TypeForwardedTo(typeof(Mono.CompilerServices.SymbolWriter.SourceFileEntry))] +#endif diff --git a/Harmony/ForwardingAttributes/MonoMod.Utils.Cil.cs b/Harmony/ForwardingAttributes/MonoMod.Utils.Cil.cs new file mode 100644 index 00000000..1df2a7e3 --- /dev/null +++ b/Harmony/ForwardingAttributes/MonoMod.Utils.Cil.cs @@ -0,0 +1,6 @@ +#if NETFRAMEWORK || NETSTANDARD2_0 +using System.Runtime.CompilerServices; + +[assembly: TypeForwardedTo(typeof(MonoMod.Utils.Cil.CecilILGenerator))] +[assembly: TypeForwardedTo(typeof(MonoMod.Utils.Cil.ILGeneratorShim))] +#endif diff --git a/Harmony/ForwardingAttributes/MonoMod.Utils.cs b/Harmony/ForwardingAttributes/MonoMod.Utils.cs new file mode 100644 index 00000000..11755aff --- /dev/null +++ b/Harmony/ForwardingAttributes/MonoMod.Utils.cs @@ -0,0 +1,11 @@ +#if NETFRAMEWORK || NETSTANDARD2_0 +using System.Runtime.CompilerServices; + +[assembly: TypeForwardedTo(typeof(MonoMod.Utils.DMDEmitDynamicMethodGenerator))] +[assembly: TypeForwardedTo(typeof(MonoMod.Utils.DMDGenerator<>))] +[assembly: TypeForwardedTo(typeof(MonoMod.Utils.DynamicMethodDefinition))] +[assembly: TypeForwardedTo(typeof(MonoMod.Utils.Extensions))] +[assembly: TypeForwardedTo(typeof(MonoMod.Utils.ICallSiteGenerator))] +[assembly: TypeForwardedTo(typeof(MonoMod.Utils.ReflectionHelper))] +[assembly: TypeForwardedTo(typeof(MonoMod.Utils.Relinker))] +#endif diff --git a/Harmony/GlobalSuppressions.cs b/Harmony/GlobalSuppressions.cs index 5c488251..847e4bec 100644 --- a/Harmony/GlobalSuppressions.cs +++ b/Harmony/GlobalSuppressions.cs @@ -1,11 +1,21 @@ using System.Diagnostics.CodeAnalysis; -[assembly: SuppressMessage("Performance", "CA1813:Avoid unsealed attributes")] -[assembly: SuppressMessage("Performance", "CA1810:Initialize reference type static fields inline")] -[assembly: SuppressMessage("Performance", "CA1822:Mark members as static")] -[assembly: SuppressMessage("Design", "CA1031:Do not catch general exception types")] -[assembly: SuppressMessage("Design", "CA1018:Mark attributes with AttributeUsageAttribute")] -[assembly: SuppressMessage("", "CA1825")] - -[assembly: SuppressMessage("Code Quality", "IDE0051")] -[assembly: SuppressMessage("Code Quality", "IDE0057")] +[assembly: SuppressMessage("Performance", "CA1813")] +[assembly: SuppressMessage("Performance", "CA1810")] +[assembly: SuppressMessage("Performance", "CA1822")] +[assembly: SuppressMessage("Performance", "CA1825")] + +[assembly: SuppressMessage("Design", "CA1031")] +[assembly: SuppressMessage("Design", "CA1018")] + +[assembly: SuppressMessage("CodeQuality", "IDE0051")] +[assembly: SuppressMessage("CodeQuality", "IDE0057")] +[assembly: SuppressMessage("CodeQuality", "IDE0079")] + +[assembly: SuppressMessage("", "IDE0251")] +[assembly: SuppressMessage("Style", "IDE0270")] +[assembly: SuppressMessage("Usage", "CA2211")] +[assembly: SuppressMessage("GeneratedRegex", "SYSLIB1045")] + +[assembly: SuppressMessage("Reliability", "CA2020:Prevent from behavioral change", Justification = "", Scope = "member", Target = "~M:HarmonyLib.FileLog.LogBytes(System.Int64,System.Int32)")] +[assembly: SuppressMessage("Performance", "CA1850:Prefer static 'HashData' method over 'ComputeHash'", Justification = "", Scope = "member", Target = "~M:HarmonyLib.FileLog.LogBytes(System.Int64,System.Int32)")] diff --git a/Harmony/Harmony.csproj b/Harmony/Harmony.csproj index da39c6e5..c2098c80 100644 --- a/Harmony/Harmony.csproj +++ b/Harmony/Harmony.csproj @@ -1,7 +1,7 @@ - net35;net45;net472;net48;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0 + netstandard2.0;net35;net452;net472;net48;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0;net7.0 true Harmony Andreas Pardeike @@ -11,13 +11,11 @@ Andreas Pardeike 0Harmony true - $(HarmonyVersion) LICENSE + README.md https://github.com/pardeike/Harmony false Harmony,Mono,Patch,Patching,Runtime,Detour,Detours,Aspect,Aspects - $(HarmonyVersion) - $(HarmonyVersion) HarmonyLogo.png https://raw.githubusercontent.com/pardeike/Harmony/master/HarmonyLogo.png true @@ -27,11 +25,17 @@ $(DefaultItemExcludes);Documentation/** false $(NoWarn);SYSLIB0011 + $(HarmonyVersion) + $(HarmonyVersion) + $(HarmonyVersion) + $(HarmonyVersion)$(HarmonyPrerelease) + $(HarmonyVersion)$(HarmonyPrerelease) + $(NoWarn);NU5131 - + true @@ -42,7 +46,7 @@ - + - - - - true - - - - - - false - true - - - - - true - false - - - - - - - false - false - false - - - - + @@ -115,21 +89,35 @@ - - - all - - + - + + - - + + + + false + + true + + $(TargetsForTfmSpecificContentInPackage);AddRefAssemblyToPackage + + + + + + + + + ref/netstandard2.0 + + + ref/netstandard2.0 + + + @@ -140,32 +128,6 @@ - - - - /Library/Frameworks/Mono.framework/Versions/Current/lib:$(HOME)/lib:/usr/local/lib:/lib:/usr/lib - "$(MSBuildToolsPath)\MSBuild.exe" - "$(DOTNET_HOST_PATH)" msbuild - "-p:TargetFramework=$(TargetFramework);Configuration=$(Configuration);DoILRepack=true" -t:ILRepack - - - - $(MSBuildThisFileDirectory)bin\$(Configuration) diff --git a/Harmony/Internal/CodeTranspiler.cs b/Harmony/Internal/CodeTranspiler.cs index 27389b59..14adb97e 100644 --- a/Harmony/Internal/CodeTranspiler.cs +++ b/Harmony/Internal/CodeTranspiler.cs @@ -10,12 +10,10 @@ namespace HarmonyLib internal class CodeTranspiler { readonly IEnumerable codeInstructions; - readonly bool argumentShift; readonly List transpilers = new(); - internal CodeTranspiler(List ilInstructions, bool argumentShift) + internal CodeTranspiler(List ilInstructions) { - this.argumentShift = argumentShift; codeInstructions = ilInstructions .Select(ilInstruction => ilInstruction.GetCodeInstruction()) .ToList().AsEnumerable(); @@ -68,7 +66,7 @@ internal static bool ShouldAddExceptionInfo(object op, int opIndex, List var isStartBlock = blocks.FirstOrDefault(block => block.blockType != ExceptionBlockType.EndExceptionBlock); var isEndBlock = blocks.FirstOrDefault(block => block.blockType == ExceptionBlockType.EndExceptionBlock); - if (isStartBlock is object && isEndBlock is null) + if (isStartBlock is not null && isEndBlock is null) { var pairInstruction = originalInstructions.Skip(originalIndex + 1).FirstOrDefault(instr => { @@ -79,7 +77,7 @@ internal static bool ShouldAddExceptionInfo(object op, int opIndex, List blocks = blocksObject as List; return blocks.Any(); }); - if (pairInstruction is object) + if (pairInstruction is not null) { var pairStart = originalIndex + 1; var pairEnd = pairStart + originalInstructions.Skip(pairStart).ToList().IndexOf(pairInstruction) - 1; @@ -96,7 +94,7 @@ internal static bool ShouldAddExceptionInfo(object op, int opIndex, List blocks = blocksObject as List; return blocks.Any(); }); - if (pairInstruction is object) + if (pairInstruction is not null) { pairStart = opIndex + 1; pairEnd = pairStart + newInstructions.Skip(opIndex + 1).ToList().IndexOf(pairInstruction) - 1; @@ -106,7 +104,7 @@ internal static bool ShouldAddExceptionInfo(object op, int opIndex, List } } } - if (isStartBlock is null && isEndBlock is object) + if (isStartBlock is null && isEndBlock is not null) { var pairInstruction = originalInstructions.GetRange(0, originalIndex).LastOrDefault(instr => { @@ -117,7 +115,7 @@ internal static bool ShouldAddExceptionInfo(object op, int opIndex, List blocks = blocksObject as List; return blocks.Any(); }); - if (pairInstruction is object) + if (pairInstruction is not null) { var pairStart = originalInstructions.GetRange(0, originalIndex).LastIndexOf(pairInstruction); var pairEnd = originalIndex; @@ -134,7 +132,7 @@ internal static bool ShouldAddExceptionInfo(object op, int opIndex, List blocks = blocksObject as List; return blocks.Any(); }); - if (pairInstruction is object) + if (pairInstruction is not null) { pairStart = newInstructions.GetRange(0, opIndex).LastIndexOf(pairInstruction); pairEnd = opIndex; @@ -237,7 +235,7 @@ internal List GetResult(ILGenerator generator, MethodBase metho // remember the order of the original input (for detection of dupped code instructions) List originalInstructions = null; - if (unassignedValues is object) + if (unassignedValues is not null) originalInstructions = instructions.Cast().ToList(); // call the transpiler @@ -247,14 +245,11 @@ internal List GetResult(ILGenerator generator, MethodBase metho instructions = newInstructions; // convert result back to 'our' CodeInstruction and re-assign otherwise lost fields - if (unassignedValues is object) + if (unassignedValues is not null) instructions = ConvertToOurInstructions(instructions, typeof(CodeInstruction), originalInstructions, unassignedValues); }); - var result = instructions as List ?? instructions.Cast().ToList(); - if (argumentShift) - StructReturnBuffer.ArgumentShifter(result, method.IsStatic && AccessTools.IsMonoRuntime); - return result; + return instructions as List ?? instructions.Cast().ToList(); } // diff --git a/Harmony/Internal/Emitter.cs b/Harmony/Internal/Emitter.cs index d2aa4cb9..b626e7ce 100644 --- a/Harmony/Internal/Emitter.cs +++ b/Harmony/Internal/Emitter.cs @@ -99,7 +99,7 @@ internal static string FormatArgument(object argument, string extra = null) var type = argument.GetType(); if (argument is MethodBase method) - return method.FullDescription() + (extra is object ? " " + extra : ""); + return method.FullDescription() + (extra is not null ? " " + extra : ""); if (argument is FieldInfo field) return $"{field.FieldType.FullDescription()} {field.DeclaringType.FullDescription()}::{field.Name}"; @@ -351,7 +351,7 @@ internal void Emit(OpCode opcode, long arg) internal void EmitCall(OpCode opcode, MethodInfo methodInfo, Type[] optionalParameterTypes) { instructions.Add(CurrentPos(), new CodeInstruction(opcode, methodInfo)); - var extra = optionalParameterTypes is object && optionalParameterTypes.Length > 0 ? optionalParameterTypes.Description() : null; + var extra = optionalParameterTypes is not null && optionalParameterTypes.Length > 0 ? optionalParameterTypes.Description() : null; LogIL(opcode, methodInfo, extra); il.EmitCall(opcode, methodInfo, optionalParameterTypes); } diff --git a/Harmony/Internal/HarmonySharedState.cs b/Harmony/Internal/HarmonySharedState.cs index b25666c3..d632e764 100644 --- a/Harmony/Internal/HarmonySharedState.cs +++ b/Harmony/Internal/HarmonySharedState.cs @@ -1,12 +1,10 @@ using Mono.Cecil; -using MonoMod.RuntimeDetour; using MonoMod.Utils; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; -using System.Runtime.CompilerServices; namespace HarmonyLib { @@ -39,9 +37,6 @@ internal static class HarmonySharedState // state/originals/methodStarts are set to instances stored in the global dynamic types static fields with the same name static readonly Dictionary state; static readonly Dictionary originals; - // maps the native start of the method to the method itself - static readonly Dictionary methodStarts; - static bool methodStartsInvalidated; internal static readonly int actualVersion; @@ -73,30 +68,6 @@ static HarmonySharedState() originals = new Dictionary(); if (originalsField != null) // may not exist in older versions originals = (Dictionary)originalsField.GetValue(null); - - // create 'methodStarts' based on the value(s) in 'originals' - methodStarts = new Dictionary(); - RefreshMethodStarts(); - - // newer .NET versions can re-jit methods so we need to patch them after that happens - DetourHelper.Runtime.OnMethodCompiled += (MethodBase method, IntPtr codeStart, ulong codeLen) => - { - if (method == null) return; - var info = GetPatchInfo(method); - if (info == null) return; - PatchFunctions.UpdateRecompiledMethod(method, codeStart, info); - methodStartsInvalidated = true; - }; - } - - private static void RefreshMethodStarts() { - lock (originals) { - methodStarts.Clear(); - foreach ( var original in originals.Keys ) { - methodStarts.Add(original.GetNativeStart().ToInt64(), original); - } - } - methodStartsInvalidated = false; } // creates a dynamic 'global' type if it does not exist @@ -149,7 +120,6 @@ internal static void UpdatePatchInfo(MethodBase original, MethodInfo replacement var bytes = patchInfo.Serialize(); lock (state) state[original] = bytes; lock (originals) originals[replacement] = original; - lock (methodStarts) methodStarts[replacement.GetNativeStart().ToInt64()] = replacement; } internal static MethodBase GetOriginal(MethodInfo replacement) @@ -157,36 +127,11 @@ internal static MethodBase GetOriginal(MethodInfo replacement) lock (originals) return originals.GetValueSafe(replacement); } - static readonly FieldInfo methodAddress = typeof(StackFrame).GetField("methodAddress", BindingFlags.Instance | BindingFlags.NonPublic); internal static MethodBase FindReplacement(StackFrame frame) { - var frameMethod = frame.GetMethod(); - var methodStart = 0L; - - if (frameMethod is null || frameMethod.IsGenericMethod) - { - if (methodAddress == null) return null; - methodStart = (long)methodAddress.GetValue(frame); - } - else - { - var baseMethod = DetourHelper.Runtime.GetIdentifiable(frameMethod); - methodStart = baseMethod.GetNativeStart().ToInt64(); - } - - // Failed to find any usable method, returning a null frameMethod means we could not find any method from the stacktrace - if (methodStart == 0) - return frameMethod; - - lock (methodStarts) { - if (methodStartsInvalidated) { - RefreshMethodStarts(); - } - - return methodStarts.TryGetValue(methodStart, out var originalMethod) - ? originalMethod - : frameMethod; - } + var method = frame.GetMethod() as MethodInfo; + if (method == null) return null; + return GetOriginal(method); } } } diff --git a/Harmony/Internal/Memory.cs b/Harmony/Internal/Memory.cs deleted file mode 100644 index e8fba763..00000000 --- a/Harmony/Internal/Memory.cs +++ /dev/null @@ -1,141 +0,0 @@ -using MonoMod.RuntimeDetour; -using MonoMod.Utils; -using System; -using System.Reflection; -using System.Reflection.Emit; -using System.Runtime.CompilerServices; - -namespace HarmonyLib -{ - /// A low level memory helper - /// - public static class Memory - { - /// Mark method for no inlining (currently only works on Mono) - /// The method/constructor to change - /// - public static unsafe void MarkForNoInlining(MethodBase method) - { - // TODO for now, this only works on mono - if (AccessTools.IsMonoRuntime) - { - var iflags = (ushort*)(method.MethodHandle.Value) + 1; - *iflags |= (ushort)MethodImplOptions.NoInlining; - } - } - - /// Detours a method - /// The original method/constructor - /// The replacement method/constructor - /// An error string - /// - public static string DetourMethod(MethodBase original, MethodBase replacement) - { - var originalCodeStart = GetMethodStart(original, out var exception); - if (originalCodeStart == 0) - return exception.Message; - - PadShortMethods(original); - - var patchCodeStart = GetMethodStart(replacement, out exception); - if (patchCodeStart == 0) - return exception.Message; - - return WriteJump(originalCodeStart, patchCodeStart); - } - - internal static void DetourCompiledMethod(IntPtr originalCodeStart, MethodBase replacement) - { - var patchCodeStart = GetMethodStart(replacement, out var exception); - if (patchCodeStart != 0 && exception == null) - _ = WriteJump((long)originalCodeStart, patchCodeStart); - } - - internal static void DetourMethodAndPersist(MethodBase original, MethodBase replacement) - { - var errorString = DetourMethod(original, replacement); - if (errorString is object) - throw new FormatException($"Method {original.FullDescription()} cannot be patched. Reason: {errorString}"); - PatchTools.RememberObject(original, replacement); - } - - /* - * Fix for detour jump overriding the method that's right next in memory - * See https://github.com/MonoMod/MonoMod.Common/blob/58702d64645aba613ad16275c0b78278ff0d2055/RuntimeDetour/Platforms/Native/DetourNativeX86Platform.cs#L77 - * - * It happens for any very small method, not just virtual, but it just so happens that - * virtual methods are usually the only empty ones. The problem is with the detour code - * overriding the method that's right next in memory. - * - * The 64bit absolute jump detour requires 14 bytes but on Linux an empty method is just - * 10 bytes. On Windows, due to prologue differences, an empty method is exactly 14 bytes - * as required. - * - * Now, the small code size wouldn't be a problem if it wasn't for the way Mono compiles - * trampolines. Usually methods on x64 are 16 bytes aligned, so no actual code could get - * overriden by the detour, but trampolines don't follow this rule and a trampoline generated - * for the dynamic method from the patch is placed right after the method being detoured. - * - * The detour code then overrides the beggining of the trampoline and that leads to a - * segfault on execution. - * - * There's also the fact that Linux seems to allocate the detour code far away in memory - * so it uses the 64 bit jump in the first place. On Windows with Mono usually the 32 bit - * smaller jumps suffice. - * - * The fix changes the order in which methods are JITted so that no trampoline is placed - * after the detoured method (or at least the trampoline that causes this specific crash) - */ - internal static void PadShortMethods(MethodBase method) - { - if (Tools.isWindows) return; - var count = method.GetMethodBody()?.GetILAsByteArray()?.Length ?? 0; - if (count == 0) return; - - // the 16 here is arbitrary but high enough to prevent the jitted code from getting under 14 bytes - // and high enough to not generate too many fix methods - if (count >= 16) return; - - var methodDef = new DynamicMethodDefinition($"PadMethod-{Guid.NewGuid()}", typeof(void), new Type[0]); - methodDef.GetILGenerator().Emit(OpCodes.Ret); - - // invoke the method so that it generates a trampoline that will later get overridden by the detour code - _ = methodDef.Generate().Invoke(null, null); - } - - /// Writes a jump to memory - /// The memory address - /// Jump destination - /// An error string - /// - public static string WriteJump(long memory, long destination) - { - var data = DetourHelper.Native.Create((IntPtr)memory, (IntPtr)destination); - DetourHelper.Native.MakeWritable(data); - DetourHelper.Native.Apply(data); - DetourHelper.Native.MakeExecutable(data); - DetourHelper.Native.FlushICache(data); - DetourHelper.Native.Free(data); - return null; - } - - /// Gets the start of a method in memory - /// The method/constructor - /// [out] Details of the exception - /// The method start address - /// - public static long GetMethodStart(MethodBase method, out Exception exception) - { - try - { - exception = null; - return method.Pin().GetNativeStart().ToInt64(); - } - catch (Exception e) - { - exception = e; - return 0; - } - } - } -} diff --git a/Harmony/Internal/MethodCopier.cs b/Harmony/Internal/MethodCopier.cs index 24b440d6..ccbf48b4 100644 --- a/Harmony/Internal/MethodCopier.cs +++ b/Harmony/Internal/MethodCopier.cs @@ -29,11 +29,6 @@ internal void SetDebugging(bool debug) reader.SetDebugging(debug); } - internal void SetArgumentShift(bool useShift) - { - reader.SetArgumentShift(useShift); - } - internal void AddTranspiler(MethodInfo transpiler) { transpilers.Add(transpiler); @@ -52,12 +47,10 @@ internal static List GetInstructions(ILGenerator generator, Met throw new ArgumentNullException(nameof(method)); var originalVariables = MethodPatcher.DeclareLocalVariables(generator, method); - var useStructReturnBuffer = StructReturnBuffer.NeedsFix(method); var copier = new MethodCopier(method, generator, originalVariables); - copier.SetArgumentShift(useStructReturnBuffer); var info = Harmony.GetPatchInfo(method); - if (info is object) + if (info is not null) { var sortedTranspilers = PatchFunctions.GetSortedPatchMethods(method, info.Transpilers.ToArray(), false); for (var i = 0; i < maxTranspilers && i < sortedTranspilers.Count; i++) @@ -73,7 +66,6 @@ internal class MethodBodyReader readonly ILGenerator generator; readonly MethodBase method; bool debug = false; - bool argumentShift = false; readonly Module module; readonly Type[] typeArguments; @@ -119,7 +111,7 @@ internal MethodBodyReader(MethodBase method, ILGenerator generator) var type = method.DeclaringType; - if (type is object && type.IsGenericType) + if (type is not null && type.IsGenericType) { try { typeArguments = type.GetGenericArguments(); } catch { typeArguments = null; } @@ -144,11 +136,6 @@ internal void SetDebugging(bool debug) this.debug = debug; } - internal void SetArgumentShift(bool argumentShift) - { - this.argumentShift = argumentShift; - } - internal void GenerateInstructions() { while (ilBytes.position < ilBytes.buffer.Length) @@ -232,7 +219,7 @@ internal void HandleNativeMethod() internal void DeclareVariables(LocalBuilder[] existingVariables) { if (generator is null) return; - if (existingVariables is object) + if (existingVariables is not null) variables = existingVariables; else variables = localVariables.Select(lvi => generator.DeclareLocal(lvi.LocalType, lvi.IsPinned)).ToArray(); @@ -342,7 +329,7 @@ internal List FinalizeILCodes(Emitter emitter, List case OperandType.InlineSwitch: { var targets = ilInstruction.operand as ILInstruction[]; - if (targets is object) + if (targets is not null) { var labels = new List