From 7068f4b2df94f5171e3f44e817a84e99d494cc2d Mon Sep 17 00:00:00 2001 From: Jonathan Pobst Date: Thu, 9 Sep 2021 14:11:11 -0500 Subject: [PATCH] [build] Enable string operations globalization code analyzers. (#879) Context: https://github.com/xamarin/xamarin-android/issues/6271 Context: https://developercommunity.visualstudio.com/t/XamarinAndroid-binding-compiling-proble/1477963 Context: https://www.learncroatian.eu/blog/the-croatian-letters If you attempt to build an Android Binding project on Windows within a Bosnian, Croatian, or Serbian locale, the build may break as the delegate type names created by 56955d9a may not be valid C#, e.g.: delegate IntPtr _JniMarshal_PP_Ljava/Lang/String; (IntPtr jnienv, IntPtr klass) It *should* be declaringn a `_JniMarshal_PP_L` type, *not* `_JniMarshal_PP_Ljava/Lang/String;`, the latter of which results in numerous C# errors: error CS1003: Syntax error, '(' expected error CS1001: Identifier expected error CS1001: Identifier expected error CS1003: Syntax error, ',' expected error CS1003: Syntax error, ',' expected error CS1001: Identifier expected error CS1026: ) expected The problem is caused by the interplay of two factors: 1. Commit 56955d9a uses the culture-sensitive [`string.StartsWith(string)`][0] method to determine if a JNI type name starts with `L`: if (jni_name.StartsWith ("L") || jni_name.StartsWith ("[")) return "L"; 2. In the `bs`, `hr`, and `sr` locales, the strings `Lj` and `lj` are treated as a single letter, *distinct from* `L` or `l`. In those locales, this expression is *false*, not true: "Ljava/lang/String;".StartsWith ("L") // false in bs, hr, sr; true everywhere else Additionally, this issue only arises when Java package names starting with `java` are used, e.g. `Ljava/lang/Object;`. Java types from packages that *don't* start with `java` don't encounter this bug. Fix this issue by enabling the [CA1307][1] and [CA1309][2] rules, previously disabled in commit ac914ce36. These code analysis rules require the use of string methods which use the [`StringComparison`][3] enumeration, for which we then specify `StringComparison.Ordinal`, which is *not* culture-sensitive. One complication with enabling these rules is that the .NET 6+ version of these rules are stricter and require overloads that do not exist in .NET Framework or .NET Standard to fix the violations. Enabling these rules in `.editorconfig` affects all `$(TargetFrameworkMoniker)`s; we will instead use `Directory.Build.props` to only enable them for non-.NET 6+ builds. Finally, add a new `.yaml` step that shuts down the cached `dotnet` MSBuild processes between invocations, to fix the error that has been happening on Windows - NET Core: error MSB3027: Could not copy "obj\\Release\Java.Interop.BootstrapTasks.dll" to "D:\a\1\s\bin\BuildRelease\Java.Interop.BootstrapTasks.dll". Exceeded retry count of 10. Failed. [D:\a\1\s\build-tools\Java.Interop.BootstrapTasks\Java.Interop.BootstrapTasks.csproj] error MSB3021: Unable to copy file "obj\\Release\Java.Interop.BootstrapTasks.dll" to "D:\a\1\s\bin\BuildRelease\Java.Interop.BootstrapTasks.dll". The process cannot access the file 'D:\a\1\s\bin\BuildRelease\Java.Interop.BootstrapTasks.dll' because it is being used by another process. [D:\a\1\s\build-tools\Java.Interop.BootstrapTasks\Java.Interop.BootstrapTasks.csproj] [0]: https://docs.microsoft.com/en-us/dotnet/api/system.string.startswith?view=net-5.0#System_String_StartsWith_System_String_ [1]: https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1307 [2]: https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1309 [3]: https://docs.microsoft.com/en-us/dotnet/api/system.stringcomparison?view=net-5.0 --- .editorconfig | 4 ++-- Directory.Build.props | 11 ++++++++++- build-tools/automation/templates/core-build.yaml | 7 +++++++ build-tools/jnienv-gen/Generator.cs | 8 ++++---- .../Enumification/ConstantsParser.cs | 3 ++- .../JavaCallableWrapperGenerator.cs | 2 +- .../SourceJavadocToXmldocGrammar.HtmlBnfTerms.cs | 4 ++-- .../JavaNativeTypeManager.cs | 6 +++--- .../AndroidAnnotationsSupport.cs | 2 +- src/Xamarin.Android.Tools.Bytecode/ClassPath.cs | 2 +- .../Kotlin/KotlinFixups.cs | 6 +++--- .../Kotlin/KotlinUtilities.cs | 6 +++--- src/Xamarin.SourceWriter/Models/CommentWriter.cs | 2 +- .../Java.Interop/TimingTests.cs | 2 +- .../Integration-Tests/BaseGeneratorTest.cs | 2 +- tools/generator/CodeGenerationOptions.cs | 8 ++++---- tools/generator/CodeGenerator.cs | 4 ++-- .../CodeGenerator.cs | 16 ++++++++-------- .../EnumGenerator.cs | 2 +- .../CecilApiImporter.cs | 2 +- .../ClassGen.cs | 2 +- .../Field.cs | 2 +- .../GenBase.cs | 6 +++--- .../InterfaceGen.cs | 10 +++++----- .../JavadocInfo.cs | 2 +- .../Method.cs | 16 ++++++++-------- .../MethodBase.cs | 2 +- .../Parameter.cs | 4 ++-- .../ParameterList.cs | 2 +- .../Property.cs | 2 +- .../Symbols/GeneratedEnumSymbol.cs | 2 +- .../Symbols/SymbolTable.cs | 4 ++-- .../EnumMap.cs | 14 +++++++------- .../EnumMappings.cs | 2 +- .../KotlinFixups.cs | 2 +- tools/generator/SourceWriters/BoundClass.cs | 4 ++-- tools/generator/SourceWriters/BoundInterface.cs | 4 ++-- .../generator/SourceWriters/ClassInvokerClass.cs | 2 +- .../Extensions/SourceWriterExtensions.cs | 10 +++++----- .../SourceWriters/InterfaceInvokerClass.cs | 2 +- tools/generator/Utilities/ParsedType.cs | 1 + tools/generator/Utilities/ProcessRocks.cs | 2 +- tools/generator/Utilities/TypeNameUtilities.cs | 2 +- tools/jnimarshalmethod-gen/App.cs | 2 +- tools/logcat-parse/repl.cs | 6 +++--- 45 files changed, 112 insertions(+), 94 deletions(-) diff --git a/.editorconfig b/.editorconfig index 9b646877b..c7f7ddc0e 100644 --- a/.editorconfig +++ b/.editorconfig @@ -332,9 +332,9 @@ dotnet_diagnostic.CA1200.severity = none # Avoid using cref tags with a prefix dotnet_diagnostic.CA1303.severity = none # Do not pass literals as localized parameters dotnet_diagnostic.CA1304.severity = none # Specify CultureInfo dotnet_diagnostic.CA1305.severity = none # Specify IFormatProvider -dotnet_diagnostic.CA1307.severity = none # Specify StringComparison +#dotnet_diagnostic.CA1307.severity = none # Specify StringComparison - Controlled via Directory.Build.props dotnet_diagnostic.CA1308.severity = none # Normalize strings to uppercase -dotnet_diagnostic.CA1309.severity = none # Use ordinal stringcomparison +#dotnet_diagnostic.CA1309.severity = none # Use ordinal stringcomparison - Controlled via Directory.Build.props dotnet_diagnostic.CA1401.severity = none # P/Invokes should not be visible dotnet_diagnostic.CA1417.severity = none # Do not use 'OutAttribute' on string parameters for P/Invokes dotnet_diagnostic.CA1501.severity = none # Avoid excessive inheritance diff --git a/Directory.Build.props b/Directory.Build.props index 604e4b506..913127cfd 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -40,7 +40,7 @@ False obj\ - + True @@ -85,6 +85,15 @@ <_RunJNIEnvGen Condition=" '$(JIBuildingForNetCoreApp)' != 'True' ">$(Runtime) "$(_JNIEnvGenPath)" + + + AllEnabledByDefault + $(WarningsAsErrors);CA1307;CA1309;CA1310 + + + $(NoWarn);CA1307;CA1309;CA1310 + + diff --git a/build-tools/automation/templates/core-build.yaml b/build-tools/automation/templates/core-build.yaml index 7910222a5..1f47df088 100644 --- a/build-tools/automation/templates/core-build.yaml +++ b/build-tools/automation/templates/core-build.yaml @@ -8,6 +8,13 @@ steps: projects: Java.Interop.sln arguments: '-c $(Build.Configuration) -target:Prepare -p:MaxJdkVersion=$(MaxJdkVersion)' +- task: DotNetCoreCLI@2 + displayName: Shut down existing build server + inputs: + command: custom + custom: build-server + arguments: shutdown + - task: DotNetCoreCLI@2 displayName: Build Solution inputs: diff --git a/build-tools/jnienv-gen/Generator.cs b/build-tools/jnienv-gen/Generator.cs index 41dca3d35..c0fe2786f 100644 --- a/build-tools/jnienv-gen/Generator.cs +++ b/build-tools/jnienv-gen/Generator.cs @@ -773,7 +773,7 @@ public override string[] VerifyParameter (HandleStyle style, string variable) { if (managed != "IntPtr") return new string [0]; - var variableName = variable.StartsWith ("@") + var variableName = variable.StartsWith ("@", StringComparison.Ordinal) ? variable.Substring (1) : variable; return new[] { @@ -851,7 +851,7 @@ public override string[] GetMarshalToManagedStatements (HandleStyle style, strin public override string[] VerifyParameter (HandleStyle style, string variable) { - var variableName = variable.StartsWith ("@") + var variableName = variable.StartsWith ("@", StringComparison.Ordinal) ? variable.Substring (1) : variable; return new[] { @@ -940,7 +940,7 @@ public override string GetManagedToMarshalExpression (HandleStyle style, string public override string[] VerifyParameter (HandleStyle style, string variable) { - var variableName = variable.StartsWith ("@") + var variableName = variable.StartsWith ("@", StringComparison.Ordinal) ? variable.Substring (1) : variable; switch (style) { @@ -1097,7 +1097,7 @@ public override string[] GetMarshalToManagedStatements (HandleStyle style, strin public override string[] VerifyParameter (HandleStyle style, string variable) { - var variableName = variable.StartsWith ("@") + var variableName = variable.StartsWith ("@", StringComparison.Ordinal) ? variable.Substring (1) : variable; switch (style) { diff --git a/src/Java.Interop.Tools.Generator/Enumification/ConstantsParser.cs b/src/Java.Interop.Tools.Generator/Enumification/ConstantsParser.cs index 084de35ef..ebd243e05 100644 --- a/src/Java.Interop.Tools.Generator/Enumification/ConstantsParser.cs +++ b/src/Java.Interop.Tools.Generator/Enumification/ConstantsParser.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -24,7 +25,7 @@ public static List FromEnumMapCsv (TextReader reader) // Read the enum csv file while ((s = reader.ReadLine ()) != null) { // Skip empty lines and comments - if (string.IsNullOrEmpty (s) || s.StartsWith ("//")) + if (string.IsNullOrEmpty (s) || s.StartsWith ("//", StringComparison.Ordinal)) continue; // Transient mode means remove the original field diff --git a/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/JavaCallableWrapperGenerator.cs b/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/JavaCallableWrapperGenerator.cs index 7b0cea79f..32833cb72 100644 --- a/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/JavaCallableWrapperGenerator.cs +++ b/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/JavaCallableWrapperGenerator.cs @@ -693,7 +693,7 @@ public Signature (string name, string signature, string connector, string manage Name = name; var jnisig = signature; - int closer = jnisig.IndexOf (")"); + int closer = jnisig.IndexOf (')'); string ret = jnisig.Substring (closer + 1); retval = JavaNativeTypeManager.Parse (ret).Type; string jniparms = jnisig.Substring (1, closer - 1); diff --git a/src/Java.Interop.Tools.JavaSource/Java.Interop.Tools.JavaSource/SourceJavadocToXmldocGrammar.HtmlBnfTerms.cs b/src/Java.Interop.Tools.JavaSource/Java.Interop.Tools.JavaSource/SourceJavadocToXmldocGrammar.HtmlBnfTerms.cs index 87259a1e0..f4e16b01d 100644 --- a/src/Java.Interop.Tools.JavaSource/Java.Interop.Tools.JavaSource/SourceJavadocToXmldocGrammar.HtmlBnfTerms.cs +++ b/src/Java.Interop.Tools.JavaSource/Java.Interop.Tools.JavaSource/SourceJavadocToXmldocGrammar.HtmlBnfTerms.cs @@ -112,10 +112,10 @@ static IEnumerable GetParagraphs (ParseTreeNodeList children) int len = 0; int n = -1; - if ((n = s.IndexOf (UnixParagraph, i)) >= 0) { + if ((n = s.IndexOf (UnixParagraph, i, StringComparison.Ordinal)) >= 0) { len = UnixParagraph.Length; } - else if ((n = s.IndexOf (DosParagraph, i)) >= 0) { + else if ((n = s.IndexOf (DosParagraph, i, StringComparison.Ordinal)) >= 0) { len = DosParagraph.Length; } diff --git a/src/Java.Interop.Tools.TypeNameMappings/Java.Interop.Tools.TypeNameMappings/JavaNativeTypeManager.cs b/src/Java.Interop.Tools.TypeNameMappings/Java.Interop.Tools.TypeNameMappings/JavaNativeTypeManager.cs index f6e97e82f..c8d4fa405 100644 --- a/src/Java.Interop.Tools.TypeNameMappings/Java.Interop.Tools.TypeNameMappings/JavaNativeTypeManager.cs +++ b/src/Java.Interop.Tools.TypeNameMappings/Java.Interop.Tools.TypeNameMappings/JavaNativeTypeManager.cs @@ -58,8 +58,8 @@ public static JniTypeName Parse (string jniType) public static IEnumerable FromSignature (string signature) { - if (signature.StartsWith ("(")) { - int e = signature.IndexOf (")"); + if (signature.StartsWith ("(", StringComparison.Ordinal)) { + int e = signature.IndexOf (')'); signature = signature.Substring (1, e >= 0 ? e-1 : signature.Length-1); } int i = 0; @@ -102,7 +102,7 @@ public static JniTypeName ReturnTypeFromSignature (string signature) case 'J': return new JniTypeName { Type = "long", IsKeyword = true }; case 'L': { - var e = signature.IndexOf (";", index); + var e = signature.IndexOf (';', index); if (e <= 0) throw new InvalidOperationException ("Missing reference type after 'L' at index " + i + "in: " + signature); var s = index; diff --git a/src/Xamarin.Android.Tools.AnnotationSupport/AndroidAnnotationsSupport.cs b/src/Xamarin.Android.Tools.AnnotationSupport/AndroidAnnotationsSupport.cs index 7ca0b9d05..ef6414667 100644 --- a/src/Xamarin.Android.Tools.AnnotationSupport/AndroidAnnotationsSupport.cs +++ b/src/Xamarin.Android.Tools.AnnotationSupport/AndroidAnnotationsSupport.cs @@ -67,7 +67,7 @@ static Stream FixAnnotationXML (Stream s) // them up before loading with a validating XML parser. var doc = new HtmlDocument (); doc.Load (s); - if (doc.DocumentNode.FirstChild.InnerHtml.StartsWith (" 1 && Char.IsDigit (parameterName [1]); + return parameterName.StartsWith ("p", StringComparison.Ordinal) && parameterName.Length > 1 && Char.IsDigit (parameterName [1]); } IEnumerable GetDescendants (ClassFile theClass, IList classFiles) diff --git a/src/Xamarin.Android.Tools.Bytecode/Kotlin/KotlinFixups.cs b/src/Xamarin.Android.Tools.Bytecode/Kotlin/KotlinFixups.cs index 3ae27ebf2..372c48a72 100644 --- a/src/Xamarin.Android.Tools.Bytecode/Kotlin/KotlinFixups.cs +++ b/src/Xamarin.Android.Tools.Bytecode/Kotlin/KotlinFixups.cs @@ -194,7 +194,7 @@ static void FixupExtensionMethod (MethodInfo method) // like "$this$toByteString", we change it to "obj" to be a bit nicer. var param = method.GetParameters (); - if (param.Length > 0 && param [0].Name.StartsWith ("$this$")) { + if (param.Length > 0 && param [0].Name.StartsWith ("$this$", StringComparison.Ordinal)) { Log.Debug ($"Kotlin: Renaming extension parameter {method.DeclaringType?.ThisClass.Name.Value} - {method.Name} - {param [0].Name} -> obj"); param [0].Name = "obj"; } @@ -288,7 +288,7 @@ static FieldInfo FindJavaFieldProperty (KotlinFile kotlinClass, KotlinProperty p static MethodInfo FindJavaPropertyGetter (KotlinFile kotlinClass, KotlinProperty property, ClassFile klass) { - var possible_methods = klass.Methods.Where (method => string.Compare (method.GetMethodNameWithoutSuffix (), $"get{property.Name}", true) == 0 && + var possible_methods = klass.Methods.Where (method => string.Compare (method.GetMethodNameWithoutSuffix (), $"get{property.Name}", StringComparison.OrdinalIgnoreCase) == 0 && method.GetParameters ().Length == 0 && TypesMatch (method.ReturnType, property.ReturnType, kotlinClass)); @@ -297,7 +297,7 @@ static MethodInfo FindJavaPropertyGetter (KotlinFile kotlinClass, KotlinProperty static MethodInfo FindJavaPropertySetter (KotlinFile kotlinClass, KotlinProperty property, ClassFile klass) { - var possible_methods = klass.Methods.Where (method => string.Compare (method.GetMethodNameWithoutSuffix (), $"set{property.Name}", true) == 0 && + var possible_methods = klass.Methods.Where (method => string.Compare (method.GetMethodNameWithoutSuffix (), $"set{property.Name}", StringComparison.OrdinalIgnoreCase) == 0 && property.ReturnType != null && method.GetParameters ().Length == 1 && method.ReturnType.BinaryName == "V" && diff --git a/src/Xamarin.Android.Tools.Bytecode/Kotlin/KotlinUtilities.cs b/src/Xamarin.Android.Tools.Bytecode/Kotlin/KotlinUtilities.cs index 0a8f03f37..7c4082f73 100644 --- a/src/Xamarin.Android.Tools.Bytecode/Kotlin/KotlinUtilities.cs +++ b/src/Xamarin.Android.Tools.Bytecode/Kotlin/KotlinUtilities.cs @@ -57,7 +57,7 @@ public static ParameterInfo[] GetFilteredParameters (this MethodInfo method) { // Kotlin adds this to some constructors but I cannot tell which ones, // so we'll just ignore them if we see them on the Java side - return method.GetParameters ().Where (p => p.Type.BinaryName != "Lkotlin/jvm/internal/DefaultConstructorMarker;" && !p.Name.StartsWith ("$")).ToArray (); + return method.GetParameters ().Where (p => p.Type.BinaryName != "Lkotlin/jvm/internal/DefaultConstructorMarker;" && !p.Name.StartsWith ("$", StringComparison.Ordinal)).ToArray (); } public static string GetMethodNameWithoutSuffix (this MethodInfo method) @@ -102,9 +102,9 @@ public static bool IsDefaultConstructorMarker (this MethodInfo method) public static bool IsPubliclyVisible (this KotlinPropertyFlags flags) => flags.HasFlag (KotlinPropertyFlags.Public) || flags.HasFlag (KotlinPropertyFlags.Protected); - public static bool IsUnnamedParameter (this ParameterInfo parameter) => parameter.Name.Length > 1 && parameter.Name.StartsWith ("p") && int.TryParse (parameter.Name.Substring (1), out var _); + public static bool IsUnnamedParameter (this ParameterInfo parameter) => parameter.Name.Length > 1 && parameter.Name.StartsWith ("p", StringComparison.Ordinal) && int.TryParse (parameter.Name.Substring (1), out var _); - public static bool IsUnnamedParameter (this KotlinValueParameter parameter) => parameter.Name.Length > 1 && parameter.Name.StartsWith ("p") && int.TryParse (parameter.Name.Substring (1), out var _); + public static bool IsUnnamedParameter (this KotlinValueParameter parameter) => parameter.Name.Length > 1 && parameter.Name.StartsWith ("p", StringComparison.Ordinal) && int.TryParse (parameter.Name.Substring (1), out var _); static Dictionary type_map = new Dictionary { { "kotlin/Int", "I" }, diff --git a/src/Xamarin.SourceWriter/Models/CommentWriter.cs b/src/Xamarin.SourceWriter/Models/CommentWriter.cs index 1eb3a29b5..d3ec6e485 100644 --- a/src/Xamarin.SourceWriter/Models/CommentWriter.cs +++ b/src/Xamarin.SourceWriter/Models/CommentWriter.cs @@ -16,7 +16,7 @@ public CommentWriter (string value) public virtual void Write (CodeWriter writer) { - if (Value.StartsWith ("#pragma")) + if (Value.StartsWith ("#pragma", StringComparison.Ordinal)) writer.WriteLineNoIndent (Value); else writer.WriteLine (Value); diff --git a/tests/Java.Interop-PerformanceTests/Java.Interop/TimingTests.cs b/tests/Java.Interop-PerformanceTests/Java.Interop/TimingTests.cs index c3935b72a..f748e29d7 100644 --- a/tests/Java.Interop-PerformanceTests/Java.Interop/TimingTests.cs +++ b/tests/Java.Interop-PerformanceTests/Java.Interop/TimingTests.cs @@ -293,7 +293,7 @@ static Action A (Action a) static string FormatFraction (double value, int width, int fractionWidth) { var v = value.ToString ("0.0" + new string ('#', fractionWidth - 1)); - var i = v.IndexOf (NumberFormatInfo.CurrentInfo.NumberDecimalSeparator); + var i = v.IndexOf (NumberFormatInfo.CurrentInfo.NumberDecimalSeparator, StringComparison.Ordinal); var p = new string (' ', width - fractionWidth - i - 1); return p + v + new string (' ', width - p.Length - v.Length); } diff --git a/tests/generator-Tests/Integration-Tests/BaseGeneratorTest.cs b/tests/generator-Tests/Integration-Tests/BaseGeneratorTest.cs index 19898e09c..83c6afb5b 100644 --- a/tests/generator-Tests/Integration-Tests/BaseGeneratorTest.cs +++ b/tests/generator-Tests/Integration-Tests/BaseGeneratorTest.cs @@ -96,7 +96,7 @@ protected bool FileCompare (string file1, string file2) using (var hash = new Crc64 ()) { var f1hash = Convert.ToBase64String (hash.ComputeHash (f1)); var f2hash = Convert.ToBase64String (hash.ComputeHash (f2)); - result = f1hash.Equals (f2hash); + result = string.Equals (f1hash, f2hash, StringComparison.Ordinal); } } diff --git a/tools/generator/CodeGenerationOptions.cs b/tools/generator/CodeGenerationOptions.cs index d29a755c6..00a7e8e2e 100644 --- a/tools/generator/CodeGenerationOptions.cs +++ b/tools/generator/CodeGenerationOptions.cs @@ -204,7 +204,7 @@ string GetJniTypeCode (ISymbol symbol) var jni_name = symbol.JniName; - if (jni_name.StartsWith ("L") || jni_name.StartsWith ("[")) + if (jni_name.StartsWith ("L", StringComparison.Ordinal) || jni_name.StartsWith ("[", StringComparison.Ordinal)) return "L"; return symbol.JniName; @@ -221,9 +221,9 @@ public string GetOutputName (string type) // Handle a few special cases if (type == "System.Void") return "void"; - if (type.StartsWith ("params ")) + if (type.StartsWith ("params ", StringComparison.Ordinal)) return "params " + GetOutputName (type.Substring ("params ".Length)); - if (type.StartsWith ("global::")) + if (type.StartsWith ("global::", StringComparison.Ordinal)) Report.LogCodedErrorAndExit (Report.ErrorUnexpectedGlobal); if (!UseGlobal) return type; @@ -249,7 +249,7 @@ public string GetSafeIdentifier (string name) // Sadly that is not true in reality, so we need to exclude non-symbols // when replacing the argument name with a valid identifier. // (ReturnValue.ToNative() takes an argument which could be either an expression or mere symbol.) - if (name [name.Length-1] != ')' && !name.Contains ('.') && !name.StartsWith ("@")) { + if (name [name.Length-1] != ')' && !name.Contains ('.') && !name.StartsWith ("@", StringComparison.Ordinal)) { if (!IdentifierValidator.IsValidIdentifier (name) || Array.BinarySearch (TypeNameUtilities.reserved_keywords, name) >= 0) { name = name + "_"; diff --git a/tools/generator/CodeGenerator.cs b/tools/generator/CodeGenerator.cs index b79ea12b5..ca7b24b86 100644 --- a/tools/generator/CodeGenerator.cs +++ b/tools/generator/CodeGenerator.cs @@ -311,7 +311,7 @@ internal static void ProcessReferencedType (TypeDefinition td, CodeGenerationOpt return; // We want to exclude "IBlahInvoker" types from this type registration. - if (td.Name.EndsWith ("Invoker")) { + if (td.Name.EndsWith ("Invoker", StringComparison.Ordinal)) { string n = td.FullName; n = n.Substring (0, n.Length - 7); var types = td.DeclaringType != null ? td.DeclaringType.Resolve ().NestedTypes : td.Module.Types; @@ -319,7 +319,7 @@ internal static void ProcessReferencedType (TypeDefinition td, CodeGenerationOpt return; //Console.Error.WriteLine ("WARNING: " + td.FullName + " survived"); } - if (td.Name.EndsWith ("Implementor")) { + if (td.Name.EndsWith ("Implementor", StringComparison.Ordinal)) { string n = td.FullName; n = n.Substring (0, n.Length - 11); var types = td.DeclaringType != null ? td.DeclaringType.Resolve ().NestedTypes : td.Module.Types; diff --git a/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/CodeGenerator.cs b/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/CodeGenerator.cs index 5ada96814..4789cbea9 100644 --- a/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/CodeGenerator.cs +++ b/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/CodeGenerator.cs @@ -877,7 +877,7 @@ public void WriteInterfaceInvoker (InterfaceGen @interface, string indent) foreach (InterfaceGen iface in @interface.GetAllDerivedInterfaces ()) { WriteInterfacePropertyInvokers (@interface, iface.Properties.Where (p => !p.Getter.IsStatic && !p.Getter.IsInterfaceDefaultMethod), indent + "\t", members); - WriteInterfaceMethodInvokers (@interface, iface.Methods.Where (m => !m.IsStatic && !m.IsInterfaceDefaultMethod && !@interface.IsCovariantMethod (m) && !(iface.FullName.StartsWith ("Java.Lang.ICharSequence") && m.Name.EndsWith ("Formatted"))), indent + "\t", members); + WriteInterfaceMethodInvokers (@interface, iface.Methods.Where (m => !m.IsStatic && !m.IsInterfaceDefaultMethod && !@interface.IsCovariantMethod (m) && !(iface.FullName.StartsWith ("Java.Lang.ICharSequence", StringComparison.Ordinal) && m.Name.EndsWith ("Formatted", StringComparison.Ordinal))), indent + "\t", members); if (iface.FullName == "Java.Lang.ICharSequence") WriteCharSequenceEnumerator (indent + "\t"); } @@ -923,7 +923,7 @@ public void WriteInterfaceListenerEventsAndProperties (InterfaceGen @interface, foreach (var m in @interface.Methods) { string nameSpec = @interface.Methods.Count > 1 ? m.EventName ?? m.AdjustedName : String.Empty; string nameUnique = String.IsNullOrEmpty (nameSpec) ? name : nameSpec; - if (nameUnique.StartsWith ("On")) + if (nameUnique.StartsWith ("On", StringComparison.Ordinal)) nameUnique = nameUnique.Substring (2); if (target.ContainsName (nameUnique)) nameUnique += "Event"; @@ -959,9 +959,9 @@ public void WriteInterfaceListenerEventsAndProperties (InterfaceGen @interface, refs.Add (method.Name); string rm = null; string remove; - if (method.Name.StartsWith ("Set")) + if (method.Name.StartsWith ("Set", StringComparison.Ordinal)) remove = string.Format ("__v => {0} (null)", method.Name); - else if (method.Name.StartsWith ("Add") && + else if (method.Name.StartsWith ("Add", StringComparison.Ordinal) && (rm = "Remove" + method.Name.Substring ("Add".Length)) != null && methods.Where (m => m.Name == rm).Any ()) remove = string.Format ("__v => {0} (__v)", rm); @@ -990,8 +990,8 @@ public void WriteInterfaceListenerEventOrProperty (InterfaceGen @interface, Meth if (m.EventName == string.Empty) return; string nameSpec = @interface.Methods.Count > 1 ? m.AdjustedName : String.Empty; - int idx = @interface.FullName.LastIndexOf ("."); - int start = @interface.Name.StartsWith ("IOn") ? 3 : 1; + int idx = @interface.FullName.LastIndexOf ('.'); + int start = @interface.Name.StartsWith ("IOn", StringComparison.Ordinal) ? 3 : 1; string full_delegate_name = @interface.FullName.Substring (0, idx + 1) + @interface.Name.Substring (start, @interface.Name.Length - start - 8) + nameSpec; if (m.IsSimpleEventHandler) full_delegate_name = "EventHandler"; @@ -1586,7 +1586,7 @@ public void WriteProperty (Property property, GenBase gen, string indent, bool w writer.WriteLine ("{0}}}", indent); writer.WriteLine (); - if (property.Type.StartsWith ("Java.Lang.ICharSequence") && virtual_override != " override") + if (property.Type.StartsWith ("Java.Lang.ICharSequence", StringComparison.Ordinal) && virtual_override != " override") WritePropertyStringVariant (property, indent); } @@ -1631,7 +1631,7 @@ public void WritePropertyAbstractDeclaration (Property property, string indent, } writer.WriteLine ("{0}}}", indent); writer.WriteLine (); - if (property.Type.StartsWith ("Java.Lang.ICharSequence")) + if (property.Type.StartsWith ("Java.Lang.ICharSequence", StringComparison.Ordinal)) WritePropertyStringVariant (property, indent); } diff --git a/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/EnumGenerator.cs b/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/EnumGenerator.cs index a589957dc..b717fbfd4 100644 --- a/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/EnumGenerator.cs +++ b/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/EnumGenerator.cs @@ -87,7 +87,7 @@ static void DoParseJniMember (string jniMember, out string package, out string t int endClass = jniMember.LastIndexOf ('.'); package = jniMember.Substring (0, endPackage).Replace ('/', '.'); - if (package.StartsWith ("I:")) + if (package.StartsWith ("I:", StringComparison.Ordinal)) package = package.Substring (2); if (endClass >= 0) { diff --git a/tools/generator/Java.Interop.Tools.Generator.Importers/CecilApiImporter.cs b/tools/generator/Java.Interop.Tools.Generator.Importers/CecilApiImporter.cs index 5af44d599..6c02731d5 100644 --- a/tools/generator/Java.Interop.Tools.Generator.Importers/CecilApiImporter.cs +++ b/tools/generator/Java.Interop.Tools.Generator.Importers/CecilApiImporter.cs @@ -216,7 +216,7 @@ public static Method CreateMethod (GenBase declaringType, MethodDefinition m) // Strip "Formatted" from ICharSequence-based method. var name_base = method.IsReturnCharSequence ? m.Name.Substring (0, m.Name.Length - "Formatted".Length) : m.Name; - method.Name = m.IsGetter ? (m.Name.StartsWith ("get_Is") && m.Name.Length > 6 && char.IsUpper (m.Name [6]) ? string.Empty : "Get") + name_base.Substring (4) : m.IsSetter ? (m.Name.StartsWith ("set_Is") && m.Name.Length > 6 && char.IsUpper (m.Name [6]) ? string.Empty : "Set") + name_base.Substring (4) : name_base; + method.Name = m.IsGetter ? (m.Name.StartsWith ("get_Is", StringComparison.Ordinal) && m.Name.Length > 6 && char.IsUpper (m.Name [6]) ? string.Empty : "Get") + name_base.Substring (4) : m.IsSetter ? (m.Name.StartsWith ("set_Is", StringComparison.Ordinal) && m.Name.Length > 6 && char.IsUpper (m.Name [6]) ? string.Empty : "Set") + name_base.Substring (4) : name_base; return method; } diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/ClassGen.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/ClassGen.cs index 7d31ba635..7ddd494f6 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/ClassGen.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/ClassGen.cs @@ -223,7 +223,7 @@ public static void GenerateTypeRegistrations (CodeGenerationOptions opt, Generat sw.WriteLine ("\t\t{"); sw.WriteLine ("\t\t\tif (package_{0}_mappings == null) {{", package); sw.WriteLine ("\t\t\t\tpackage_{0}_mappings = new string[]{{", package); - map.Value.Sort ((a, b) => a.Key.CompareTo (b.Key)); + map.Value.Sort ((a, b) => string.Compare (a.Key, b.Key, StringComparison.Ordinal)); foreach (KeyValuePair t in map.Value) { sw.WriteLine ("\t\t\t\t\t\"{0}:{1}\",", t.Key, t.Value); } diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Field.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Field.cs index da6b2423d..ac0206cba 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Field.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Field.cs @@ -49,7 +49,7 @@ public bool Validate (CodeGenerationOptions opt, GenericParameterDefinitionList return false; } - if (!string.IsNullOrEmpty (Value) && Symbol != null && Symbol.FullName == "char" && !Value.StartsWith ("(char)")) + if (!string.IsNullOrEmpty (Value) && Symbol != null && Symbol.FullName == "char" && !Value.StartsWith ("(char)", StringComparison.Ordinal)) Value = "(char)" + Value; SetParameters = new ParameterList { diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs index 609b027cf..aaa3f82c2 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs @@ -66,7 +66,7 @@ public void AddMethod (Method m) public virtual void AddNestedType (GenBase gen) { foreach (var nest in NestedTypes) { - if (gen.JavaName.StartsWith (nest.JavaName + ".")) { + if (gen.JavaName.StartsWith (nest.JavaName + ".", StringComparison.Ordinal)) { nest.AddNestedType (gen); return; } @@ -75,7 +75,7 @@ public virtual void AddNestedType (GenBase gen) var removes = new List (); foreach (var nest in NestedTypes) { - if (nest.JavaName.StartsWith (gen.JavaName + ".")) { + if (nest.JavaName.StartsWith (gen.JavaName + ".", StringComparison.Ordinal)) { gen.AddNestedType (nest); removes.Add (nest); } @@ -112,7 +112,7 @@ void AddPropertyAccessors () unmatched.Add (m); else { if (prop_hash.ContainsKey (prop_name)) { - if (m.Name.StartsWith ("Get")) + if (m.Name.StartsWith ("Get", StringComparison.Ordinal)) unmatched.Add (m); else { unmatched.Add (prop_hash [prop_name].Getter); diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/InterfaceGen.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/InterfaceGen.cs index 8b8b0ef6d..6e0947616 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/InterfaceGen.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/InterfaceGen.cs @@ -20,7 +20,7 @@ public override void AddNestedType (GenBase gen) var nest_name = gen.JavaName.Substring (JavaName.Length + 1); - if (nest_name.IndexOf (".") < 0) { + if (nest_name.IndexOf ('.') < 0) { // We don't need to mangle the name if we support nested interface types // ex: my.namespace.IParent.IChild if (!gen.Unnest) { @@ -116,14 +116,14 @@ internal string GetArgsName (Method m) if (m.IsSimpleEventHandler) return "EventArgs"; nameBase = m.AdjustedName; - start = nameBase.StartsWith ("On") ? 2 : 0; + start = nameBase.StartsWith ("On", StringComparison.Ordinal) ? 2 : 0; } else { if (!string.IsNullOrEmpty (ArgsType)) return ArgsType; if (m.IsSimpleEventHandler) return "EventArgs"; nameBase = Name; - start = Name.StartsWith ("IOn") ? 3 : 1; + start = Name.StartsWith ("IOn", StringComparison.Ordinal) ? 3 : 1; trim = 8; // "Listener" } return nameBase.Substring (start, nameBase.Length - start - trim) + "EventArgs"; @@ -131,7 +131,7 @@ internal string GetArgsName (Method m) internal string GetEventDelegateName (Method m) { - int start = Name.StartsWith ("IOn") ? 3 : 1; + int start = Name.StartsWith ("IOn", StringComparison.Ordinal) ? 3 : 1; if (m.RetVal.IsVoid) { if (m.IsSimpleEventHandler) return "EventHandler"; @@ -189,7 +189,7 @@ public bool IsConstSugar (CodeGenerationOptions options) } // If there is a property it cannot generate valid implementor, so reject this at least so far. - public bool IsListener => Name.EndsWith ("Listener") && Properties.Count == 0 && Interfaces.Count == 0; + public bool IsListener => Name.EndsWith ("Listener", StringComparison.Ordinal) && Properties.Count == 0 && Interfaces.Count == 0; public bool HasManagedName { get; set; } diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/JavadocInfo.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/JavadocInfo.cs index 702984499..088573f23 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/JavadocInfo.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/JavadocInfo.cs @@ -233,7 +233,7 @@ static XElement CreateAndroidDocLinkUri (string prefix, string declaringJniType, .Replace ("/", ".") .Replace ("$", "."); var url = new StringBuilder (prefix); - if (!prefix.EndsWith ("/")) { + if (!prefix.EndsWith ("/", StringComparison.Ordinal)) { url.Append ("/"); } url.Append (declaringJniType); diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Method.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Method.cs index 6f95ce665..c78ca6af7 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Method.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Method.cs @@ -67,7 +67,7 @@ public string AutoDetectEnumifiedOverrideReturn (AncestorDescendantCache cache) public bool CanAdd { get { - return Name.Length > 3 && Name.StartsWith ("Add") && Name.EndsWith ("Listener") && IsVoid && + return Name.Length > 3 && Name.StartsWith ("Add", StringComparison.Ordinal) && Name.EndsWith ("Listener", StringComparison.Ordinal) && IsVoid && (Parameters.Count == 1 || (Parameters.Count == 2 && Parameters [1].Type == "Android.OS.Handler")) && !(Parameters [0].IsArray); } @@ -77,15 +77,15 @@ public string AutoDetectEnumifiedOverrideReturn (AncestorDescendantCache cache) get { return Parameters.Count == 0 && !IsVoid && !RetVal.IsArray && - ((Name.Length > 4 && Name.StartsWith ("Get") && char.IsUpper (Name [3])) || - ((Name.Length > 4 && Name.StartsWith ("Has") && char.IsUpper (Name [3]) && RetVal.JavaName == "boolean") || - (Name.Length > 3 && Name.StartsWith ("Is") && char.IsUpper (Name [2]) && RetVal.JavaName == "boolean"))); + ((Name.Length > 4 && Name.StartsWith ("Get", StringComparison.Ordinal) && char.IsUpper (Name [3])) || + ((Name.Length > 4 && Name.StartsWith ("Has", StringComparison.Ordinal) && char.IsUpper (Name [3]) && RetVal.JavaName == "boolean") || + (Name.Length > 3 && Name.StartsWith ("Is", StringComparison.Ordinal) && char.IsUpper (Name [2]) && RetVal.JavaName == "boolean"))); } } public bool CanSet { get { - return Name.Length > 3 && Name.StartsWith ("Set") && Parameters.Count == 1 && IsVoid && + return Name.Length > 3 && Name.StartsWith ("Set", StringComparison.Ordinal) && Parameters.Count == 1 && IsVoid && !(Parameters [0].IsArray); } } @@ -96,7 +96,7 @@ internal string CalculateEventName (Func checkNameDuplicate) if (event_name == null) { var trimSize = Name.EndsWith ("Listener", StringComparison.Ordinal) ? 8 : 0; event_name = Name.Substring (0, Name.Length - trimSize).Substring (3); - if (event_name.StartsWith ("On")) + if (event_name.StartsWith ("On", StringComparison.Ordinal)) event_name = event_name.Substring (2); if (checkNameDuplicate (event_name)) event_name += "Event"; @@ -149,7 +149,7 @@ internal string GetAdapterName (CodeGenerationOptions opt, string adapter) public bool IsPropertyAccessor => CanGet || CanSet; - public bool IsReturnCharSequence => RetVal.FullName.StartsWith ("Java.Lang.ICharSequence"); + public bool IsReturnCharSequence => RetVal.FullName.StartsWith ("Java.Lang.ICharSequence", StringComparison.Ordinal); public bool IsSimpleEventHandler => RetVal.IsVoid && (Parameters.Count == 0 || (Parameters.HasSender && Parameters.Count == 1)); @@ -183,7 +183,7 @@ public override bool Matches (MethodBase other) if (pn != null) return pn; var nameBase = Name; - if (CanAdd || CanSet || Name.StartsWith ("Get")) + if (CanAdd || CanSet || Name.StartsWith ("Get", StringComparison.Ordinal)) nameBase = Name.Substring (3); if (IsAbstract && (CanGet && RetVal.IsGeneric || CanSet && Parameters [0].IsGeneric) && DeclaringType is ClassGen) // Interface methods cannot be RawXxx (because they are not generic so far...) diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/MethodBase.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/MethodBase.cs index a9222d4ca..ee10dc45f 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/MethodBase.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/MethodBase.cs @@ -91,7 +91,7 @@ public string GetSignature (CodeGenerationOptions opt) // Kotlin generates methods that cannot be referenced in Java, // like `add-impl` and `add-V5j3Lk8`. We will need to fix those later. if (this is Method method) { - if (method.JavaName.IndexOf ("-impl") >= 0) + if (method.JavaName.IndexOf ("-impl", StringComparison.Ordinal) >= 0) return true; return method.JavaName.Length >= 8 && method.JavaName [method.JavaName.Length - 8] == '-'; diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Parameter.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Parameter.cs index 1c79726e0..f3a886596 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Parameter.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Parameter.cs @@ -126,7 +126,7 @@ public string GetGenericType (Dictionary mappings) public string JavaName { get { - if (Name.StartsWith ("@")) + if (Name.StartsWith ("@", StringComparison.Ordinal)) return Name.Substring (1); return Name; } @@ -253,7 +253,7 @@ public string GetGenericCall (CodeGenerationOptions opt, Dictionary ()", name, targetType.Replace ("[]","")); } var rgm = opt.SymbolTable.Lookup (targetType) as IRequireGenericMarshal; diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/ParameterList.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/ParameterList.cs index 711932e52..859156341 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/ParameterList.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/ParameterList.cs @@ -149,7 +149,7 @@ public string GetCallbackSignature (CodeGenerationOptions opt) public bool HasCharSequence { get { foreach (Parameter p in items) - if (p.JavaType.StartsWith("java.lang.CharSequence")) + if (p.JavaType.StartsWith ("java.lang.CharSequence", StringComparison.Ordinal)) return true; return false; } diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Property.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Property.cs index 391199e3e..591002361 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Property.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Property.cs @@ -35,7 +35,7 @@ public Property (string name) public bool GenerateDispatchingSetter { get; set; } internal string AdjustedName => - Getter.ReturnType.StartsWith ("Java.Lang.ICharSequence") ? Name + "Formatted" : Name; + Getter.ReturnType.StartsWith ("Java.Lang.ICharSequence", StringComparison.Ordinal) ? Name + "Formatted" : Name; public string Name { get; set; } diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Symbols/GeneratedEnumSymbol.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Symbols/GeneratedEnumSymbol.cs index 3f8a1fddc..1878cd89a 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Symbols/GeneratedEnumSymbol.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Symbols/GeneratedEnumSymbol.cs @@ -11,7 +11,7 @@ public class GeneratedEnumSymbol : ISymbol public GeneratedEnumSymbol (string enumType) { - if (enumType.EndsWith ("[]")) { + if (enumType.EndsWith ("[]", StringComparison.Ordinal)) { enum_type = enumType.Substring (0, enumType.Length - 2); is_array = true; } diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Symbols/SymbolTable.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Symbols/SymbolTable.cs index 5ae736a6b..4cd4fe7f5 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Symbols/SymbolTable.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Symbols/SymbolTable.cs @@ -309,7 +309,7 @@ public ISymbol Lookup (string java_type) private string AddArity (string key, string typeParams) { - if (string.IsNullOrWhiteSpace (typeParams) || !typeParams.StartsWith ("<") || !typeParams.EndsWith (">")) + if (string.IsNullOrWhiteSpace (typeParams) || !typeParams.StartsWith ("<", StringComparison.Ordinal) || !typeParams.EndsWith (">", StringComparison.Ordinal)) return key; var nested_count = 0; @@ -335,7 +335,7 @@ private string AddArity (string key, string typeParams) public void Dump () { foreach (var p in symbols) { - if (p.Key.StartsWith ("System")) + if (p.Key.StartsWith ("System", StringComparison.Ordinal)) continue; foreach (var s in p.Value) { Console.Error.WriteLine ("[{0}]: {1} {2}", p.Key, s.GetType (), s.FullName); diff --git a/tools/generator/Java.Interop.Tools.Generator.Transformation/EnumMap.cs b/tools/generator/Java.Interop.Tools.Generator.Transformation/EnumMap.cs index c0bb534b7..62902f8f8 100644 --- a/tools/generator/Java.Interop.Tools.Generator.Transformation/EnumMap.cs +++ b/tools/generator/Java.Interop.Tools.Generator.Transformation/EnumMap.cs @@ -28,11 +28,11 @@ public EnumMappings (string outputDir, string outputMetadata, string version, bo internal Dictionary Process (string fieldMap, string flagsFile, string methodMap) { remove_nodes = new List> (); - var enums = (fieldMap ?? "").EndsWith (".csv") + var enums = (fieldMap ?? "").EndsWith (".csv", StringComparison.OrdinalIgnoreCase) ? ParseFieldMappings (fieldMap, flagsFile, version, remove_nodes) : ParseXmlFieldMappings (fieldMap, version, remove_nodes); - var methods = (methodMap ?? "").EndsWith (".csv") + var methods = (methodMap ?? "").EndsWith (".csv", StringComparison.OrdinalIgnoreCase) ? ParseMethodMappings (methodMap, version) : ParseXmlMethodMappings (methodMap, version); @@ -64,7 +64,7 @@ void RemoveOldConstants (StreamWriter sw) ParseJniMember (enu, out package, out type, out member); try { sw.WriteLine (" ", - package, type, member, enu.StartsWith ("I:") ? "interface" : "class"); + package, type, member, enu.StartsWith ("I:", StringComparison.Ordinal) ? "interface" : "class"); } catch (Exception ex) { Report.LogCodedErrorAndExit (Report.ErrorFailedToRemoveConstants, ex, enu); throw; @@ -82,16 +82,16 @@ void FixOldConstants (StreamWriter sw) if (pair.Value != null) { sw.WriteLine (" {4}", - package, type, member, enu.StartsWith ("I:") ? "interface" : "class", pair.Value); + package, type, member, enu.StartsWith ("I:", StringComparison.Ordinal) ? "interface" : "class", pair.Value); sw.WriteLine (" This constant will be removed in the future version. Use {4} enum directly instead of this field.", - package, type, member, enu.StartsWith ("I:") ? "interface" : "class", pair.Value); + package, type, member, enu.StartsWith ("I:", StringComparison.Ordinal) ? "interface" : "class", pair.Value); sw.WriteLine (" true", - package, type, member, enu.StartsWith ("I:") ? "interface" : "class", pair.Value); + package, type, member, enu.StartsWith ("I:", StringComparison.Ordinal) ? "interface" : "class", pair.Value); continue; } try { sw.WriteLine (" ", - package, type, member, enu.StartsWith ("I:") ? "interface" : "class"); + package, type, member, enu.StartsWith ("I:", StringComparison.Ordinal) ? "interface" : "class"); } catch (Exception ex) { Report.LogCodedErrorAndExit (Report.ErrorFailedToRemoveConstants, ex, enu); throw; diff --git a/tools/generator/Java.Interop.Tools.Generator.Transformation/EnumMappings.cs b/tools/generator/Java.Interop.Tools.Generator.Transformation/EnumMappings.cs index be84e6949..39e764cd2 100644 --- a/tools/generator/Java.Interop.Tools.Generator.Transformation/EnumMappings.cs +++ b/tools/generator/Java.Interop.Tools.Generator.Transformation/EnumMappings.cs @@ -95,7 +95,7 @@ static void DoParseJniMember (string jniMember, out string package, out string t int endClass = jniMember.LastIndexOf ('.'); package = jniMember.Substring (0, endPackage).Replace ('/', '.'); - if (package.StartsWith ("I:")) + if (package.StartsWith ("I:", StringComparison.Ordinal)) package = package.Substring (2); if (endClass >= 0) { diff --git a/tools/generator/Java.Interop.Tools.Generator.Transformation/KotlinFixups.cs b/tools/generator/Java.Interop.Tools.Generator.Transformation/KotlinFixups.cs index 6545a0818..680da243c 100644 --- a/tools/generator/Java.Interop.Tools.Generator.Transformation/KotlinFixups.cs +++ b/tools/generator/Java.Interop.Tools.Generator.Transformation/KotlinFixups.cs @@ -49,7 +49,7 @@ private static void FixMethodName (Method method) // We want to remove the hyphen and anything afterwards to fix mangled names, // but a previous step converted it to an underscore. Remove the final // underscore and anything after it. - var index = method.Name.IndexOf ("_impl"); + var index = method.Name.IndexOf ("_impl", StringComparison.Ordinal); if (index >= 0) method.Name = method.Name.Substring (0, index); diff --git a/tools/generator/SourceWriters/BoundClass.cs b/tools/generator/SourceWriters/BoundClass.cs index b7743bbee..e32628491 100644 --- a/tools/generator/SourceWriters/BoundClass.cs +++ b/tools/generator/SourceWriters/BoundClass.cs @@ -331,7 +331,7 @@ void AddProperty (ClassGen klass, Property property, CodeGenerationOptions opt) var bound_property = new BoundProperty (klass, property, opt, true, false); Properties.Add (bound_property); - if (property.Type.StartsWith ("Java.Lang.ICharSequence") && !bound_property.IsOverride) + if (property.Type.StartsWith ("Java.Lang.ICharSequence", StringComparison.Ordinal) && !bound_property.IsOverride) Properties.Add (new BoundPropertyStringVariant (property, opt)); } @@ -349,7 +349,7 @@ void AddAbstractPropertyDeclaration (ClassGen klass, Property property, CodeGene Properties.Add (new BoundAbstractProperty (klass, property, opt)); - if (property.Type.StartsWith ("Java.Lang.ICharSequence")) + if (property.Type.StartsWith ("Java.Lang.ICharSequence", StringComparison.Ordinal)) Properties.Add (new BoundPropertyStringVariant (property, opt)); } diff --git a/tools/generator/SourceWriters/BoundInterface.cs b/tools/generator/SourceWriters/BoundInterface.cs index 1738d922a..350bf303b 100644 --- a/tools/generator/SourceWriters/BoundInterface.cs +++ b/tools/generator/SourceWriters/BoundInterface.cs @@ -193,13 +193,13 @@ void AddProperties (InterfaceGen iface, CodeGenerationOptions opt) var bound_property = new BoundAbstractProperty (iface, prop, opt); Properties.Add (bound_property); - if (prop.Type.StartsWith ("Java.Lang.ICharSequence") && !bound_property.IsOverride) + if (prop.Type.StartsWith ("Java.Lang.ICharSequence", StringComparison.Ordinal) && !bound_property.IsOverride) Properties.Add (new BoundPropertyStringVariant (prop, opt)); } else { var bound_property = new BoundProperty (iface, prop, opt, true, false); Properties.Add (bound_property); - if (prop.Type.StartsWith ("Java.Lang.ICharSequence") && !bound_property.IsOverride) + if (prop.Type.StartsWith ("Java.Lang.ICharSequence", StringComparison.Ordinal) && !bound_property.IsOverride) Properties.Add (new BoundPropertyStringVariant (prop, opt)); } } diff --git a/tools/generator/SourceWriters/ClassInvokerClass.cs b/tools/generator/SourceWriters/ClassInvokerClass.cs index 9b767d760..f650a344e 100644 --- a/tools/generator/SourceWriters/ClassInvokerClass.cs +++ b/tools/generator/SourceWriters/ClassInvokerClass.cs @@ -75,7 +75,7 @@ void AddPropertyInvokers (ClassGen klass, IEnumerable properties, Hash var bound_property = new BoundProperty (klass, prop, opt, false, true); Properties.Add (bound_property); - if (prop.Type.StartsWith ("Java.Lang.ICharSequence") && !bound_property.IsOverride) + if (prop.Type.StartsWith ("Java.Lang.ICharSequence", StringComparison.Ordinal) && !bound_property.IsOverride) Properties.Add (new BoundPropertyStringVariant (prop, opt)); } } diff --git a/tools/generator/SourceWriters/Extensions/SourceWriterExtensions.cs b/tools/generator/SourceWriters/Extensions/SourceWriterExtensions.cs index 917024e2e..dd965bf15 100644 --- a/tools/generator/SourceWriters/Extensions/SourceWriterExtensions.cs +++ b/tools/generator/SourceWriters/Extensions/SourceWriterExtensions.cs @@ -91,9 +91,9 @@ public static void AddInterfaceListenerEventsAndProperties (TypeWriter tw, Inter string rm = null; string remove; - if (method.Name.StartsWith ("Set")) + if (method.Name.StartsWith ("Set", StringComparison.Ordinal)) remove = string.Format ("__v => {0} (null)", method.Name); - else if (method.Name.StartsWith ("Add") && + else if (method.Name.StartsWith ("Add", StringComparison.Ordinal) && (rm = "Remove" + method.Name.Substring ("Add".Length)) != null && methods.Where (m => m.Name == rm).Any ()) remove = string.Format ("__v => {0} (__v)", rm); @@ -124,7 +124,7 @@ public static void AddInterfaceListenerEventsAndProperties (TypeWriter tw, Inter var nameSpec = iface.Methods.Count > 1 ? method.EventName ?? method.AdjustedName : string.Empty; var nameUnique = string.IsNullOrEmpty (nameSpec) ? name : nameSpec; - if (nameUnique.StartsWith ("On")) + if (nameUnique.StartsWith ("On", StringComparison.Ordinal)) nameUnique = nameUnique.Substring (2); if (target.ContainsName (nameUnique)) @@ -140,8 +140,8 @@ public static void AddInterfaceListenerEventOrProperty (TypeWriter tw, Interface return; var nameSpec = iface.Methods.Count > 1 ? method.AdjustedName : string.Empty; - var idx = iface.FullName.LastIndexOf ("."); - var start = iface.Name.StartsWith ("IOn") ? 3 : 1; + var idx = iface.FullName.LastIndexOf (".", StringComparison.Ordinal); + var start = iface.Name.StartsWith ("IOn", StringComparison.Ordinal) ? 3 : 1; var full_delegate_name = iface.FullName.Substring (0, idx + 1) + iface.Name.Substring (start, iface.Name.Length - start - 8) + nameSpec; if (method.IsSimpleEventHandler) diff --git a/tools/generator/SourceWriters/InterfaceInvokerClass.cs b/tools/generator/SourceWriters/InterfaceInvokerClass.cs index 683f4b191..1f16753fe 100644 --- a/tools/generator/SourceWriters/InterfaceInvokerClass.cs +++ b/tools/generator/SourceWriters/InterfaceInvokerClass.cs @@ -50,7 +50,7 @@ void AddMemberInvokers (InterfaceGen iface, HashSet members, CodeGenerat foreach (var i in iface.GetAllDerivedInterfaces ()) { AddPropertyInvokers (iface, i.Properties.Where (p => !p.Getter.IsStatic && !p.Getter.IsInterfaceDefaultMethod), members, opt, context); - AddMethodInvokers (iface, i.Methods.Where (m => !m.IsStatic && !m.IsInterfaceDefaultMethod && !iface.IsCovariantMethod (m) && !(i.FullName.StartsWith ("Java.Lang.ICharSequence") && m.Name.EndsWith ("Formatted"))), members, opt, context); + AddMethodInvokers (iface, i.Methods.Where (m => !m.IsStatic && !m.IsInterfaceDefaultMethod && !iface.IsCovariantMethod (m) && !(i.FullName.StartsWith ("Java.Lang.ICharSequence", StringComparison.Ordinal) && m.Name.EndsWith ("Formatted", StringComparison.Ordinal))), members, opt, context); AddCharSequenceEnumerators (i); } } diff --git a/tools/generator/Utilities/ParsedType.cs b/tools/generator/Utilities/ParsedType.cs index 0dc6121c8..a7c1026ea 100644 --- a/tools/generator/Utilities/ParsedType.cs +++ b/tools/generator/Utilities/ParsedType.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Linq; diff --git a/tools/generator/Utilities/ProcessRocks.cs b/tools/generator/Utilities/ProcessRocks.cs index 6ece4beef..04f0d45e6 100644 --- a/tools/generator/Utilities/ProcessRocks.cs +++ b/tools/generator/Utilities/ProcessRocks.cs @@ -87,7 +87,7 @@ internal static string MapGeneratedToProjectFile (string filename) try { // Find the root, by stripping off \obj and beyond - string root = filename.Substring (0, filename.IndexOf (string.Format ("{0}obj{0}", Path.DirectorySeparatorChar))); + string root = filename.Substring (0, filename.IndexOf (string.Format ("{0}obj{0}", Path.DirectorySeparatorChar), StringComparison.Ordinal)); var files = FindFileInDirectory (root, Path.GetFileName (filename)); diff --git a/tools/generator/Utilities/TypeNameUtilities.cs b/tools/generator/Utilities/TypeNameUtilities.cs index 465dca976..4af711dc2 100644 --- a/tools/generator/Utilities/TypeNameUtilities.cs +++ b/tools/generator/Utilities/TypeNameUtilities.cs @@ -71,7 +71,7 @@ public static string GetGenericJavaObjectTypeOverride (string managed_name, stri public static string GetNativeName (string name) { - if (name.StartsWith ("@")) + if (name.StartsWith ("@", StringComparison.Ordinal)) return "native__" + name.Substring (1); return "native_" + name; } diff --git a/tools/jnimarshalmethod-gen/App.cs b/tools/jnimarshalmethod-gen/App.cs index 0f5cbe71a..d4020fd51 100644 --- a/tools/jnimarshalmethod-gen/App.cs +++ b/tools/jnimarshalmethod-gen/App.cs @@ -270,7 +270,7 @@ public int Compare (MethodInfo a, MethodInfo b) if (atd.HasOverrides ^ btd.HasOverrides) return btd.HasOverrides ? -1 : 1; - return string.Compare (a.Name, b.Name); + return string.Compare (a.Name, b.Name, StringComparison.Ordinal); } } diff --git a/tools/logcat-parse/repl.cs b/tools/logcat-parse/repl.cs index edba70d85..4a342e7ff 100644 --- a/tools/logcat-parse/repl.cs +++ b/tools/logcat-parse/repl.cs @@ -177,7 +177,7 @@ void ExecuteSources (IEnumerable sources, bool ignore_errors) ReadEvalPrintLoopWith (p => { var line = r.ReadLine (); if (first){ - if (line.StartsWith ("#!")) + if (line.StartsWith ("#!", StringComparison.Ordinal)) line = r.ReadLine (); first = false; } @@ -209,9 +209,9 @@ protected virtual void LoadStartupFiles () foreach (string file in System.IO.Directory.GetFiles (dir)){ string l = file.ToLower (); - if (l.EndsWith (".cs")) + if (l.EndsWith (".cs", StringComparison.OrdinalIgnoreCase)) sources.Add (file); - else if (l.EndsWith (".dll")) + else if (l.EndsWith (".dll", StringComparison.OrdinalIgnoreCase)) libraries.Add (file); }