diff --git a/.editorconfig b/.editorconfig
index edd8742bc6..bd22b2b4cb 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -1263,3 +1263,24 @@ dotnet_diagnostic.RCS1239.severity = warning
# Use element access.
dotnet_diagnostic.RCS1246.severity = warning
+
+# Use enum field explicitly.
+dotnet_diagnostic.RCS1257.severity = warning
+
+# Unnecessary enum flag.
+dotnet_diagnostic.RCS1258.severity = warning
+
+# Resource can be disposed asynchronously.
+dotnet_diagnostic.RCS1261.severity = warning
+
+# Unnecessary raw string literal.
+dotnet_diagnostic.RCS1262.severity = warning
+
+# Remove redundant catch block.
+dotnet_diagnostic.RCS1265.severity = warning
+
+# Use raw string literal.
+dotnet_diagnostic.RCS1266.severity = warning
+
+# Use string interpolation instead of 'string.Concat'.
+dotnet_diagnostic.RCS1267.severity = warning
diff --git a/Directory.Build.props b/Directory.Build.props
index cdcb750c17..98881ac904 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -53,7 +53,7 @@
-
-
+
+
diff --git a/OpenRA.Game/FileSystem/Folder.cs b/OpenRA.Game/FileSystem/Folder.cs
index 86ce46983f..371bfb20c1 100644
--- a/OpenRA.Game/FileSystem/Folder.cs
+++ b/OpenRA.Game/FileSystem/Folder.cs
@@ -35,7 +35,7 @@ namespace OpenRA.FileSystem
return Directory.GetFiles(Name, "*", SearchOption.TopDirectoryOnly)
.Concat(Directory.GetDirectories(Name))
.Select(Path.GetFileName)
- .OrderBy(f => f);
+ .Order();
}
}
diff --git a/OpenRA.Game/Game.cs b/OpenRA.Game/Game.cs
index 21da88f9ac..683a75f8b4 100644
--- a/OpenRA.Game/Game.cs
+++ b/OpenRA.Game/Game.cs
@@ -408,7 +408,7 @@ namespace OpenRA
// Sanitize input from platform-specific launchers
// Process.Start requires paths to not be quoted, even if they contain spaces
- if (launchPath != null && launchPath[0] == '"' && launchPath.Last() == '"')
+ if (launchPath != null && launchPath[0] == '"' && launchPath[^1] == '"')
launchPath = launchPath[1..^1];
// Metadata registration requires an explicit launch path
@@ -584,7 +584,7 @@ namespace OpenRA
Directory.CreateDirectory(directory);
var filename = TimestampedFilename(true);
- var path = Path.Combine(directory, string.Concat(filename, ".png"));
+ var path = Path.Combine(directory, $"{filename}.png");
Log.Write("debug", "Taking screenshot " + path);
Renderer.SaveScreenshot(path);
diff --git a/OpenRA.Game/HttpExtension.cs b/OpenRA.Game/HttpExtension.cs
index 5bba955e7b..30cf06789c 100644
--- a/OpenRA.Game/HttpExtension.cs
+++ b/OpenRA.Game/HttpExtension.cs
@@ -26,7 +26,7 @@ namespace OpenRA
var total = response.Content.Headers.ContentLength ?? -1;
var canReportProgress = total > 0;
- using (var contentStream = await response.Content.ReadAsStreamAsync(token))
+ await using (var contentStream = await response.Content.ReadAsStreamAsync(token))
{
var totalRead = 0L;
var buffer = new byte[8192];
diff --git a/OpenRA.Mods.Cnc/AudioLoaders/VocLoader.cs b/OpenRA.Mods.Cnc/AudioLoaders/VocLoader.cs
index bb684d4810..d9095d046b 100644
--- a/OpenRA.Mods.Cnc/AudioLoaders/VocLoader.cs
+++ b/OpenRA.Mods.Cnc/AudioLoaders/VocLoader.cs
@@ -12,7 +12,6 @@
using System;
using System.Collections.Generic;
using System.IO;
-using System.Linq;
using OpenRA.Primitives;
namespace OpenRA.Mods.Cnc.AudioLoaders
@@ -186,7 +185,7 @@ namespace OpenRA.Mods.Cnc.AudioLoaders
// See if last block contained additional information
if (blockList.Count > 0)
{
- var b = blockList.Last();
+ var b = blockList[^1];
if (b.Code == 8)
{
block.SampleBlock.Rate = b.SampleBlock.Rate;
diff --git a/OpenRA.Mods.Cnc/FileFormats/IdxEntry.cs b/OpenRA.Mods.Cnc/FileFormats/IdxEntry.cs
index ae7fac664c..5228572a5b 100644
--- a/OpenRA.Mods.Cnc/FileFormats/IdxEntry.cs
+++ b/OpenRA.Mods.Cnc/FileFormats/IdxEntry.cs
@@ -29,7 +29,7 @@ namespace OpenRA.Mods.Cnc.FileFormats
if (pos != 0)
name = name[..pos];
- Filename = string.Concat(name, ".wav");
+ Filename = $"{name}.wav";
Offset = s.ReadUInt32();
Length = s.ReadUInt32();
SampleRate = s.ReadUInt32();
diff --git a/OpenRA.Mods.Cnc/UtilityCommands/ConvertPngToShpCommand.cs b/OpenRA.Mods.Cnc/UtilityCommands/ConvertPngToShpCommand.cs
index 79fba50415..718726ba26 100644
--- a/OpenRA.Mods.Cnc/UtilityCommands/ConvertPngToShpCommand.cs
+++ b/OpenRA.Mods.Cnc/UtilityCommands/ConvertPngToShpCommand.cs
@@ -32,7 +32,7 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
[Desc("PNGFILE [PNGFILE ...]", "Combine a list of PNG images into a SHP")]
void IUtilityCommand.Run(Utility utility, string[] args)
{
- var inputFiles = GlobArgs(args).OrderBy(a => a).ToList();
+ var inputFiles = GlobArgs(args).Order().ToList();
var dest = inputFiles[0].Split('-').First() + ".shp";
var frames = inputFiles.ConvertAll(a => new Png(File.OpenRead(a)));
diff --git a/OpenRA.Mods.Cnc/UtilityCommands/LegacyRulesImporter.cs b/OpenRA.Mods.Cnc/UtilityCommands/LegacyRulesImporter.cs
index ba6bfae45f..482ce760f4 100644
--- a/OpenRA.Mods.Cnc/UtilityCommands/LegacyRulesImporter.cs
+++ b/OpenRA.Mods.Cnc/UtilityCommands/LegacyRulesImporter.cs
@@ -139,7 +139,7 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
if (!string.IsNullOrEmpty(foundation))
{
var dimensions = foundation.Split('x');
- if (dimensions[0] == "0" || dimensions.Last() == "0")
+ if (dimensions[0] == "0" || dimensions[^1] == "0")
Console.WriteLine("\tImmobile:\n \t\tOccupiesSpace: False");
else
{
@@ -149,11 +149,11 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
if (!string.IsNullOrEmpty(adjacent))
Console.WriteLine("\t\tAdjacent: " + adjacent);
- Console.WriteLine("\t\tDimensions: " + dimensions[0] + "," + dimensions.Last());
+ Console.WriteLine("\t\tDimensions: " + dimensions[0] + "," + dimensions[^1]);
Console.Write("\t\tFootprint:");
int.TryParse(dimensions[0], out var width);
- int.TryParse(dimensions.Last(), out var height);
+ int.TryParse(dimensions[^1], out var height);
for (var y = 0; y < height; y++)
{
Console.Write(" ");
diff --git a/OpenRA.Mods.Cnc/VideoLoaders/WsaLoader.cs b/OpenRA.Mods.Cnc/VideoLoaders/WsaLoader.cs
index 074b3f814f..10a312a436 100644
--- a/OpenRA.Mods.Cnc/VideoLoaders/WsaLoader.cs
+++ b/OpenRA.Mods.Cnc/VideoLoaders/WsaLoader.cs
@@ -10,7 +10,6 @@
#endregion
using System.IO;
-using System.Linq;
using OpenRA.Mods.Cnc.FileFormats;
using OpenRA.Video;
@@ -65,7 +64,7 @@ namespace OpenRA.Mods.Cnc.VideoLoaders
s.Position = start;
- return s.Length == offsets.Last();
+ return s.Length == offsets[^1];
}
}
}
diff --git a/OpenRA.Mods.Common/Commands/HelpCommand.cs b/OpenRA.Mods.Common/Commands/HelpCommand.cs
index 8d8e814d32..388f8473ce 100644
--- a/OpenRA.Mods.Common/Commands/HelpCommand.cs
+++ b/OpenRA.Mods.Common/Commands/HelpCommand.cs
@@ -54,7 +54,7 @@ namespace OpenRA.Mods.Common.Commands
{
TextNotificationsManager.Debug(FluentProvider.GetMessage(AvailableCommands));
- foreach (var key in console.Commands.Keys.OrderBy(k => k))
+ foreach (var key in console.Commands.Keys.Order())
{
if (!helpDescriptions.TryGetValue(key, out var description))
description = FluentProvider.GetMessage(NoDescription);
diff --git a/OpenRA.Mods.Common/Effects/RallyPointIndicator.cs b/OpenRA.Mods.Common/Effects/RallyPointIndicator.cs
index 2f2dc0a094..c44e9dcf93 100644
--- a/OpenRA.Mods.Common/Effects/RallyPointIndicator.cs
+++ b/OpenRA.Mods.Common/Effects/RallyPointIndicator.cs
@@ -96,10 +96,10 @@ namespace OpenRA.Mods.Common.Effects
{
var palette = wr.Palette(rp.PaletteName);
if (circles != null)
- renderables = renderables.Concat(circles.Render(targetLineNodes.Last(), palette));
+ renderables = renderables.Concat(circles.Render(targetLineNodes[^1], palette));
if (flag != null)
- renderables = renderables.Concat(flag.Render(targetLineNodes.Last(), palette));
+ renderables = renderables.Concat(flag.Render(targetLineNodes[^1], palette));
}
return renderables;
diff --git a/OpenRA.Mods.Common/Scripting/Global/ReinforcementsGlobal.cs b/OpenRA.Mods.Common/Scripting/Global/ReinforcementsGlobal.cs
index b05f9dcf3d..adc7ffa8f3 100644
--- a/OpenRA.Mods.Common/Scripting/Global/ReinforcementsGlobal.cs
+++ b/OpenRA.Mods.Common/Scripting/Global/ReinforcementsGlobal.cs
@@ -163,7 +163,7 @@ namespace OpenRA.Mods.Common.Scripting
// Scripted cargo aircraft must turn to default position before unloading.
// TODO: pass facing through UnloadCargo instead.
if (aircraft != null)
- transport.QueueActivity(new Land(transport, Target.FromCell(transport.World, entryPath.Last()), WDist.FromCells(dropRange)));
+ transport.QueueActivity(new Land(transport, Target.FromCell(transport.World, entryPath[^1]), WDist.FromCells(dropRange)));
if (cargo != null)
transport.QueueActivity(new UnloadCargo(transport, WDist.FromCells(dropRange)));
diff --git a/OpenRA.Mods.Common/Scripting/Properties/ProductionProperties.cs b/OpenRA.Mods.Common/Scripting/Properties/ProductionProperties.cs
index 4ef6437f8f..bdc4c3fc53 100644
--- a/OpenRA.Mods.Common/Scripting/Properties/ProductionProperties.cs
+++ b/OpenRA.Mods.Common/Scripting/Properties/ProductionProperties.cs
@@ -84,7 +84,7 @@ namespace OpenRA.Mods.Common.Scripting
get
{
if (rp.Path.Count > 0)
- return rp.Path.Last();
+ return rp.Path[^1];
var exit = Self.NearestExitOrDefault(Self.CenterPosition);
if (exit != null)
diff --git a/OpenRA.Mods.Common/Traits/Cargo.cs b/OpenRA.Mods.Common/Traits/Cargo.cs
index d16b34c9ca..e8ed69b253 100644
--- a/OpenRA.Mods.Common/Traits/Cargo.cs
+++ b/OpenRA.Mods.Common/Traits/Cargo.cs
@@ -331,11 +331,11 @@ namespace OpenRA.Mods.Common.Traits
public bool HasSpace(int weight) { return totalWeight + reservedWeight + weight <= Info.MaxWeight; }
public bool IsEmpty() { return cargo.Count == 0; }
- public Actor Peek() { return cargo.Last(); }
+ public Actor Peek() { return cargo[^1]; }
public Actor Unload(Actor self, Actor passenger = null)
{
- passenger ??= cargo.Last();
+ passenger ??= cargo[^1];
if (!cargo.Remove(passenger))
throw new ArgumentException("Attempted to unload an actor that is not a passenger.");
diff --git a/OpenRA.Mods.Common/Traits/DockClientManager.cs b/OpenRA.Mods.Common/Traits/DockClientManager.cs
index 880f5f15d2..5b195081e7 100644
--- a/OpenRA.Mods.Common/Traits/DockClientManager.cs
+++ b/OpenRA.Mods.Common/Traits/DockClientManager.cs
@@ -373,7 +373,7 @@ namespace OpenRA.Mods.Common.Traits
});
if (path.Count > 0)
- return lookup[path.Last()];
+ return lookup[path[^1]];
}
else
{
diff --git a/OpenRA.Mods.Common/Traits/Player/GrantConditionOnPrerequisiteManager.cs b/OpenRA.Mods.Common/Traits/Player/GrantConditionOnPrerequisiteManager.cs
index 12f146871b..6b03706515 100644
--- a/OpenRA.Mods.Common/Traits/Player/GrantConditionOnPrerequisiteManager.cs
+++ b/OpenRA.Mods.Common/Traits/Player/GrantConditionOnPrerequisiteManager.cs
@@ -36,7 +36,7 @@ namespace OpenRA.Mods.Common.Traits
static string MakeKey(string[] prerequisites)
{
- return "condition_" + string.Join("_", prerequisites.OrderBy(a => a));
+ return "condition_" + string.Join("_", prerequisites.Order());
}
public void Register(Actor actor, GrantConditionOnPrerequisite u, string[] prerequisites)
diff --git a/OpenRA.Mods.Common/Traits/World/RaMapGenerator.cs b/OpenRA.Mods.Common/Traits/World/RaMapGenerator.cs
index 4a740039dd..eecfe8c013 100644
--- a/OpenRA.Mods.Common/Traits/World/RaMapGenerator.cs
+++ b/OpenRA.Mods.Common/Traits/World/RaMapGenerator.cs
@@ -477,7 +477,7 @@ namespace OpenRA.Mods.Common.Traits
{
var types = typeWeights
.Select(kv => kv.Key)
- .OrderBy(k => k)
+ .Order()
.ToArray();
var weights = types
.Select(type => typeWeights[type])
diff --git a/OpenRA.Mods.Common/Widgets/Logic/Editor/ActorSelectorLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Editor/ActorSelectorLogic.cs
index 6ee42c3531..1ab8480232 100644
--- a/OpenRA.Mods.Common/Widgets/Logic/Editor/ActorSelectorLogic.cs
+++ b/OpenRA.Mods.Common/Widgets/Logic/Editor/ActorSelectorLogic.cs
@@ -129,7 +129,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
allCategories = allActors.SelectMany(ac => ac.Categories)
.Distinct()
- .OrderBy(x => x)
+ .Order()
.ToArray();
foreach (var c in allCategories)
@@ -149,7 +149,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
s => s.Contains(searchFilter, StringComparison.CurrentCultureIgnoreCase)))
.SelectMany(t => t.Categories)
.Distinct()
- .OrderBy(x => x));
+ .Order());
else
FilteredCategories.AddRange(allCategories);
diff --git a/OpenRA.Mods.Common/Widgets/Logic/Installation/DownloadPackageLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Installation/DownloadPackageLogic.cs
index c3432cae10..56eca67cc2 100644
--- a/OpenRA.Mods.Common/Widgets/Logic/Installation/DownloadPackageLogic.cs
+++ b/OpenRA.Mods.Common/Widgets/Logic/Installation/DownloadPackageLogic.cs
@@ -191,7 +191,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
return;
}
- using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.ReadWrite, 8192, true))
+ await using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.ReadWrite, 8192, true))
{
await response.ReadAsStreamWithProgress(fileStream, OnDownloadProgress, token);
}
@@ -205,7 +205,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
var archiveValid = false;
try
{
- using (var stream = File.OpenRead(file))
+ await using (var stream = File.OpenRead(file))
{
var archiveSHA1 = CryptoUtil.SHA1Hash(stream);
Log.Write("install", "Downloaded SHA1: " + archiveSHA1);
@@ -233,7 +233,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
var extracted = new List();
try
{
- using (var stream = File.OpenRead(file))
+ await using (var stream = File.OpenRead(file))
{
var packageLoader = modData.ObjectCreator.CreateObject($"{download.Type}Loader");
@@ -253,8 +253,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
Directory.CreateDirectory(Path.GetDirectoryName(targetPath));
extracted.Add(targetPath);
- using (var zz = package.GetStream(kv.Value))
- using (var f = File.Create(targetPath))
+ await using (var zz = package.GetStream(kv.Value))
+ await using (var f = File.Create(targetPath))
await zz.CopyToAsync(f);
}
diff --git a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs
index 5a15e610eb..01aed4fe5a 100644
--- a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs
+++ b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs
@@ -887,7 +887,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
if (orderManager.LobbyInfo.GlobalSettings.Dedicated)
{
var endpoint = CurrentServerSettings.Target.GetConnectEndPoints().First();
- secret = string.Concat(endpoint.Address, "|", endpoint.Port);
+ secret = $"{endpoint.Address}|{endpoint.Port}";
}
var state = skirmishMode ? DiscordState.InSkirmishLobby : DiscordState.InMultiplayerLobby;
diff --git a/OpenRA.Test/OpenRA.Game/PriorityQueueTest.cs b/OpenRA.Test/OpenRA.Game/PriorityQueueTest.cs
index aa700b6afe..2f024006c1 100644
--- a/OpenRA.Test/OpenRA.Game/PriorityQueueTest.cs
+++ b/OpenRA.Test/OpenRA.Game/PriorityQueueTest.cs
@@ -112,7 +112,7 @@ namespace OpenRA.Test
Assert.That(queue.Empty, Is.False, "Queue should not be empty - items have been added.");
}
- foreach (var value in shuffledValues.Take(10).OrderBy(x => x).Take(5))
+ foreach (var value in shuffledValues.Take(10).Order().Take(5))
{
Assert.That(value, Is.EqualTo(queue.Peek()), "Peek returned the wrong item - should be in order.");
Assert.That(queue.Empty, Is.False, "Queue should not be empty yet.");
@@ -125,8 +125,8 @@ namespace OpenRA.Test
Assert.That(queue.Empty, Is.False, "Queue should not be empty - items have been added.");
}
- foreach (var value in shuffledValues.Take(10).OrderBy(x => x).Skip(5)
- .Concat(shuffledValues.Skip(10).Take(5)).OrderBy(x => x).Take(5))
+ foreach (var value in shuffledValues.Take(10).Order().Skip(5)
+ .Concat(shuffledValues.Skip(10).Take(5)).Order().Take(5))
{
Assert.That(value, Is.EqualTo(queue.Peek()), "Peek returned the wrong item - should be in order.");
Assert.That(queue.Empty, Is.False, "Queue should not be empty yet.");
@@ -139,9 +139,9 @@ namespace OpenRA.Test
Assert.That(queue.Empty, Is.False, "Queue should not be empty - items have been added.");
}
- foreach (var value in shuffledValues.Take(10).OrderBy(x => x).Skip(5)
- .Concat(shuffledValues.Skip(10).Take(5)).OrderBy(x => x).Skip(5)
- .Concat(shuffledValues.Skip(15)).OrderBy(x => x))
+ foreach (var value in shuffledValues.Take(10).Order().Skip(5)
+ .Concat(shuffledValues.Skip(10).Take(5)).Order().Skip(5)
+ .Concat(shuffledValues.Skip(15)).Order())
{
Assert.That(value, Is.EqualTo(queue.Peek()), "Peek returned the wrong item - should be in order.");
Assert.That(queue.Empty, Is.False, "Queue should not be empty yet.");
diff --git a/OpenRA.Utility/Program.cs b/OpenRA.Utility/Program.cs
index f7abf5a36b..4095ed90d0 100644
--- a/OpenRA.Utility/Program.cs
+++ b/OpenRA.Utility/Program.cs
@@ -152,7 +152,7 @@ namespace OpenRA
if (actions == null)
return;
- var keys = actions.Keys.OrderBy(x => x);
+ var keys = actions.Keys.Order();
foreach (var key in keys)
{