diff --git a/.editorconfig b/.editorconfig
index a9a2a81b8..2d2c3e500 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -97,7 +97,6 @@ dotnet_diagnostic.CA2208.severity = suggestion # CA2208: Instantiate argument e
dotnet_diagnostic.CA2211.severity = none # CA2211: Non-constant fields should not be visible
dotnet_diagnostic.CA2219.severity = suggestion # CA2219: Do not raise exceptions in finally clauses
dotnet_diagnostic.CA2229.severity = suggestion # CA2229: Implement serialization constructors
-dotnet_diagnostic.CA2249.severity = suggestion # CA2249: Consider using 'string.Contains' instead of 'string.IndexOf'
dotnet_diagnostic.CA2263.severity = none # CA2263: Prefer generic overload when type is known
dotnet_diagnostic.CA3075.severity = suggestion # CA3075: Insecure DTD processing in XML
dotnet_diagnostic.CA5350.severity = suggestion # CA5350: Do Not Use Weak Cryptographic Algorithms
diff --git a/src/core/IronPython.Modules/IronPython.Modules.csproj b/src/core/IronPython.Modules/IronPython.Modules.csproj
index 7a314eec0..86e575a48 100644
--- a/src/core/IronPython.Modules/IronPython.Modules.csproj
+++ b/src/core/IronPython.Modules/IronPython.Modules.csproj
@@ -13,6 +13,7 @@
T:System.Diagnostics.CodeAnalysis.NotNullAttribute;
T:System.Diagnostics.CodeAnalysis.NotNullWhenAttribute;
T:System.Runtime.Versioning.SupportedOSPlatformAttribute;
+ M:System.String.Contains(System.Char);
M:System.String.EndsWith(System.Char);
@@ -43,7 +44,7 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/src/core/IronPython.Modules/_csv.cs b/src/core/IronPython.Modules/_csv.cs
index f442329aa..278f65f01 100644
--- a/src/core/IronPython.Modules/_csv.cs
+++ b/src/core/IronPython.Modules/_csv.cs
@@ -1006,7 +1006,7 @@ private void JoinAppend(string field, bool quoted) {
}
foreach (char c in need_escape) {
- if (field.IndexOf(c) >= 0) {
+ if (field.Contains(c)) {
if (string.IsNullOrEmpty(_dialect.escapechar))
throw MakeError("need to escape, but no escapechar set");
field = field.Replace(c.ToString(), _dialect.escapechar + c);
diff --git a/src/core/IronPython.Modules/_ctypes/SimpleType.cs b/src/core/IronPython.Modules/_ctypes/SimpleType.cs
index 2bdcf6467..a786362da 100644
--- a/src/core/IronPython.Modules/_ctypes/SimpleType.cs
+++ b/src/core/IronPython.Modules/_ctypes/SimpleType.cs
@@ -44,7 +44,7 @@ public SimpleType(CodeContext/*!*/ context, string name, PythonTuple bases, Pyth
if (!TryGetBoundCustomMember(context, "_type_", out object val) ||
(sVal = StringOps.AsString(val)) == null ||
sVal.Length != 1 ||
- allowedTypes.IndexOf(sVal[0]) == -1) {
+ !allowedTypes.Contains(sVal[0])) {
throw PythonOps.AttributeError("AttributeError: class must define a '_type_' attribute which must be a single character string containing one of '{0}'.", allowedTypes);
}
@@ -86,7 +86,7 @@ public SimpleType(CodeContext/*!*/ context, string name, PythonTuple bases, Pyth
throw new NotImplementedException("simple type " + sVal);
}
- if (!name.EndsWith("_be", StringComparison.Ordinal) && !name.EndsWith("_le", StringComparison.Ordinal) && swappedTypes.IndexOf(_charType) != -1) {
+ if (!name.EndsWith("_be", StringComparison.Ordinal) && !name.EndsWith("_le", StringComparison.Ordinal) && swappedTypes.Contains(_charType)) {
CreateSwappedType(context, name, bases, dict);
}
_format = (BitConverter.IsLittleEndian ? '<' : '>') + _charType.ToString();
diff --git a/src/core/IronPython.Modules/_ctypes/_ctypes.cs b/src/core/IronPython.Modules/_ctypes/_ctypes.cs
index 83ccefdb9..c841898b5 100644
--- a/src/core/IronPython.Modules/_ctypes/_ctypes.cs
+++ b/src/core/IronPython.Modules/_ctypes/_ctypes.cs
@@ -186,7 +186,7 @@ public static void FreeLibrary(IntPtr handle) {
}
private static object LoadDLL(string? library, int mode) {
- if (library is not null && library.IndexOf((char)0) != -1) throw PythonOps.ValueError("embedded null byte");
+ if (library is not null && library.Contains((char)0)) throw PythonOps.ValueError("embedded null byte");
IntPtr res = NativeFunctions.LoadDLL(library, mode);
if (res == IntPtr.Zero) {
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
diff --git a/src/core/IronPython.Modules/array.cs b/src/core/IronPython.Modules/array.cs
index 1102c5ed6..03a70cabc 100644
--- a/src/core/IronPython.Modules/array.cs
+++ b/src/core/IronPython.Modules/array.cs
@@ -865,7 +865,7 @@ bool IStructuralEquatable.Equals(object? other, IEqualityComparer comparer) {
if (_typeCode == 'u') {
char quote = '\'';
string s = new string(((ArrayData)_data).Data, 0, _data.Count);
- if (s.IndexOf('\'') != -1 && s.IndexOf('\"') == -1) {
+ if (s.Contains('\'') && !s.Contains('\"')) {
quote = '\"';
}
diff --git a/src/core/IronPython.Modules/grp.cs b/src/core/IronPython.Modules/grp.cs
index dc0344358..e1ae57b47 100644
--- a/src/core/IronPython.Modules/grp.cs
+++ b/src/core/IronPython.Modules/grp.cs
@@ -112,7 +112,7 @@ public static struct_group getgrgid(CodeContext context, object gid) {
}
public static struct_group getgrnam(string name) {
- if (name is not null && name.IndexOf((char)0) != -1) throw PythonOps.ValueError("embedded null byte");
+ if (name is not null && name.Contains((char)0)) throw PythonOps.ValueError("embedded null byte");
var grp = _getgrnam(name);
if (grp == IntPtr.Zero) {
throw PythonOps.KeyError($"getgrnam()): name not found: {name}");
diff --git a/src/core/IronPython.Modules/nt.cs b/src/core/IronPython.Modules/nt.cs
index 773c4634a..dbc80ff0d 100644
--- a/src/core/IronPython.Modules/nt.cs
+++ b/src/core/IronPython.Modules/nt.cs
@@ -1221,7 +1221,7 @@ private static string ArgumentsToString(CodeContext/*!*/ context, object? args,
if (space) {
sb.Append(' ');
}
- if (strarg.IndexOf(' ') != -1) {
+ if (strarg.Contains(' ')) {
sb.Append('"');
// double quote any existing quotes
sb.Append(strarg.Replace("\"", "\"\""));
@@ -2398,7 +2398,7 @@ private static void CheckOptionalArgsCount(int numRegParms, int numOptPosParms,
}
private static void VerifyPath(string path, string functionName, string argName) {
- if (path.IndexOf((char)0) != -1) throw PythonOps.ValueError($"{functionName}: embedded null character in {argName}");
+ if (path.Contains((char)0)) throw PythonOps.ValueError($"{functionName}: embedded null character in {argName}");
}
[SupportedOSPlatform("windows")]
diff --git a/src/core/IronPython.Modules/winsound.cs b/src/core/IronPython.Modules/winsound.cs
index 3231430cb..c9bb99f54 100644
--- a/src/core/IronPython.Modules/winsound.cs
+++ b/src/core/IronPython.Modules/winsound.cs
@@ -90,7 +90,7 @@ public static void PlaySound(CodeContext/*!*/ context, string? sound, int flags)
if (((flags & SND_ASYNC) == SND_ASYNC) && ((flags & SND_MEMORY) == SND_MEMORY)) throw PythonOps.RuntimeError("Cannot play asynchronously from memory");
if ((flags & SND_MEMORY) == SND_MEMORY) throw PythonOps.TypeError($"a bytes-like object is required, not '{PythonOps.GetPythonTypeName(sound)}'");
- if (sound.IndexOf((char)0) != -1) throw PythonOps.ValueError("embedded null character");
+ if (sound.Contains((char)0)) throw PythonOps.ValueError("embedded null character");
if (!PlaySound(sound, IntPtr.Zero, flags)) {
throw PythonOps.RuntimeError("Failed to play sound");
diff --git a/src/core/IronPython/IronPython.csproj b/src/core/IronPython/IronPython.csproj
index f4c66fcf1..9360331b0 100644
--- a/src/core/IronPython/IronPython.csproj
+++ b/src/core/IronPython/IronPython.csproj
@@ -16,9 +16,9 @@
T:System.Diagnostics.CodeAnalysis.NotNullWhenAttribute;
T:System.Runtime.Versioning.SupportedOSPlatformAttribute;
T:System.Runtime.Versioning.UnsupportedOSPlatformAttribute;
- M:System.String.StartsWith(System.Char);
- M:System.String.EndsWith(System.Char);
M:System.String.Contains(System.Char);
+ M:System.String.EndsWith(System.Char);
+ M:System.String.StartsWith(System.Char);
@@ -65,7 +65,7 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/src/core/IronPython/Modules/Builtin.cs b/src/core/IronPython/Modules/Builtin.cs
index b16807d79..92d81bbd9 100644
--- a/src/core/IronPython/Modules/Builtin.cs
+++ b/src/core/IronPython/Modules/Builtin.cs
@@ -206,7 +206,7 @@ public static object compile(CodeContext/*!*/ context, [NotNone] string source,
string sfilename = PythonOps.FsPathDecoded(context, filename);
var sourceCodeKind = ValidateCompileMode(mode);
- if (source.IndexOf('\0') != -1) {
+ if (source.Contains('\0')) {
throw PythonOps.TypeError("compile() expected string without null bytes");
}
diff --git a/src/core/IronPython/Runtime/ClrModule.cs b/src/core/IronPython/Runtime/ClrModule.cs
index e9382f31f..79d47a881 100644
--- a/src/core/IronPython/Runtime/ClrModule.cs
+++ b/src/core/IronPython/Runtime/ClrModule.cs
@@ -193,7 +193,7 @@ object. Namespaces or types in the assembly can be accessed directly from
if (file.Length == 0) throw new ValueErrorException("assembly name must not be empty string");
ContractUtils.RequiresNotNull(context, nameof(context));
- if (file.IndexOf(Path.DirectorySeparatorChar) != -1) {
+ if (file.Contains(Path.DirectorySeparatorChar)) {
throw new ValueErrorException("filenames must not contain full paths, first add the path to sys.path");
}
diff --git a/src/core/IronPython/Runtime/FormattingHelper.cs b/src/core/IronPython/Runtime/FormattingHelper.cs
index 21be97843..8edc383a7 100644
--- a/src/core/IronPython/Runtime/FormattingHelper.cs
+++ b/src/core/IronPython/Runtime/FormattingHelper.cs
@@ -107,9 +107,9 @@ public static NumberFormatInfo InvariantUnderscoreNumberInfo {
// that isn't. After all, it would be pretty weird to produce:
// 000,xxx,xxx,xxx. So, produce 0,000,xxx,xxx,xxx instead.
// (Just like CPython)
- if (separator.IndexOf(res[beginningOfMaximumWidth]) != -1) {
+ if (separator.Contains(res[beginningOfMaximumWidth])) {
for (int i = beginningOfMaximumWidth - 1; i >= 0; i--) {
- if (separator.IndexOf(res[i]) == -1) {
+ if (!separator.Contains(res[i])) {
res.Remove(0, i);
break;
}
diff --git a/src/core/IronPython/Runtime/Importer.cs b/src/core/IronPython/Runtime/Importer.cs
index 824bdf692..973b97c20 100644
--- a/src/core/IronPython/Runtime/Importer.cs
+++ b/src/core/IronPython/Runtime/Importer.cs
@@ -148,7 +148,7 @@ private static object ImportModuleFrom(CodeContext/*!*/ context, object from, Ar
public static object ImportModule(CodeContext/*!*/ context, object globals, string/*!*/ modName, bool bottom, int level) {
if (level < 0) throw PythonOps.ValueError("level must be >= 0");
- if (modName.IndexOf(Path.DirectorySeparatorChar) != -1) {
+ if (modName.Contains(Path.DirectorySeparatorChar)) {
throw PythonOps.ImportError("Import by filename is not supported.");
}
diff --git a/src/core/IronPython/Runtime/LiteralParser.cs b/src/core/IronPython/Runtime/LiteralParser.cs
index 24ac94dfa..3548efdbf 100644
--- a/src/core/IronPython/Runtime/LiteralParser.cs
+++ b/src/core/IronPython/Runtime/LiteralParser.cs
@@ -933,7 +933,7 @@ public static Complex ParseComplex(string s) {
text = text.Trim();
- if (string.IsNullOrEmpty(text) || text.IndexOf(' ') != -1) {
+ if (string.IsNullOrEmpty(text) || text.Contains(' ')) {
throw ExnMalformed();
}
diff --git a/src/core/IronPython/Runtime/MemoryView.cs b/src/core/IronPython/Runtime/MemoryView.cs
index f10b3f2cb..bd6dc75a7 100644
--- a/src/core/IronPython/Runtime/MemoryView.cs
+++ b/src/core/IronPython/Runtime/MemoryView.cs
@@ -516,7 +516,7 @@ public MemoryView cast([NotNone] string format, [NotNone, AllowNull]object shape
}
private static bool IsSupportedTypecode(char code) {
- return ValidCodes.IndexOf(code) >= 0;
+ return ValidCodes.Contains(code);
}
private static void UnpackBytes(char typecode, object o, Span dest) {
diff --git a/src/core/IronPython/Runtime/NewStringFormatter.cs b/src/core/IronPython/Runtime/NewStringFormatter.cs
index fa5278f25..6fdddb86f 100644
--- a/src/core/IronPython/Runtime/NewStringFormatter.cs
+++ b/src/core/IronPython/Runtime/NewStringFormatter.cs
@@ -356,8 +356,7 @@ private string ReplaceText(string format) {
/// spec to compute those values.
///
private string/*!*/ ReplaceComputedFormats(string/*!*/ formatSpec) {
- int computeStart = formatSpec.IndexOf('{');
- if (computeStart != -1) {
+ if (formatSpec.Contains('{')) {
_depth++;
formatSpec = ReplaceText(formatSpec);
_depth--;
diff --git a/src/core/IronPython/Runtime/Operations/FloatOps.cs b/src/core/IronPython/Runtime/Operations/FloatOps.cs
index 51cf840ea..a086f5e62 100644
--- a/src/core/IronPython/Runtime/Operations/FloatOps.cs
+++ b/src/core/IronPython/Runtime/Operations/FloatOps.cs
@@ -760,7 +760,7 @@ internal static string Repr(CodeContext/*!*/ context, double self, bool trailing
// if it's not round trippable though use .NET's round-trip format
res = self.ToString("R", CultureInfo.InvariantCulture);
- if (trailingZeroAfterWholeFloat && res.IndexOf('.') == -1) {
+ if (trailingZeroAfterWholeFloat && !res.Contains('.')) {
res += ".0";
}
return res;
diff --git a/src/core/IronPython/Runtime/Operations/PythonOps.cs b/src/core/IronPython/Runtime/Operations/PythonOps.cs
index 42c7744fb..b3280ab6e 100644
--- a/src/core/IronPython/Runtime/Operations/PythonOps.cs
+++ b/src/core/IronPython/Runtime/Operations/PythonOps.cs
@@ -155,7 +155,7 @@ internal static void RegisterEncodingError(CodeContext/*!*/ context, string name
}
internal static PythonTuple LookupEncoding(CodeContext/*!*/ context, string encoding) {
- if (encoding.IndexOf('\0') != -1) {
+ if (encoding.Contains('\0')) {
throw PythonOps.TypeError("lookup string cannot contain null character");
}
//compute encoding.ToLower().Replace(' ', '-') but ToLower only on ASCII letters
@@ -2109,7 +2109,7 @@ public static object ImportTop(CodeContext/*!*/ context, string fullName, int le
public static object ImportBottom(CodeContext/*!*/ context, string fullName, int level) {
object module = Importer.ImportLightThrow(context, fullName, null, level);
- if (!LightExceptions.IsLightException(module) && fullName.IndexOf('.') >= 0) {
+ if (!LightExceptions.IsLightException(module) && fullName.Contains('.')) {
// Extract bottom from the imported module chain
string[] parts = fullName.Split('.');
diff --git a/src/core/IronPython/Runtime/Operations/StringOps.cs b/src/core/IronPython/Runtime/Operations/StringOps.cs
index f17a210d3..20b8b0f89 100644
--- a/src/core/IronPython/Runtime/Operations/StringOps.cs
+++ b/src/core/IronPython/Runtime/Operations/StringOps.cs
@@ -297,7 +297,7 @@ public static bool __contains__([NotNone] string s, string? item) {
}
public static bool __contains__([NotNone] string s, char item) {
- return s.IndexOf(item) != -1;
+ return s.Contains(item);
}
public static string __format__(CodeContext/*!*/ context, [NotNone] string self, [NotNone] string formatSpec) {
@@ -1520,7 +1520,7 @@ public static string __str__([NotNone] ExtensibleString self) {
internal static string Quote(string s) {
StringBuilder b = new StringBuilder(s.Length + 5);
char quote = '\'';
- if (s.IndexOf('\'') != -1 && s.IndexOf('\"') == -1) {
+ if (s.Contains('\'') && !s.Contains('\"')) {
quote = '\"';
}
b.Append(quote);
diff --git a/src/core/IronPython/Runtime/TypecodeOps.cs b/src/core/IronPython/Runtime/TypecodeOps.cs
index cfd9ed3cf..69be2235f 100644
--- a/src/core/IronPython/Runtime/TypecodeOps.cs
+++ b/src/core/IronPython/Runtime/TypecodeOps.cs
@@ -33,7 +33,7 @@ public static bool TryDecomposeTypecode(string format, out char byteorder, out c
code = format[1];
}
// TODO: add validation of combinations
- return ValidByteorder.IndexOf(byteorder) >= 0 && ValidCodes.IndexOf(code) >= 0;
+ return ValidByteorder.Contains(byteorder) && ValidCodes.Contains(code);
}
public static void DecomposeTypecode(string format, out char byteorder, out char code) {