From b4a7a9ffe82a8aab9a7fc910eb37dd86332df5b9 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Tue, 1 Jun 2021 07:21:18 +0200 Subject: [PATCH 1/9] [tests] Re-enable Mac Catalyst tests related to the GC not working. (#11752) This seems to be working again now. --- tests/monotouch-test/CoreAnimation/LayerTest.cs | 3 --- tests/monotouch-test/ObjCRuntime/RegistrarTest.cs | 3 --- tests/monotouch-test/mono/WeakReferenceTest.cs | 3 --- 3 files changed, 9 deletions(-) diff --git a/tests/monotouch-test/CoreAnimation/LayerTest.cs b/tests/monotouch-test/CoreAnimation/LayerTest.cs index 8a30942b5a82..d83bf2e91129 100644 --- a/tests/monotouch-test/CoreAnimation/LayerTest.cs +++ b/tests/monotouch-test/CoreAnimation/LayerTest.cs @@ -107,9 +107,6 @@ public void AddAnimation () static int TextLayersDisposed; static int Generation; [Test] -#if __MACCATALYST__ - [Ignore ("https://github.com/dotnet/runtime/issues/47407")] // The GC doesn't collect objects with finalizers -#endif public void TestBug26532() { TextLayersDisposed = 0; diff --git a/tests/monotouch-test/ObjCRuntime/RegistrarTest.cs b/tests/monotouch-test/ObjCRuntime/RegistrarTest.cs index fe33af14fb5e..38426f12042e 100644 --- a/tests/monotouch-test/ObjCRuntime/RegistrarTest.cs +++ b/tests/monotouch-test/ObjCRuntime/RegistrarTest.cs @@ -2033,9 +2033,6 @@ public int M2 (int v) } } -#if __MACCATALYST__ - [Ignore ("https://github.com/dotnet/runtime/issues/47407")] // The GC doesn't collect objects with finalizers -#endif [Test] public void BlockCollection () { diff --git a/tests/monotouch-test/mono/WeakReferenceTest.cs b/tests/monotouch-test/mono/WeakReferenceTest.cs index 6335e6be0ca5..2c79593a4b3f 100644 --- a/tests/monotouch-test/mono/WeakReferenceTest.cs +++ b/tests/monotouch-test/mono/WeakReferenceTest.cs @@ -37,9 +37,6 @@ public void Setup () TestRuntime.AssertSystemVersion (PlatformName.MacOSX, 10, 9, throwIfOtherPlatform: false); } -#if __MACCATALYST__ - [Ignore ("https://github.com/dotnet/runtime/issues/47407")] // The GC doesn't collect objects with finalizers -#endif [Test] public void NoRetainCyclesExpectedTest () { From 1b98f4ec9e6c79a993ee81f7d6e01fbc4165df2e Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Tue, 1 Jun 2021 07:35:29 +0200 Subject: [PATCH 2/9] [runtime] Release the block_wrapper_queue and xamarin_wrapper_hash dictionaries upon process exit. (#11751) While not strictly necessary to not leak (because the process is exiting anyway), it makes it easier to read leak reports, because these dictionaries won't show up as leaked memory anymore. Before: There were 258096 MonoObjects created, 258015 MonoObjects freed, so 81 were not freed. (dynamic registrar) There were 205834 MonoObjects created, 205833 MonoObjects freed, so 1 were not freed. (static registrar) After: There were 258104 MonoObjects created, 258025 MonoObjects freed, so 79 were not freed. (dynamic registrar) There were 205834 MonoObjects created, 205834 MonoObjects freed, so no leaked MonoObjects. (static registrar) --- runtime/monotouch-main.m | 2 ++ runtime/runtime.m | 16 ++++++++++++++++ runtime/xamarin/runtime.h | 1 + 3 files changed, 19 insertions(+) diff --git a/runtime/monotouch-main.m b/runtime/monotouch-main.m index d0c0a2d55abe..0a9a0c2cc46f 100644 --- a/runtime/monotouch-main.m +++ b/runtime/monotouch-main.m @@ -495,6 +495,8 @@ - (void) memoryWarning: (NSNotification *) sender xamarin_mono_object_release (&assembly); + xamarin_release_static_dictionaries (); + xamarin_bridge_shutdown (); return rv; diff --git a/runtime/runtime.m b/runtime/runtime.m index 0163bbdaf5dd..c7728faebd63 100644 --- a/runtime/runtime.m +++ b/runtime/runtime.m @@ -2070,6 +2070,22 @@ -(void) xamarinSetFlags: (enum XamarinGCHandleFlags) flags; return rv; } +void +xamarin_release_static_dictionaries () +{ +#if defined (CORECLR_RUNTIME) + // Release static dictionaries of cached objects. If we end up trying to + // add objects to these dictionaries after this point (on a background + // thread), the dictionaries will be re-created (and leak) - which + // shouldn't be a problem, because at this point the process is about to + // exit anyway. + pthread_mutex_lock (&wrapper_hash_lock); + xamarin_mono_object_release (&block_wrapper_queue); + xamarin_mono_object_release (&xamarin_wrapper_hash); + pthread_mutex_unlock (&wrapper_hash_lock); +#endif +} + void xamarin_set_use_sgen (bool value) { diff --git a/runtime/xamarin/runtime.h b/runtime/xamarin/runtime.h index a67df5d83ed6..8b1fd409223a 100644 --- a/runtime/xamarin/runtime.h +++ b/runtime/xamarin/runtime.h @@ -230,6 +230,7 @@ bool xamarin_set_gchandle_with_flags_safe (id self, GCHandle gchandle, enum Xa void xamarin_create_gchandle (id self, void *managed_object, enum XamarinGCHandleFlags flags, bool force_weak); void xamarin_release_managed_ref (id self, bool user_type); void xamarin_notify_dealloc (id self, GCHandle gchandle); +void xamarin_release_static_dictionaries (); int xamarin_main (int argc, char *argv[], enum XamarinLaunchMode launch_mode); From 03685e70b869af0013f2fb19b68aedbf14909cfc Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Tue, 1 Jun 2021 07:36:01 +0200 Subject: [PATCH 3/9] [static registrar] Release the return value from xamarin_get_reflection_method_method in generated code. (#11748) * If the return value from xamarin_get_reflection_method_method is cached in a static variable, we can only release at process exist. * Otherwise just release at the end of the current method. Before: There were 258096 MonoObjects created, 246948 MonoObjects freed, so 11148 were not freed. (dynamic registrar) There were 205834 MonoObjects created, 205214 MonoObjects freed, so 620 were not freed. (static registrar) After: There were 258092 MonoObjects created, 246945 MonoObjects freed, so 11147 were not freed. (dynamic registrar) There were 205834 MonoObjects created, 205600 MonoObjects freed, so 234 were not freed. (static registrar) --- runtime/coreclr-bridge.m | 30 ++++++++++++++++++++++++++++-- runtime/xamarin/runtime.h | 2 ++ tools/common/StaticRegistrar.cs | 7 +++++++ 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/runtime/coreclr-bridge.m b/runtime/coreclr-bridge.m index 1ec00ec69a43..2b7b915ad5b0 100644 --- a/runtime/coreclr-bridge.m +++ b/runtime/coreclr-bridge.m @@ -9,9 +9,11 @@ #if defined (CORECLR_RUNTIME) #include +#include #include "product.h" #include "runtime-internal.h" +#include "slinked-list.h" #include "xamarin/xamarin.h" #include "xamarin/coreclr-bridge.h" @@ -19,6 +21,8 @@ unsigned int coreclr_domainId = 0; void *coreclr_handle = NULL; +pthread_mutex_t monoobject_lock = PTHREAD_MUTEX_INITIALIZER; +SList *release_at_exit = NULL; // A list of MonoObject*s to be released at process exit #if defined (TRACK_MONOOBJECTS) @@ -30,12 +34,10 @@ // MONOOBJECT_TRACKING_WITH_STACKTRACES environment variable. #include -#include static int _Atomic monoobject_created = 0; static int _Atomic monoobject_destroyed = 0; static CFMutableDictionaryRef monoobject_dict = NULL; -static pthread_mutex_t monoobject_lock = PTHREAD_MUTEX_INITIALIZER; struct monoobject_tracked_entry { char *managed; @@ -171,6 +173,22 @@ void xamarin_bridge_shutdown () { + SList *list; + + // Free our list of MonoObject*s to free at process exist. + // No need to keep the lock locked while we traverse the list, the only thing we need to protect + // are reads and writes to the 'release_at_exit' variable, so let's do just that. + pthread_mutex_lock (&monoobject_lock); + list = release_at_exit; + release_at_exit = NULL; + pthread_mutex_unlock (&monoobject_lock); + + while (list) { + xamarin_mono_object_release ((MonoObject **) &list->data); + list = list->next; + } + s_list_free (list); + #if defined (TRACK_MONOOBJECTS) xamarin_bridge_dump_monoobjects (); #endif @@ -357,6 +375,14 @@ *mobj_ref = NULL; } +void +xamarin_mono_object_release_at_process_exit (MonoObject *mobj) +{ + pthread_mutex_lock (&monoobject_lock); + release_at_exit = s_list_prepend (release_at_exit, mobj); + pthread_mutex_unlock (&monoobject_lock); +} + /* Implementation of the Mono Embedding API */ // returns a retained MonoAssembly * diff --git a/runtime/xamarin/runtime.h b/runtime/xamarin/runtime.h index 8b1fd409223a..3d4ed6ed8f2e 100644 --- a/runtime/xamarin/runtime.h +++ b/runtime/xamarin/runtime.h @@ -307,10 +307,12 @@ void xamarin_mono_object_retain (MonoObject *mobj); // Use C++ linking to be able to use method overloading, so that callers don't have to cast their variables to 'MonoObject**' (which improves type safety a lot). extern "C++" void xamarin_mono_object_release (MonoObject **mobj); extern "C++" void xamarin_mono_object_release (MonoString **mobj); +void xamarin_mono_object_release_at_process_exit (MonoObject *mobj); #else // Nothing to do here. #define xamarin_mono_object_retain(x) #define xamarin_mono_object_release(x) do { *x = NULL; } while (0); +#define xamarin_mono_object_release_at_process_exit(x) #endif diff --git a/tools/common/StaticRegistrar.cs b/tools/common/StaticRegistrar.cs index cd9492d37a14..6a25a66a8e4a 100644 --- a/tools/common/StaticRegistrar.cs +++ b/tools/common/StaticRegistrar.cs @@ -4002,6 +4002,13 @@ void Specialize (AutoIndentStringBuilder sb, ObjCMethod method, List body.WriteLine ("managed_method = xamarin_get_reflection_method_method (reflection_method);"); if (merge_bodies) body.WriteLine ("*managed_method_ptr = managed_method;"); + + // If the managed_method instance is stored in a static variable, we can't release it until process exit. + if (merge_bodies || !isGeneric) { + body.WriteLine ("xamarin_mono_object_release_at_process_exit (managed_method);"); + } else { + cleanup.AppendLine ("xamarin_mono_object_release (&managed_method);"); + } body.WriteLine ("}"); From 1e1e0298bd61d89560a8668e48af8ab6bb1f4ed8 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Tue, 1 Jun 2021 13:09:43 +0200 Subject: [PATCH 4/9] [runtime] Don't forget to free the method field in MonoMethodSignatures. (#11746) Before: There were 258096 MonoObjects created, 246948 MonoObjects freed, so 11148 were not freed. (dynamic registrar) There were 205834 MonoObjects created, 205214 MonoObjects freed, so 620 were not freed. (static registrar) After: There were 205834 MonoObjects created, 205222 MonoObjects freed, so 612 were not freed. (dynamic registrar) There were 258100 MonoObjects created, 258019 MonoObjects freed, so 81 were not freed. (static registrar) --- runtime/coreclr-bridge.m | 1 + 1 file changed, 1 insertion(+) diff --git a/runtime/coreclr-bridge.m b/runtime/coreclr-bridge.m index 2b7b915ad5b0..3a5cc5628057 100644 --- a/runtime/coreclr-bridge.m +++ b/runtime/coreclr-bridge.m @@ -693,6 +693,7 @@ if (sig == NULL) return; + xamarin_mono_object_release (&sig->method); for (int i = 0; i < sig->parameter_count; i++) { xamarin_mono_object_release (&sig->parameters [i]); } From 50dfaf535c0ec109995ad6701a329793e7124cb8 Mon Sep 17 00:00:00 2001 From: Sebastien Pouliot Date: Tue, 1 Jun 2021 09:08:27 -0400 Subject: [PATCH 5/9] [generator] Use `is` instead of `==` when doing null checks (#11754) In most cases this will generate the exact same IL [1]. However it will perform _better_ (like you expect) if the `==` operator is overloaded (even more if the operator implementation is buggy). A last, small benefit is that avoiding `==` means the linker is more likely to be able to remove it from the final applications. This PR only change the generated code. IOW not the generator code, nor the manual bindings. Those should also be updated but requires more work. References: [1] https://gist.github.com/spouliot/fb05e733e1f9f403de69ab3ab6bdac2b [2] https://www.thomasclaudiushuber.com/2020/03/19/c-why-you-should-prefer-the-is-keyword-over-the-operator/ --- src/NativeTypes/Drawing.tt | 4 +-- src/NativeTypes/Primitives.tt | 4 +-- src/generator-enums.cs | 4 +-- src/generator-filters.cs | 4 +-- src/generator.cs | 66 +++++++++++++++++------------------ src/mapkit.cs | 2 +- src/safariservices.cs | 2 +- src/uikit.cs | 6 ++-- 8 files changed, 46 insertions(+), 46 deletions(-) diff --git a/src/NativeTypes/Drawing.tt b/src/NativeTypes/Drawing.tt index 1487ba241e02..ea5e957b1936 100644 --- a/src/NativeTypes/Drawing.tt +++ b/src/NativeTypes/Drawing.tt @@ -165,7 +165,7 @@ namespace CoreGraphics #if !COREBUILD public static bool TryParse (NSDictionary dictionaryRepresentation, out <#= type.Name #> <#= type.ArgName #>) { - if (dictionaryRepresentation == null){ + if (dictionaryRepresentation is null) { <#= type.ArgName #> = Empty; return false; } @@ -597,7 +597,7 @@ namespace CoreGraphics #if !COREBUILD public static bool TryParse (NSDictionary dictionaryRepresentation, out CGRect rect) { - if (dictionaryRepresentation == null){ + if (dictionaryRepresentation is null) { rect = Empty; return false; } diff --git a/src/NativeTypes/Primitives.tt b/src/NativeTypes/Primitives.tt index ad763022e201..9f66ee02d72a 100644 --- a/src/NativeTypes/Primitives.tt +++ b/src/NativeTypes/Primitives.tt @@ -393,7 +393,7 @@ namespace System { if (source == IntPtr.Zero) throw new ArgumentNullException ("source"); - if (destination == null) + if (destination is null) throw new ArgumentNullException ("destination"); if (destination.Rank != 1) throw new ArgumentException ("destination", "array is multi-dimensional"); @@ -410,7 +410,7 @@ namespace System public static void CopyArray (<#= type.NSName #> [] source, int startIndex, IntPtr destination, int length) { - if (source == null) + if (source is null) throw new ArgumentNullException ("source"); if (destination == IntPtr.Zero) throw new ArgumentNullException ("destination"); diff --git a/src/generator-enums.cs b/src/generator-enums.cs index c068124ed244..619ca47635d0 100644 --- a/src/generator-enums.cs +++ b/src/generator-enums.cs @@ -118,7 +118,7 @@ void GenerateEnum (Type type) print ("public static NSString? GetDomain (this {0} self)", type.Name); print ("{"); indent++; - print ("if (_domain == null)"); + print ("if (_domain is null)"); indent++; print ("_domain = Dlfcn.GetStringConstant (Libraries.{0}.Handle, \"{1}\");", library_name, error.ErrorDomain); indent--; @@ -191,7 +191,7 @@ void GenerateEnum (Type type) print ("public static {0} GetValue (NSString{1} constant)", type.Name, nullable ? "?" : ""); print ("{"); indent++; - print ("if (constant == null)"); + print ("if (constant is null)"); indent++; // if we do not have a enum value that maps to a null field then we throw if (!nullable) diff --git a/src/generator-filters.cs b/src/generator-filters.cs index 40ca38548190..f4f958fc9c30 100644 --- a/src/generator-filters.cs +++ b/src/generator-filters.cs @@ -84,7 +84,7 @@ public void GenerateFilter (Type type) print ("public {0} (NSCoder coder) : base (NSObjectFlag.Empty)", type_name); print ("{"); indent++; - print ("if (coder == null)"); + print ("if (coder is null)"); indent++; print ("throw new ArgumentNullException (nameof (coder));"); indent--; @@ -359,7 +359,7 @@ void GenerateFilterSetter (string propertyType, string propertyName) indent--; break; case "CIVector[]": - print ("if (value == null) {"); + print ("if (value is null) {"); indent++; print ($"SetHandle (\"{propertyName}\", IntPtr.Zero);"); indent--; diff --git a/src/generator.cs b/src/generator.cs index a76423efafca..bd0b84ef85ed 100644 --- a/src/generator.cs +++ b/src/generator.cs @@ -1377,10 +1377,10 @@ string GetToBindAsWrapper (MethodInfo mi, MemberInformation minfo = null, Parame var isEnum = retType.IsEnum; var parameterName = pi != null ? pi.Name.GetSafeParamName () : "value"; var denullify = isNullable ? ".Value" : string.Empty; - var nullCheck = isNullable ? $"{parameterName} == null ? null : " : string.Empty; + var nullCheck = isNullable ? $"{parameterName} is null ? null : " : string.Empty; if (isNullable || !isValueType) - temp = string.Format ("{0} == null ? null : ", parameterName); + temp = string.Format ("{0} is null ? null : ", parameterName); if (originalType == TypeManager.NSNumber) { var enumCast = isEnum ? $"(int)" : string.Empty; @@ -1397,7 +1397,7 @@ string GetToBindAsWrapper (MethodInfo mi, MemberInformation minfo = null, Parame } temp = string.Format ("{3}NSValue.From{0} ({2}{1});", typeStr, denullify, parameterName, nullCheck); } else if (originalType == TypeManager.NSString && IsSmartEnum (retType)) { - temp = isNullable ? $"{parameterName} == null ? null : " : string.Empty; + temp = isNullable ? $"{parameterName} is null ? null : " : string.Empty; temp += $"{FormatType (retType.DeclaringType, retType)}Extensions.GetConstant ({parameterName}{denullify});"; } else if (originalType.IsArray && originalType.GetArrayRank () == 1) { if (!retType.IsArray) { @@ -1726,7 +1726,7 @@ public TrampolineInfo MakeTrampoline (Type t) var refname = $"__xamarin_pref{pi.Position}"; convert.Append ($"var {refname} = Runtime.GetINativeObject<{RenderType (nt)}> ({safe_name}, false);"); pars.Append ($"ref IntPtr {safe_name}"); - postConvert.Append ($"{safe_name} = {refname} == null ? IntPtr.Zero : {refname}.Handle;"); + postConvert.Append ($"{safe_name} = {refname} is null ? IntPtr.Zero : {refname}.Handle;"); invoke.Append ($"ref {refname}"); continue; } @@ -1820,9 +1820,9 @@ public string MarshalParameter (MethodInfo mi, ParameterInfo pi, bool null_allow } if (HasBindAsAttribute (pi)) - return string.Format ("nsb_{0} == null ? IntPtr.Zero : nsb_{0}.Handle", pi.Name); + return string.Format ("nsb_{0} is null ? IntPtr.Zero : nsb_{0}.Handle", pi.Name); if (propInfo != null && HasBindAsAttribute (propInfo)) - return string.Format ("nsb_{0} == null ? IntPtr.Zero : nsb_{0}.Handle", propInfo.Name); + return string.Format ("nsb_{0} is null ? IntPtr.Zero : nsb_{0}.Handle", propInfo.Name); var safe_name = pi.Name.GetSafeParamName (); @@ -1847,7 +1847,7 @@ public string MarshalParameter (MethodInfo mi, ParameterInfo pi, bool null_allow if (mai.ZeroCopyStringMarshal){ if (allow_null) - return String.Format ("{0} == null ? IntPtr.Zero : (IntPtr)(&_s{0})", pi.Name); + return String.Format ("{0} is null ? IntPtr.Zero : (IntPtr)(&_s{0})", pi.Name); else return String.Format ("(IntPtr)(&_s{0})", pi.Name); } else { @@ -1870,7 +1870,7 @@ public string MarshalParameter (MethodInfo mi, ParameterInfo pi, bool null_allow //Type etype = pi.ParameterType.GetElementType (); if (null_allowed_override || AttributeManager.HasAttribute (pi)) - return String.Format ("nsa_{0} == null ? IntPtr.Zero : nsa_{0}.Handle", pi.Name); + return String.Format ("nsa_{0} is null ? IntPtr.Zero : nsa_{0}.Handle", pi.Name); return "nsa_" + pi.Name + ".Handle"; } @@ -1892,13 +1892,13 @@ public string MarshalParameter (MethodInfo mi, ParameterInfo pi, bool null_allow if (IsDictionaryContainerType(pi.ParameterType)){ if (null_allowed_override || AttributeManager.HasAttribute (pi)) - return String.Format ("{0} == null ? IntPtr.Zero : {0}.Dictionary.Handle", safe_name); + return String.Format ("{0} is null ? IntPtr.Zero : {0}.Dictionary.Handle", safe_name); return safe_name + ".Dictionary.Handle"; } if (pi.ParameterType.IsGenericParameter) { if (null_allowed_override || AttributeManager.HasAttribute (pi)) - return string.Format ("{0} == null ? IntPtr.Zero : {0}.Handle", safe_name); + return string.Format ("{0} is null ? IntPtr.Zero : {0}.Handle", safe_name); return safe_name + ".Handle"; } @@ -3021,7 +3021,7 @@ void GenerateEventArgsFile () } // [NullAllowed] on `UserInfo` requires a check for every case print ("var userinfo = Notification.UserInfo;"); - print ("if (userinfo == null)"); + print ("if (userinfo is null)"); indent++; if (probe_presence) print ("return false;"); @@ -4063,7 +4063,7 @@ public string GenerateMarshalString (bool probe_null, bool must_copy) "_s{0}.ClassPtr = ObjCRuntime.NSStringStruct.ReferencePtr;\n" + "_s{0}.Flags = 0x010007d1; // RefCount=1, Unicode, InlineContents = 0, DontFreeContents\n" + "_s{0}.UnicodePtr = _p{0};\n" + - "_s{0}.Length = " + (probe_null ? "{1} == null ? 0 : {1}.Length;" : "{1}.Length;\n"); + "_s{0}.Length = " + (probe_null ? "{1} is null ? 0 : {1}.Length;" : "{1}.Length;\n"); } public string GenerateDisposeString (bool probe_null, bool must_copy) @@ -4191,7 +4191,7 @@ void GenerateTypeLowering (MethodInfo mi, bool null_allowed_override, EnumMode e disposes.AppendFormat ("\nnsb_{0}?.Dispose ();", propInfo.Name); } else if (etype == TypeManager.System_String) { if (null_allowed_override || AttributeManager.HasAttribute (pi)) { - convs.AppendFormat ("var nsa_{0} = {1} == null ? null : NSArray.FromStrings ({1});\n", pi.Name, pi.Name.GetSafeParamName ()); + convs.AppendFormat ("var nsa_{0} = {1} is null ? null : NSArray.FromStrings ({1});\n", pi.Name, pi.Name.GetSafeParamName ()); disposes.AppendFormat ("if (nsa_{0} != null)\n\tnsa_{0}.Dispose ();\n", pi.Name); } else { convs.AppendFormat ("var nsa_{0} = NSArray.FromStrings ({1});\n", pi.Name, pi.Name.GetSafeParamName ()); @@ -4201,7 +4201,7 @@ void GenerateTypeLowering (MethodInfo mi, bool null_allowed_override, EnumMode e exceptions.Add (ErrorHelper.CreateError (1065, mai.Type.FullName, string.IsNullOrEmpty (pi.Name) ? $"#{pi.Position}" : pi.Name, mi.DeclaringType.FullName, mi.Name)); } else { if (null_allowed_override || AttributeManager.HasAttribute (pi)) { - convs.AppendFormat ("var nsa_{0} = {1} == null ? null : NSArray.FromNSObjects ({1});\n", pi.Name, pi.Name.GetSafeParamName ()); + convs.AppendFormat ("var nsa_{0} = {1} is null ? null : NSArray.FromNSObjects ({1});\n", pi.Name, pi.Name.GetSafeParamName ()); disposes.AppendFormat ("if (nsa_{0} != null)\n\tnsa_{0}.Dispose ();\n", pi.Name); } else { convs.AppendFormat ("var nsa_{0} = NSArray.FromNSObjects ({1});\n", pi.Name, pi.Name.GetSafeParamName ()); @@ -4216,7 +4216,7 @@ void GenerateTypeLowering (MethodInfo mi, bool null_allowed_override, EnumMode e convs.AppendFormat ("BlockLiteral *block_ptr_{0};\n", pi.Name); convs.AppendFormat ("BlockLiteral block_{0};\n", pi.Name); if (null_allowed){ - convs.AppendFormat ("if ({0} == null){{\n", pi.Name.GetSafeParamName ()); + convs.AppendFormat ("if ({0} is null){{\n", pi.Name.GetSafeParamName ()); convs.AppendFormat ("\tblock_ptr_{0} = null;\n", pi.Name); convs.AppendFormat ("}} else {{\n"); extra = "\t"; @@ -4277,12 +4277,12 @@ void GenerateTypeLowering (MethodInfo mi, bool null_allowed_override, EnumMode e by_ref_init.AppendFormat ("IntPtr {0}OriginalValue = {0}Value;\n", pi.Name.GetSafeParamName ()); } else if (isArrayOfNSObject || isArrayOfINativeObjectSubclass) { by_ref_init.Insert (0, string.Format ("NSArray {0}ArrayValue = NSArray.FromNSObjects ({0});\n", pi.Name.GetSafeParamName ())); - by_ref_init.AppendFormat ("{0}ArrayValue == null ? IntPtr.Zero : {0}ArrayValue.Handle;\n", pi.Name.GetSafeParamName ()); + by_ref_init.AppendFormat ("{0}ArrayValue is null ? IntPtr.Zero : {0}ArrayValue.Handle;\n", pi.Name.GetSafeParamName ()); } else if (isArrayOfString) { - by_ref_init.Insert (0, string.Format ("NSArray {0}ArrayValue = {0} == null ? null : NSArray.FromStrings ({0});\n", pi.Name.GetSafeParamName ())); - by_ref_init.AppendFormat ("{0}ArrayValue == null ? IntPtr.Zero : {0}ArrayValue.Handle;\n", pi.Name.GetSafeParamName ()); + by_ref_init.Insert (0, string.Format ("NSArray {0}ArrayValue = {0} is null ? null : NSArray.FromStrings ({0});\n", pi.Name.GetSafeParamName ())); + by_ref_init.AppendFormat ("{0}ArrayValue is null ? IntPtr.Zero : {0}ArrayValue.Handle;\n", pi.Name.GetSafeParamName ()); } else if (isNSObject || isINativeObjectSubclass) { - by_ref_init.AppendFormat ("{0} == null ? IntPtr.Zero : {0}.Handle;\n", pi.Name.GetSafeParamName ()); + by_ref_init.AppendFormat ("{0} is null ? IntPtr.Zero : {0}.Handle;\n", pi.Name.GetSafeParamName ()); } else { throw ErrorHelper.CreateError (88, mai.Type, mi); } @@ -4294,7 +4294,7 @@ void GenerateTypeLowering (MethodInfo mi, bool null_allowed_override, EnumMode e by_ref_processing.AppendFormat ("{0} = NSString.FromHandle ({0}Value);\n", pi.Name.GetSafeParamName ()); } else if (isArray) { if (!pi.IsOut) - by_ref_processing.AppendFormat ("if ({0}Value != ({0}ArrayValue == null ? IntPtr.Zero : {0}ArrayValue.Handle))\n\t", pi.Name.GetSafeParamName ()); + by_ref_processing.AppendFormat ("if ({0}Value != ({0}ArrayValue is null ? IntPtr.Zero : {0}ArrayValue.Handle))\n\t", pi.Name.GetSafeParamName ()); if (isArrayOfNSObject || isArrayOfINativeObjectSubclass) { by_ref_processing.AppendFormat ("{0} = NSArray.ArrayFromHandle<{1}> ({0}Value);\n", pi.Name.GetSafeParamName (), RenderType (elementType.GetElementType ())); @@ -4310,7 +4310,7 @@ void GenerateTypeLowering (MethodInfo mi, bool null_allowed_override, EnumMode e by_ref_processing.AppendFormat ("{0} = Runtime.GetNSObject<{1}> ({0}Value);\n", pi.Name.GetSafeParamName (), RenderType (elementType)); } else if (isINativeObjectSubclass) { if (!pi.IsOut) - by_ref_processing.AppendFormat ("if ({0}Value != ({0} == null ? IntPtr.Zero : {0}.Handle))\n\t", pi.Name.GetSafeParamName ()); + by_ref_processing.AppendFormat ("if ({0}Value != ({0} is null ? IntPtr.Zero : {0}.Handle))\n\t", pi.Name.GetSafeParamName ()); by_ref_processing.AppendFormat ("{0} = Runtime.GetINativeObject<{1}> ({0}Value, {2}, {3});\n", pi.Name.GetSafeParamName (), RenderType (elementType), isForcedType ? "true" : "false", isForcedType ? isForcedOwns : "false"); } else { throw ErrorHelper.CreateError (88, mai.Type, mi); @@ -4354,7 +4354,7 @@ void GenerateArgumentChecks (MethodInfo mi, bool null_allowed_override, Property print ($"var {safe_name}__handle__ = {safe_name}.GetHandle ();"); } } else if (needs_null_check) { - print ("if ({0} == null)", safe_name); + print ("if ({0} is null)", safe_name); print ("\tObjCRuntime.ThrowHelper.ThrowArgumentNullException (nameof ({0}));", safe_name); } } @@ -4886,7 +4886,7 @@ void GenerateProperty (Type type, PropertyInfo pi, List instance_fields_ if (IsDictionaryContainerType (pi.PropertyType)) { print ("var src = {0} != null ? new NSMutableDictionary ({0}) : null;", wrap); - print ("return src == null ? null! : new {0}(src);", FormatType (pi.DeclaringType, pi.PropertyType)); + print ("return src is null ? null! : new {0}(src);", FormatType (pi.DeclaringType, pi.PropertyType)); } else { if (IsArrayOfWrappedType (pi.PropertyType)) print ("return NSArray.FromArray<{0}>({1} as NSArray);", FormatType (pi.DeclaringType, pi.PropertyType.GetElementType ()), wrap); @@ -4908,7 +4908,7 @@ void GenerateProperty (Type type, PropertyInfo pi, List instance_fields_ if (minfo.protocolize || is_protocol_wrapper){ print ("var rvalue = value as NSObject;"); - print ("if (value != null && rvalue == null)"); + print ("if (!(value is null) && rvalue is null)"); print ("\tthrow new ArgumentException (\"The object passed of type \" + value.GetType () + \" does not derive from NSObject\");"); } @@ -6912,19 +6912,19 @@ public void Generate (Type type) print ("get {"); indent++; if (field_pi.PropertyType == TypeManager.NSString){ - print ("if (_{0} == null)", field_pi.Name); + print ("if (_{0} is null)", field_pi.Name); indent++; print ("_{0} = Dlfcn.GetStringConstant (Libraries.{2}.Handle, \"{1}\");", field_pi.Name, fieldAttr.SymbolName, library_name); indent--; print ("return _{0};", field_pi.Name); } else if (field_pi.PropertyType.Name == "NSArray"){ - print ("if (_{0} == null)", field_pi.Name); + print ("if (_{0} is null)", field_pi.Name); indent++; print ("_{0} = Runtime.GetNSObject (Dlfcn.GetIndirect (Libraries.{2}.Handle, \"{1}\"));", field_pi.Name, fieldAttr.SymbolName, library_name); indent--; print ("return _{0};", field_pi.Name); } else if (field_pi.PropertyType.Name == "UTType") { - print ("if (_{0} == null)", field_pi.Name); + print ("if (_{0} is null)", field_pi.Name); indent++; print ("_{0} = Runtime.GetNSObject (Dlfcn.GetIntPtr (Libraries.{2}.Handle, \"{1}\"));", field_pi.Name, fieldAttr.SymbolName, library_name); indent--; @@ -6964,7 +6964,7 @@ public void Generate (Type type) } else if (field_pi.PropertyType.IsEnum) { var btype = field_pi.PropertyType.GetEnumUnderlyingType (); if (smartEnumTypeName != null) { - print ("if (_{0} == null)", field_pi.Name); + print ("if (_{0} is null)", field_pi.Name); indent++; print ("_{0} = Dlfcn.GetStringConstant (Libraries.{2}.Handle, \"{1}\");", field_pi.Name, fieldAttr.SymbolName, library_name); indent--; @@ -7146,14 +7146,14 @@ public void Generate (Type type) print ("var del = {1} as _{0};", dtype.Name, delName); - print ("if (del == null){"); + print ("if (del is null){"); indent++; if (!hasKeepRefUntil) print ("del = (_{0}){1} ();", dtype.Name, delegateCreationMethodName); else { string oref = "new object[] {\"oref\"}"; print ("del = (_{0}){1} ({2});", dtype.Name, delegateCreationMethodName, oref); - print ("if (instances == null) instances = new System.Collections.ArrayList ();"); + print ("if (instances is null) instances = new System.Collections.ArrayList ();"); print ("if (!instances.Contains (this)) instances.Add (this);"); } print ("{0} = (I{1})del;", delName, dtype.Name); @@ -7163,10 +7163,10 @@ public void Generate (Type type) } else { print ("var del = {0};", delName); - print ("if (del == null || (!(del is _{0}))){{", dtype.Name); + print ("if (del is null || (!(del is _{0}))){{", dtype.Name); print ("\tdel = new _{0} ({1});", dtype.Name, bta.KeepRefUntil == null ? "" : "oref"); if (hasKeepRefUntil) { - print ("\tif (instances == null) instances = new System.Collections.ArrayList ();"); + print ("\tif (instances is null) instances = new System.Collections.ArrayList ();"); print ("\tif (!instances.Contains (this)) instances.Add (this);"); } print ("\t{0} = del;", delName); @@ -7333,7 +7333,7 @@ public void Generate (Type type) print ("public override bool RespondsToSelector (Selector? sel)"); print ("{"); ++indent; - print ("if (sel == null)"); + print ("if (sel is null)"); ++indent; print ("return false;"); --indent; diff --git a/src/mapkit.cs b/src/mapkit.cs index 2cde75de89a2..57b3d72d1c7a 100644 --- a/src/mapkit.cs +++ b/src/mapkit.cs @@ -492,7 +492,7 @@ interface MKMapView { void Register ([NullAllowed] Class viewClass, string identifier); [TV (11,0)][iOS (11,0)][Mac (10,13)] - [Wrap ("Register (viewType == null ? null : new Class (viewType), identifier)")] + [Wrap ("Register (viewType is null ? null : new Class (viewType), identifier)")] void Register ([NullAllowed] Type viewType, string identifier); [Export ("selectAnnotation:animated:")] diff --git a/src/safariservices.cs b/src/safariservices.cs index e0fc186a6f21..412c6e9c6dba 100644 --- a/src/safariservices.cs +++ b/src/safariservices.cs @@ -58,7 +58,7 @@ partial interface SSReadingList { [Static, Export ("supportsURL:")] // Apple says it's __nonnull so let's be safe and maintain compatibility with our current behaviour - [PreSnippet ("if (url == null) return false;")] + [PreSnippet ("if (url is null) return false;")] bool SupportsUrl ([NullAllowed] NSUrl url); [Export ("addReadingListItemWithURL:title:previewText:error:")] diff --git a/src/uikit.cs b/src/uikit.cs index 06346ef526fc..1fe25718ce27 100644 --- a/src/uikit.cs +++ b/src/uikit.cs @@ -2435,7 +2435,7 @@ interface UIApplication { void OpenUrl (NSUrl url, UIApplicationOpenUrlOptions options, [NullAllowed] Action completion); [Export ("canOpenURL:")] - [PreSnippet ("if (url == null) return false;")] // null not really allowed (but it's a behaviour change with known bug reports) + [PreSnippet ("if (url is null) return false;")] // null not really allowed (but it's a behaviour change with known bug reports) bool CanOpenUrl ([NullAllowed] NSUrl url); [Export ("sendEvent:")] @@ -19954,7 +19954,7 @@ interface UISceneConfiguration : NSCopying, NSSecureCoding { Type SceneType { [Wrap ("Class.Lookup (SceneClass)")] get; - [Wrap ("SceneClass = value == null ? null : new Class (value)")] set; + [Wrap ("SceneClass = value is null ? null : new Class (value)")] set; } [Advice ("You can use 'DelegateType' with a 'Type' instead.")] @@ -19963,7 +19963,7 @@ Type SceneType { Type DelegateType { [Wrap ("Class.Lookup (DelegateClass)")] get; - [Wrap ("DelegateClass = value == null ? null : new Class (value)")] set; + [Wrap ("DelegateClass = value is null ? null : new Class (value)")] set; } [NullAllowed, Export ("storyboard", ArgumentSemantic.Strong)] From 3d68543d3dd90d80b2218179950f5f4038434112 Mon Sep 17 00:00:00 2001 From: Sebastien Pouliot Date: Tue, 1 Jun 2021 09:09:19 -0400 Subject: [PATCH 6/9] [catalyst][coremotion] Update xtro (#11753) The _missing_ API are for watchOS only and not available for Catalyst. --- ...MacCatalyst-CoreMotion.todo => MacCatalyst-CoreMotion.ignore} | 1 + 1 file changed, 1 insertion(+) rename tests/xtro-sharpie/{MacCatalyst-CoreMotion.todo => MacCatalyst-CoreMotion.ignore} (93%) diff --git a/tests/xtro-sharpie/MacCatalyst-CoreMotion.todo b/tests/xtro-sharpie/MacCatalyst-CoreMotion.ignore similarity index 93% rename from tests/xtro-sharpie/MacCatalyst-CoreMotion.todo rename to tests/xtro-sharpie/MacCatalyst-CoreMotion.ignore index c2e965033913..9a7889f28564 100644 --- a/tests/xtro-sharpie/MacCatalyst-CoreMotion.todo +++ b/tests/xtro-sharpie/MacCatalyst-CoreMotion.ignore @@ -1,3 +1,4 @@ +## The following types are only available on watchOS (not iOS, so definitively not Catalyst) !missing-enum! CMFallDetectionEventUserResolution not bound !missing-protocol! CMFallDetectionDelegate not bound !missing-selector! +CMFallDetectionManager::isAvailable not bound From a57e31873da1f87cb28b72903cb589e4e0e3bd6f Mon Sep 17 00:00:00 2001 From: Manuel de la Pena Date: Tue, 1 Jun 2021 09:53:02 -0400 Subject: [PATCH 7/9] [CI] Do not generate github static pages on CI. (#11720) We added the github pages to make the life of the reviews easier, the issue we found is that we have a limited amount of space. Due to that we are removing the generation from the ci. Triggers in pipleines are disable by default, removing it will stop it from being executed. The PR are triggered via a release pipeline we called macios.glue --- .../automation/publish-pr-html-results.yml | 3 --- tools/devops/automation/scripts/GitHub.psm1 | 22 ++++++++----------- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/tools/devops/automation/publish-pr-html-results.yml b/tools/devops/automation/publish-pr-html-results.yml index 06fb91057ee9..ab1b6f146765 100644 --- a/tools/devops/automation/publish-pr-html-results.yml +++ b/tools/devops/automation/publish-pr-html-results.yml @@ -22,9 +22,6 @@ resources: pipelines: - pipeline: macios source: xamarin-macios - trigger: - stages: - - build_packages variables: - group: xamops-azdev-secrets diff --git a/tools/devops/automation/scripts/GitHub.psm1 b/tools/devops/automation/scripts/GitHub.psm1 index 3fa60c48e33f..a7cc324576a0 100644 --- a/tools/devops/automation/scripts/GitHub.psm1 +++ b/tools/devops/automation/scripts/GitHub.psm1 @@ -561,21 +561,17 @@ function New-GitHubSummaryComment { } $githubPagePrefix = "https://xamarin.github.io/macios.ci" - if ([string]::IsNullOrEmpty($Env:PR_ID)) { - $githubPagePrefix = "$githubPagePrefix/ci/$Env:BUILD_SOURCEBRANCHNAME/$Env:BUILD_REVISION" - } else { - $githubPagePrefix = "$githubPagePrefix/pr/PR$Env:PR_ID" + if (-not [string]::IsNullOrEmpty($Env:PR_ID)) { + $githubPagePrefix = "$githubPagePrefix/pr/PR$Env:PR_ID/$Env:BUILD_BUILDID" + $sb.AppendLine("# GitHub pages") + $sb.AppendLine() + $sb.AppendLine("Results can be found in the following github pages (it might take some time to publish):") + $sb.AppendLine() + $sb.AppendLine("* [Test results]($githubPagePrefix/HtmlReport-sim/tests/vsdrops_index.html)") + $sb.AppendLine("* [API diff ]($githubPagePrefix/HtmlReport-sim/api-diff/api-diff.html)") + $sb.AppendLine("* [API & Generator diff]($githubPagePrefix/apicomparison/api-diff.html)") } - $githubPagePrefix = "$githubPagePrefix/$Env:BUILD_BUILDID" - $sb.AppendLine("# GitHub pages") - $sb.AppendLine() - $sb.AppendLine("Results can be found in the following github pages (it might take some time to publish):") - $sb.AppendLine() - $sb.AppendLine("* [Test results]($githubPagePrefix/HtmlReport-sim/tests/vsdrops_index.html)") - $sb.AppendLine("* [API diff ]($githubPagePrefix/HtmlReport-sim/api-diff/api-diff.html)") - $sb.AppendLine("* [API & Generator diff]($githubPagePrefix/apicomparison/api-diff.html)") - $headerLinks = $sb.ToString() $request = $null From 0864407f78fc4930dcd6353bc03ca227c4fa791d Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Tue, 1 Jun 2021 15:56:54 +0200 Subject: [PATCH 8/9] [tests] Adjust MX8029_b and MX8033 tests to cope with slightly different exception message output for CoreCLR. (#11732) * [tests] Adjust MX8029_b and MX8033 tests to cope with slightly different exception message output for CoreCLR. Fixes these unit tests: [FAIL] MX8029_b : Message Expected string length 217 but was 238. Strings differ at index 149. Expected: "...lector: setIntArray:\n\tMethod: MonoTouchFixtures.ObjCRuntim..." But was: "...lector: setIntArray:\n\tMethod: System.Void MonoTouchFixture..." ----------------------------------------------^ at MonoTouchFixtures.ObjCRuntime.RuntimeTest.MX8029_b() in /Users/rolf/work/maccore/onedotnet/xamarin-macios/tests/monotouch-test/ObjCRuntime/RuntimeTest.cs:line 625 [FAIL] MX8033 : Message Expected string length 192 but was 207. Strings differ at index 129. Expected: "...\n\tSelector: intArray\n\tMethod: MonoTouchFixtures.ObjCRuntim..." But was: "...\n\tSelector: intArray\n\tMethod: System.Int32[] MonoTouchFixt..." ------------------------------------------------^ at MonoTouchFixtures.ObjCRuntime.RuntimeTest.MX8033() in /Users/rolf/work/maccore/onedotnet/xamarin-macios/tests/monotouch-test/ObjCRuntime/RuntimeTest.cs:line 644 * There's no need to restrict the TestRuntime.IsCoreCLR method to .NET code only. The logic works just as well on legacy Xamarin as well. * Make code C# 7.3 compatible. Fixes this error: > xamarin-macios/tests/common/TestRuntime.cs(1183,46): error CS8370: Feature 'not pattern' is not available in C# 7.3. Please use language version 9.0 or greater. --- tests/common/TestRuntime.cs | 4 +-- .../monotouch-test/ObjCRuntime/RuntimeTest.cs | 28 ++++++++++++++++--- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/tests/common/TestRuntime.cs b/tests/common/TestRuntime.cs index 00fe26c5ea39..35d13981f39c 100644 --- a/tests/common/TestRuntime.cs +++ b/tests/common/TestRuntime.cs @@ -1175,14 +1175,12 @@ public static bool IsOptimizeAll { } } -#if NET // There's no official API yet for distinguishing between CoreCLR and MonoVM (https://github.com/dotnet/runtime/issues/49481) // (checking for the Mono.Runtime type doesn't work, because the BCL is the same, so there's never a Mono.Runtime type). // However, the System.__Canon type seems to be CoreCLR-only. public static bool IsCoreCLR { get { - return Type.GetType ("System.__Canon") is not null; + return !(Type.GetType ("System.__Canon") is null); } } -#endif } diff --git a/tests/monotouch-test/ObjCRuntime/RuntimeTest.cs b/tests/monotouch-test/ObjCRuntime/RuntimeTest.cs index affa1014b4ac..b148be0d4f54 100644 --- a/tests/monotouch-test/ObjCRuntime/RuntimeTest.cs +++ b/tests/monotouch-test/ObjCRuntime/RuntimeTest.cs @@ -622,11 +622,21 @@ public void MX8029_b () } } catch (RuntimeException re) { Assert.AreEqual (8029, re.Code, "Code"); - Assert.AreEqual (@"Unable to marshal the array parameter #1 whose managed type is 'System.Int32[]' to managed. + string expectedExceptionMessage; + if (TestRuntime.IsCoreCLR) { + expectedExceptionMessage = @"Unable to marshal the array parameter #1 whose managed type is 'System.Int32[]' to managed. +Additional information: + Selector: setIntArray: + Method: System.Void MonoTouchFixtures.ObjCRuntime.RuntimeTest+Dummy.SetIntArray (System.Int32[]) +"; + } else { + expectedExceptionMessage = @"Unable to marshal the array parameter #1 whose managed type is 'System.Int32[]' to managed. Additional information: Selector: setIntArray: Method: MonoTouchFixtures.ObjCRuntime.RuntimeTest/Dummy:SetIntArray (int[]) -", re.Message, "Message"); +"; + } + Assert.AreEqual (expectedExceptionMessage, re.Message, "Message"); var inner = (RuntimeException)re.InnerException; Assert.AreEqual (8031, inner.Code, "Inner Code"); Assert.AreEqual ("Unable to convert from an NSArray to a managed array of System.Int32.", inner.Message, "Inner Message"); @@ -641,11 +651,21 @@ public void MX8033 () Assert.Fail ("An exception should have been thrown"); } catch (RuntimeException re) { Assert.AreEqual (8033, re.Code, "Code"); - Assert.AreEqual (@"Unable to marshal the return value of type 'System.Int32[]' to Objective-C. + string expectedExceptionMessage; + if (TestRuntime.IsCoreCLR) { + expectedExceptionMessage = @"Unable to marshal the return value of type 'System.Int32[]' to Objective-C. +Additional information: + Selector: intArray + Method: System.Int32[] MonoTouchFixtures.ObjCRuntime.RuntimeTest+Dummy.GetIntArray () +"; + } else { + expectedExceptionMessage = @"Unable to marshal the return value of type 'System.Int32[]' to Objective-C. Additional information: Selector: intArray Method: MonoTouchFixtures.ObjCRuntime.RuntimeTest/Dummy:GetIntArray () -", re.Message, "Message"); +"; + } + Assert.AreEqual (expectedExceptionMessage, re.Message, "Message"); var inner = (RuntimeException) re.InnerException; Assert.AreEqual (8032, inner.Code, "Inner Code"); Assert.AreEqual ("Unable to convert from a managed array of System.Int32 to an NSArray.", inner.Message, "Inner Message"); From 640467a03f638131744bf34708a5b2635f0285d6 Mon Sep 17 00:00:00 2001 From: TJ Lambert <50846373+tj-devel709@users.noreply.github.com> Date: Tue, 1 Jun 2021 09:51:38 -0500 Subject: [PATCH 9/9] Updating Localization READMEs (#11738) Co-authored-by: tj_devel709 --- .../Xamarin.Localization.MSBuild/README.md | 33 ++++--------------- src/README.md | 11 +++++++ tools/mtouch/README.md | 16 +++++++++ 3 files changed, 34 insertions(+), 26 deletions(-) create mode 100644 tools/mtouch/README.md diff --git a/msbuild/Xamarin.Localization.MSBuild/README.md b/msbuild/Xamarin.Localization.MSBuild/README.md index f0e797e85479..d6cb7b2bf23a 100644 --- a/msbuild/Xamarin.Localization.MSBuild/README.md +++ b/msbuild/Xamarin.Localization.MSBuild/README.md @@ -2,34 +2,15 @@ Messages for new MSBuild error codes live in `MSBStrings.resx`. -If changes are made to `MBStrings.resx`, you will hit: +* You can now make changes to `MSBStrings.resx` in the Visual Studio for Mac IDE or from any text editor. - XliffTasks.targets(91,5): error : 'xlf\MSBStrings.cs.xlf' is out-of-date with 'MSBStrings.resx'. - Run `msbuild /t:UpdateXlf` to update .xlf files or set UpdateXlfOnBuild=true to update them on every build, - but note that it is strongly discouraged to set UpdateXlfOnBuild=true in official/CI build environments - as they should not modify source code during the build. +* If you make changes in the IDE, you should see changes automatically copy into MSBStrings.Designer.cs. Be sure to rebuild the project after making your changes. -To regenerate the `.xlf` files run: +* If you make changes from a text editor, be sure to run `make` inside the xamarin-macios/msbuild/Xamarin.Localization.MSBuild directory. - $ msbuild msbuild/Xamarin.Localization.MSBuild/Xamarin.Localization.MSBuild.csproj -restore -t:UpdateXlf +See [Localization Wiki][Localization-wiki] for more details on our localization process -For `mtouch`, `Errors.resx` contains the localizable strings. Use -these commands instead to update `.xlf` files: +or the [OneLocBuild Wiki][OneLocBuild-wiki] for information on OneLocBuild. - $ nuget restore tools - $ msbuild tools/mtouch/mtouch.csproj -t:UpdateXlf - -For `generator`, `src/Resources.resx`, contains the localizable -strings. To update the `.xlf` files: - - $ nuget restore src - $ msbuild src/generator.csproj -t:UpdateXlf - -*NOTE: `nuget restore` can be used instead of the MSBuild `-restore` -switch for projects using `packages.config`* - -See [dotnet/xliff-tasks][xliff-tasks] or [Xamarin.Android's -documentation][xamarin-android] for details. - -[xliff-tasks]: https://github.com/dotnet/xliff-tasks -[xamarin-android]: https://github.com/xamarin/xamarin-android/blob/master/Documentation/workflow/Localization.md +[Localization-wiki]: https://github.com/xamarin/maccore/wiki/Localization +[OneLocBuild-wiki]: https://ceapex.visualstudio.com/CEINTL/_wiki/wikis/CEINTL.wiki/107/Localization-with-OneLocBuild-Task diff --git a/src/README.md b/src/README.md index f40d9b414fcf..1bbdfd8889b8 100644 --- a/src/README.md +++ b/src/README.md @@ -188,3 +188,14 @@ For example, to build an API for all of iOS but only 64-bit OS X (Xamarin.Mac): ... #endif ``` + + +## Source Localization ## +Coming soon! + +See [Localization Wiki][Localization-wiki] for more details on our localization process + +or the [OneLocBuild Wiki][OneLocBuild-wiki] for information on OneLocBuild. + +[Localization-wiki]: https://github.com/xamarin/maccore/wiki/Localization +[OneLocBuild-wiki]: https://ceapex.visualstudio.com/CEINTL/_wiki/wikis/CEINTL.wiki/107/Localization-with-OneLocBuild-Task \ No newline at end of file diff --git a/tools/mtouch/README.md b/tools/mtouch/README.md new file mode 100644 index 000000000000..aa8aeeb22794 --- /dev/null +++ b/tools/mtouch/README.md @@ -0,0 +1,16 @@ +# Mtouch Localization + +Messages for new mtouch error codes live in `Errors.resx`. + +* You can now make changes to `Errors.resx` in the Visual Studio for Mac IDE or from any text editor. + +* If you make changes in the IDE, you should see changes automatically copy into Errors.Designer.cs. Be sure to rebuild the project after making your changes. + +* If you make changes from a text editor, be sure to run `make` inside the xamarin-macios/tools/mtouch directory. + +See [Localization Wiki][Localization-wiki] for more details on our localization process + +or the [OneLocBuild Wiki][OneLocBuild-wiki] for information on OneLocBuild. + +[Localization-wiki]: https://github.com/xamarin/maccore/wiki/Localization +[OneLocBuild-wiki]: https://ceapex.visualstudio.com/CEINTL/_wiki/wikis/CEINTL.wiki/107/Localization-with-OneLocBuild-Task