diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index b8dc201559..99906f0895 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,13 +3,13 @@ "isRoot": true, "tools": { "jetbrains.resharper.globaltools": { - "version": "2022.2.3", + "version": "2023.3.3", "commands": [ "jb" ] }, "nvika": { - "version": "2.2.0", + "version": "3.0.0", "commands": [ "nvika" ] diff --git a/.globalconfig b/.globalconfig index a7b652c454..a4d4707f9b 100644 --- a/.globalconfig +++ b/.globalconfig @@ -1,5 +1,3 @@ -is_global = true - # .NET Code Style # IDE styles reference: https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ @@ -56,4 +54,4 @@ dotnet_diagnostic.RS0030.severity = error # Temporarily disable analysing CanBeNull = true in NRT contexts due to mobile issues. # See: https://github.com/ppy/osu/pull/19677 -dotnet_diagnostic.OSUF001.severity = none \ No newline at end of file +dotnet_diagnostic.OSUF001.severity = none diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestScenePathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestScenePathControlPointVisualiser.cs index 8234381283..2b53554ed1 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestScenePathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestScenePathControlPointVisualiser.cs @@ -206,7 +206,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor { AddStep($"click context menu item \"{contextMenuText}\"", () => { - MenuItem item = visualiser.ContextMenuItems.FirstOrDefault(menuItem => menuItem.Text.Value == "Curve type")?.Items.FirstOrDefault(menuItem => menuItem.Text.Value == contextMenuText); + MenuItem item = visualiser.ContextMenuItems!.FirstOrDefault(menuItem => menuItem.Text.Value == "Curve type")?.Items.FirstOrDefault(menuItem => menuItem.Text.Value == contextMenuText); item?.Action.Value?.Invoke(); }); diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs index eefaa3cae3..28c9d71139 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs @@ -183,7 +183,7 @@ namespace osu.Game.Rulesets.Osu.Tests break; } - hitObjectContainer.Add(drawableObject); + hitObjectContainer.Add(drawableObject!); followPointRenderer.AddFollowPoints(objects[i]); } }); diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs index 09b906cb10..c624fbbe73 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Linq; +using JetBrains.Annotations; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -173,6 +174,7 @@ namespace osu.Game.Rulesets.Osu.Tests public IEnumerable AllSources => new[] { this }; + [CanBeNull] public event Action SourceChanged; private bool enabled = true; diff --git a/osu.Game.Rulesets.Taiko/UI/DrumTouchInputArea.cs b/osu.Game.Rulesets.Taiko/UI/DrumTouchInputArea.cs index 29ccd96675..0b7f6f621a 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrumTouchInputArea.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrumTouchInputArea.cs @@ -179,10 +179,9 @@ namespace osu.Game.Rulesets.Taiko.UI TaikoAction taikoAction = getTaikoActionFromPosition(position); // Not too sure how this can happen, but let's avoid throwing. - if (trackedActions.ContainsKey(source)) + if (!trackedActions.TryAdd(source, taikoAction)) return; - trackedActions.Add(source, taikoAction); keyBindingContainer.TriggerPressed(taikoAction); } diff --git a/osu.Game.Tests/Beatmaps/WorkingBeatmapTest.cs b/osu.Game.Tests/Beatmaps/WorkingBeatmapTest.cs index f4b1028c0e..3c26f8e39a 100644 --- a/osu.Game.Tests/Beatmaps/WorkingBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/WorkingBeatmapTest.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using JetBrains.Annotations; using Moq; using NUnit.Framework; using osu.Game.Beatmaps; @@ -98,9 +99,10 @@ namespace osu.Game.Tests.Beatmaps Beatmap = beatmap; } +#pragma warning disable CS0067 + [CanBeNull] public event Action> ObjectConverted; - - protected virtual void OnObjectConverted(HitObject arg1, IEnumerable arg2) => ObjectConverted?.Invoke(arg1, arg2); +#pragma warning restore CS0067 public IBeatmap Beatmap { get; } diff --git a/osu.Game.Tests/Database/RulesetStoreTests.cs b/osu.Game.Tests/Database/RulesetStoreTests.cs index 8b4c6e2411..ddf207342a 100644 --- a/osu.Game.Tests/Database/RulesetStoreTests.cs +++ b/osu.Game.Tests/Database/RulesetStoreTests.cs @@ -79,7 +79,7 @@ namespace osu.Game.Tests.Database Assert.That(realm.Run(r => r.Find(rulesetShortName)!.Available), Is.True); // Availability is updated on construction of a RealmRulesetStore - var _ = new RealmRulesetStore(realm, storage); + _ = new RealmRulesetStore(realm, storage); Assert.That(realm.Run(r => r.Find(rulesetShortName)!.Available), Is.False); }); @@ -104,13 +104,13 @@ namespace osu.Game.Tests.Database Assert.That(realm.Run(r => r.Find(rulesetShortName)!.Available), Is.True); // Availability is updated on construction of a RealmRulesetStore - var _ = new RealmRulesetStore(realm, storage); + _ = new RealmRulesetStore(realm, storage); Assert.That(realm.Run(r => r.Find(rulesetShortName)!.Available), Is.False); // Simulate the ruleset getting updated LoadTestRuleset.Version = Ruleset.CURRENT_RULESET_API_VERSION; - var __ = new RealmRulesetStore(realm, storage); + _ = new RealmRulesetStore(realm, storage); Assert.That(realm.Run(r => r.Find(rulesetShortName)!.Available), Is.True); }); diff --git a/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs b/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs index 4fb9db845b..61161f3206 100644 --- a/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs +++ b/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs @@ -203,9 +203,9 @@ namespace osu.Game.Tests.Gameplay public IRenderer Renderer => host.Renderer; public AudioManager AudioManager => Audio; - public IResourceStore Files => null; + public IResourceStore Files => null!; public new IResourceStore Resources => base.Resources; - public RealmAccess RealmAccess => null; + public RealmAccess RealmAccess => null!; public IResourceStore CreateTextureLoaderStore(IResourceStore underlyingStore) => null; #endregion diff --git a/osu.Game.Tests/Rulesets/TestSceneBrokenRulesetHandling.cs b/osu.Game.Tests/Rulesets/TestSceneBrokenRulesetHandling.cs index dac6beea65..b378704e80 100644 --- a/osu.Game.Tests/Rulesets/TestSceneBrokenRulesetHandling.cs +++ b/osu.Game.Tests/Rulesets/TestSceneBrokenRulesetHandling.cs @@ -56,9 +56,9 @@ namespace osu.Game.Tests.Rulesets public override IEnumerable GetModsFor(ModType type) => new Mod[] { null }; - public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => null; - public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => null; - public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => null; + public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => null!; + public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => null!; + public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => null!; } private class TestAPIIncompatibleRuleset : Ruleset @@ -69,9 +69,9 @@ namespace osu.Game.Tests.Rulesets // simulate API incompatibility by throwing similar exceptions. public override IEnumerable GetModsFor(ModType type) => throw new MissingMethodException(); - public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => null; - public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => null; - public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => null; + public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => null!; + public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => null!; + public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => null!; } } } diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorTestGameplay.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorTestGameplay.cs index bbd7123f20..ca5e89c8ed 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorTestGameplay.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorTestGameplay.cs @@ -142,7 +142,7 @@ namespace osu.Game.Tests.Visual.Editing AddStep("dismiss prompt", () => { - var button = DialogOverlay.CurrentDialog.Buttons.Last(); + var button = DialogOverlay.CurrentDialog!.Buttons.Last(); InputManager.MoveMouseTo(button); InputManager.Click(MouseButton.Left); }); @@ -167,7 +167,7 @@ namespace osu.Game.Tests.Visual.Editing }); AddUntilStep("save prompt shown", () => DialogOverlay.CurrentDialog is SaveRequiredPopupDialog); - AddStep("save changes", () => DialogOverlay.CurrentDialog.PerformOkAction()); + AddStep("save changes", () => DialogOverlay.CurrentDialog!.PerformOkAction()); EditorPlayer editorPlayer = null; AddUntilStep("player pushed", () => (editorPlayer = Stack.CurrentScreen as EditorPlayer) != null); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs index c51883b221..a7ab021884 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs @@ -120,7 +120,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override void Update() { base.Update(); - playbackManager?.ReplayInputHandler.SetFrameFromTime(Time.Current - 100); + playbackManager?.ReplayInputHandler?.SetFrameFromTime(Time.Current - 100); } [TearDownSteps] diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs index 3a5b3864af..dd5bbf70b4 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs @@ -198,7 +198,7 @@ namespace osu.Game.Tests.Visual.Gameplay foreach (var legacyFrame in frames.Frames) { var frame = new TestReplayFrame(); - frame.FromLegacy(legacyFrame, null); + frame.FromLegacy(legacyFrame, null!); playbackReplay.Frames.Add(frame); } diff --git a/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs b/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs index ce9f80a84f..12d7dde11b 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs @@ -250,7 +250,7 @@ namespace osu.Game.Tests.Visual.Menus { } - public virtual IBindable UnreadCount => null; + public virtual IBindable UnreadCount { get; } = new Bindable(); public IEnumerable AllNotifications => Enumerable.Empty(); } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs index d99d764449..b938e59d63 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs @@ -58,7 +58,7 @@ namespace osu.Game.Tests.Visual.Multiplayer .SkipWhile(r => r.Room.Category.Value == RoomCategory.Spotlight) .All(r => r.Room.Category.Value == RoomCategory.Normal)); - AddStep("remove first room", () => RoomManager.RemoveRoom(RoomManager.Rooms.FirstOrDefault(r => r.RoomID.Value == 0))); + AddStep("remove first room", () => RoomManager.RemoveRoom(RoomManager.Rooms.First(r => r.RoomID.Value == 0))); AddAssert("has 4 rooms", () => container.Rooms.Count == 4); AddAssert("first room removed", () => container.Rooms.All(r => r.Room.RoomID.Value != 0)); diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs index 1053789b27..9f7b20ad43 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs @@ -179,7 +179,7 @@ namespace osu.Game.Tests.Visual.Playlists public IBindable InitialRoomsReceived { get; } = new Bindable(true); - public IBindableList Rooms => null; + public IBindableList Rooms => null!; public void AddOrUpdateRoom(Room room) => throw new NotImplementedException(); diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs index 2f66309f04..1636a3d4b8 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs @@ -52,11 +52,11 @@ namespace osu.Game.Tests.Visual.Playlists [SetUpSteps] public void SetupSteps() { - AddStep("set room", () => SelectedRoom.Value = new Room()); + AddStep("set room", () => SelectedRoom!.Value = new Room()); importBeatmap(); - AddStep("load match", () => LoadScreen(match = new TestPlaylistsRoomSubScreen(SelectedRoom.Value))); + AddStep("load match", () => LoadScreen(match = new TestPlaylistsRoomSubScreen(SelectedRoom!.Value))); AddUntilStep("wait for load", () => match.IsCurrentScreen()); } @@ -115,7 +115,7 @@ namespace osu.Game.Tests.Visual.Playlists }); }); - AddAssert("first playlist item selected", () => match.SelectedItem.Value == SelectedRoom.Value.Playlist[0]); + AddAssert("first playlist item selected", () => match.SelectedItem.Value == SelectedRoom!.Value.Playlist[0]); } [Test] @@ -201,7 +201,7 @@ namespace osu.Game.Tests.Visual.Playlists private void setupAndCreateRoom(Action room) { - AddStep("setup room", () => room(SelectedRoom.Value)); + AddStep("setup room", () => room(SelectedRoom!.Value)); AddStep("click create button", () => { diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs b/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs index 5671cbebd7..685a685896 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs @@ -432,7 +432,7 @@ namespace osu.Game.Tests.Visual.Ranking private class RulesetWithNoPerformanceCalculator : OsuRuleset { - public override PerformanceCalculator CreatePerformanceCalculator() => null; + public override PerformanceCalculator CreatePerformanceCalculator() => null!; } } } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunSetupOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunSetupOverlay.cs index 9275f9755f..51da4d8755 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunSetupOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunSetupOverlay.cs @@ -213,7 +213,7 @@ namespace osu.Game.Tests.Visual.UserInterface { } - public virtual IBindable UnreadCount => null; + public virtual IBindable UnreadCount { get; } = new Bindable(); public IEnumerable AllNotifications => Enumerable.Empty(); } diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 1ee4670ae2..386dada328 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -567,10 +567,9 @@ namespace osu.Game.Beatmaps.Formats for (int i = pendingControlPoints.Count - 1; i >= 0; i--) { var type = pendingControlPoints[i].GetType(); - if (pendingControlPointTypes.Contains(type)) + if (!pendingControlPointTypes.Add(type)) continue; - pendingControlPointTypes.Add(type); beatmap.ControlPointInfo.Add(pendingControlPointsTime, pendingControlPoints[i]); } diff --git a/osu.Game/Beatmaps/WorkingBeatmapCache.cs b/osu.Game/Beatmaps/WorkingBeatmapCache.cs index 2c500146c5..74a85cde7c 100644 --- a/osu.Game/Beatmaps/WorkingBeatmapCache.cs +++ b/osu.Game/Beatmaps/WorkingBeatmapCache.cs @@ -116,7 +116,7 @@ namespace osu.Game.Beatmaps ITrackStore IBeatmapResourceProvider.Tracks => trackStore; IRenderer IStorageResourceProvider.Renderer => host?.Renderer ?? new DummyRenderer(); AudioManager IStorageResourceProvider.AudioManager => audioManager; - RealmAccess IStorageResourceProvider.RealmAccess => null; + RealmAccess IStorageResourceProvider.RealmAccess => null!; IResourceStore IStorageResourceProvider.Files => files; IResourceStore IStorageResourceProvider.Resources => resources; IResourceStore IStorageResourceProvider.CreateTextureLoaderStore(IResourceStore underlyingStore) => host?.CreateTextureLoaderStore(underlyingStore); diff --git a/osu.Game/Graphics/Containers/SelectionCycleFillFlowContainer.cs b/osu.Game/Graphics/Containers/SelectionCycleFillFlowContainer.cs index 62544c6111..098fd7b1ab 100644 --- a/osu.Game/Graphics/Containers/SelectionCycleFillFlowContainer.cs +++ b/osu.Game/Graphics/Containers/SelectionCycleFillFlowContainer.cs @@ -52,10 +52,10 @@ namespace osu.Game.Graphics.Containers public override void Add(T drawable) { - base.Add(drawable); - Debug.Assert(drawable != null); + base.Add(drawable); + drawable.StateChanged += state => selectionChanged(drawable, state); } diff --git a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs index af4b3849af..4af6ce7498 100644 --- a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs +++ b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; using System.Linq; +using JetBrains.Annotations; using osu.Framework.Graphics.Sprites; namespace osu.Game.Graphics.UserInterface @@ -48,6 +49,7 @@ namespace osu.Game.Graphics.UserInterface { protected virtual float ChevronSize => 10; + [CanBeNull] public event Action StateChanged; public readonly SpriteIcon Chevron; diff --git a/osu.Game/IO/IStorageResourceProvider.cs b/osu.Game/IO/IStorageResourceProvider.cs index 08982a8b5f..91760971e8 100644 --- a/osu.Game/IO/IStorageResourceProvider.cs +++ b/osu.Game/IO/IStorageResourceProvider.cs @@ -41,6 +41,6 @@ namespace osu.Game.IO /// /// The underlying provider of texture data (in arbitrary image formats). /// A texture loader store. - IResourceStore CreateTextureLoaderStore(IResourceStore underlyingStore); + IResourceStore? CreateTextureLoaderStore(IResourceStore underlyingStore); } } diff --git a/osu.Game/Online/Spectator/SpectatorClient.cs b/osu.Game/Online/Spectator/SpectatorClient.cs index 7911701853..07ee9115d6 100644 --- a/osu.Game/Online/Spectator/SpectatorClient.cs +++ b/osu.Game/Online/Spectator/SpectatorClient.cs @@ -264,13 +264,12 @@ namespace osu.Game.Online.Spectator { Debug.Assert(ThreadSafety.IsUpdateThread); - if (watchedUsersRefCounts.ContainsKey(userId)) + if (!watchedUsersRefCounts.TryAdd(userId, 1)) { watchedUsersRefCounts[userId]++; return; } - watchedUsersRefCounts.Add(userId, 1); WatchUserInternal(userId); } diff --git a/osu.Game/Overlays/Comments/VotePill.cs b/osu.Game/Overlays/Comments/VotePill.cs index dd418a9e58..8c5aaa062f 100644 --- a/osu.Game/Overlays/Comments/VotePill.cs +++ b/osu.Game/Overlays/Comments/VotePill.cs @@ -30,7 +30,7 @@ namespace osu.Game.Overlays.Comments public Color4 AccentColour { get; set; } - protected override IEnumerable EffectTargets => null; + protected override IEnumerable EffectTargets => Enumerable.Empty(); [Resolved] private IAPIProvider api { get; set; } diff --git a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs index a25147b69f..f4f6fd2bc1 100644 --- a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs +++ b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs @@ -4,6 +4,7 @@ #nullable disable using System; +using JetBrains.Annotations; using osu.Framework; using osuTK; using osu.Framework.Allocation; @@ -24,6 +25,7 @@ namespace osu.Game.Overlays.MedalSplash private const float scale_when_unlocked = 0.76f; private const float scale_when_full = 0.6f; + [CanBeNull] public event Action StateChanged; private readonly Medal medal; diff --git a/osu.Game/Overlays/Volume/VolumeMeter.cs b/osu.Game/Overlays/Volume/VolumeMeter.cs index 9ca4c25ab9..6ec4971f06 100644 --- a/osu.Game/Overlays/Volume/VolumeMeter.cs +++ b/osu.Game/Overlays/Volume/VolumeMeter.cs @@ -5,6 +5,7 @@ using System; using System.Globalization; +using JetBrains.Annotations; using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -48,6 +49,7 @@ namespace osu.Game.Overlays.Volume private Sample notchSample; private double sampleLastPlaybackTime; + [CanBeNull] public event Action StateChanged; private SelectionState state; diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 5662fb2293..161537200a 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -11,6 +11,7 @@ using System.Linq; using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Extensions.TypeExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Primitives; @@ -139,7 +140,7 @@ namespace osu.Game.Rulesets.Objects.Drawables protected override bool RequiresChildrenUpdate => true; - public override bool IsPresent => base.IsPresent || (State.Value == ArmedState.Idle && Clock?.CurrentTime >= LifetimeStart); + public override bool IsPresent => base.IsPresent || (State.Value == ArmedState.Idle && Clock.IsNotNull() && Clock.CurrentTime >= LifetimeStart); private readonly Bindable state = new Bindable(); diff --git a/osu.Game/Rulesets/Objects/Pooling/HitObjectEntryManager.cs b/osu.Game/Rulesets/Objects/Pooling/HitObjectEntryManager.cs index fabf4fc444..7977166cb2 100644 --- a/osu.Game/Rulesets/Objects/Pooling/HitObjectEntryManager.cs +++ b/osu.Game/Rulesets/Objects/Pooling/HitObjectEntryManager.cs @@ -47,12 +47,9 @@ namespace osu.Game.Rulesets.Objects.Pooling { HitObject hitObject = entry.HitObject; - if (entryMap.ContainsKey(hitObject)) + if (!entryMap.TryAdd(hitObject, entry)) throw new InvalidOperationException($@"The {nameof(HitObjectLifetimeEntry)} is already added to this {nameof(HitObjectEntryManager)}."); - // Add the entry. - entryMap[hitObject] = entry; - // If the entry has a parent, set it and add the entry to the parent's children. if (parent != null) { diff --git a/osu.Game/Screens/Edit/Compose/Components/DragBox.cs b/osu.Game/Screens/Edit/Compose/Components/DragBox.cs index 4d1f81228e..b83e565e89 100644 --- a/osu.Game/Screens/Edit/Compose/Components/DragBox.cs +++ b/osu.Game/Screens/Edit/Compose/Components/DragBox.cs @@ -4,6 +4,7 @@ #nullable disable using System; +using JetBrains.Annotations; using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -69,6 +70,7 @@ namespace osu.Game.Screens.Edit.Compose.Components public override void Show() => State = Visibility.Visible; + [CanBeNull] public event Action StateChanged; public partial class BoxWithBorders : CompositeDrawable diff --git a/osu.Game/Screens/Menu/ButtonArea.cs b/osu.Game/Screens/Menu/ButtonArea.cs index 69ba68442f..4eb91c526f 100644 --- a/osu.Game/Screens/Menu/ButtonArea.cs +++ b/osu.Game/Screens/Menu/ButtonArea.cs @@ -4,6 +4,7 @@ #nullable disable using System; +using JetBrains.Annotations; using osu.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -88,6 +89,7 @@ namespace osu.Game.Screens.Menu public override void Show() => State = Visibility.Visible; + [CanBeNull] public event Action StateChanged; private partial class ButtonAreaBackground : Box, IStateful @@ -146,6 +148,7 @@ namespace osu.Game.Screens.Menu } } + [CanBeNull] public event Action StateChanged; } diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs b/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs index e892f9280f..cb27d1ee61 100644 --- a/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs +++ b/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Development; @@ -19,6 +20,7 @@ namespace osu.Game.Screens.OnlinePlay.Components { public partial class RoomManager : Component, IRoomManager { + [CanBeNull] public event Action RoomsUpdated; private readonly BindableList rooms = new BindableList(); diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index f35b205bc4..4c0219eff5 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -509,7 +509,7 @@ namespace osu.Game.Screens.OnlinePlay.Match private void cancelTrackLooping() { - var track = Beatmap?.Value?.Track; + var track = Beatmap.Value?.Track; if (track != null) track.Looping = false; diff --git a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs index 1cf3d25dad..a260156595 100644 --- a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs +++ b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs @@ -109,7 +109,7 @@ namespace osu.Game.Screens.Play.HUD protected override bool OnMouseMove(MouseMoveEvent e) { - positionalAdjust = Vector2.Distance(e.MousePosition, button.ToSpaceOfOtherDrawable(button.DrawRectangle.Centre, Parent)) / 100; + positionalAdjust = Vector2.Distance(e.MousePosition, button.ToSpaceOfOtherDrawable(button.DrawRectangle.Centre, Parent!)) / 100; return base.OnMouseMove(e); } diff --git a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs index 93c6e72aa2..54c5b578e6 100644 --- a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs +++ b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs @@ -20,7 +20,7 @@ namespace osu.Game.Tests.Visual.Multiplayer public TestMultiplayerClient MultiplayerClient => OnlinePlayDependencies.MultiplayerClient; public new TestMultiplayerRoomManager RoomManager => OnlinePlayDependencies.RoomManager; - public TestSpectatorClient SpectatorClient => OnlinePlayDependencies?.SpectatorClient; + public TestSpectatorClient SpectatorClient => OnlinePlayDependencies.SpectatorClient; protected new MultiplayerTestSceneDependencies OnlinePlayDependencies => (MultiplayerTestSceneDependencies)base.OnlinePlayDependencies; @@ -57,7 +57,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("join room", () => { - SelectedRoom.Value = CreateRoom(); + SelectedRoom!.Value = CreateRoom(); RoomManager.CreateRoom(SelectedRoom.Value); }); diff --git a/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestSceneDependencies.cs b/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestSceneDependencies.cs index 3509519113..eb5184353a 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestSceneDependencies.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestSceneDependencies.cs @@ -16,31 +16,31 @@ namespace osu.Game.Tests.Visual.OnlinePlay /// /// The cached . /// - Bindable SelectedRoom { get; } + Bindable? SelectedRoom { get; } /// /// The cached /// - IRoomManager RoomManager { get; } + IRoomManager? RoomManager { get; } /// /// The cached . /// - OngoingOperationTracker OngoingOperationTracker { get; } + OngoingOperationTracker? OngoingOperationTracker { get; } /// /// The cached . /// - OnlinePlayBeatmapAvailabilityTracker AvailabilityTracker { get; } + OnlinePlayBeatmapAvailabilityTracker? AvailabilityTracker { get; } /// /// The cached . /// - TestUserLookupCache UserLookupCache { get; } + TestUserLookupCache? UserLookupCache { get; } /// /// The cached . /// - BeatmapLookupCache BeatmapLookupCache { get; } + BeatmapLookupCache? BeatmapLookupCache { get; } } } diff --git a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs index 87488710a7..0118d60dca 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -22,23 +20,23 @@ namespace osu.Game.Tests.Visual.OnlinePlay /// public abstract partial class OnlinePlayTestScene : ScreenTestScene, IOnlinePlayTestSceneDependencies { - public Bindable SelectedRoom => OnlinePlayDependencies?.SelectedRoom; - public IRoomManager RoomManager => OnlinePlayDependencies?.RoomManager; - public OngoingOperationTracker OngoingOperationTracker => OnlinePlayDependencies?.OngoingOperationTracker; - public OnlinePlayBeatmapAvailabilityTracker AvailabilityTracker => OnlinePlayDependencies?.AvailabilityTracker; - public TestUserLookupCache UserLookupCache => OnlinePlayDependencies?.UserLookupCache; - public BeatmapLookupCache BeatmapLookupCache => OnlinePlayDependencies?.BeatmapLookupCache; + public Bindable SelectedRoom => OnlinePlayDependencies.SelectedRoom; + public IRoomManager RoomManager => OnlinePlayDependencies.RoomManager; + public OngoingOperationTracker OngoingOperationTracker => OnlinePlayDependencies.OngoingOperationTracker; + public OnlinePlayBeatmapAvailabilityTracker AvailabilityTracker => OnlinePlayDependencies.AvailabilityTracker; + public TestUserLookupCache UserLookupCache => OnlinePlayDependencies.UserLookupCache; + public BeatmapLookupCache BeatmapLookupCache => OnlinePlayDependencies.BeatmapLookupCache; /// /// All dependencies required for online play components and screens. /// - protected OnlinePlayTestSceneDependencies OnlinePlayDependencies => dependencies?.OnlinePlayDependencies; + protected OnlinePlayTestSceneDependencies OnlinePlayDependencies => dependencies.OnlinePlayDependencies; protected override Container Content => content; private readonly Container content; private readonly Container drawableDependenciesContainer; - private DelegatedDependencyContainer dependencies; + private DelegatedDependencyContainer dependencies = null!; protected OnlinePlayTestScene() { @@ -51,8 +49,10 @@ namespace osu.Game.Tests.Visual.OnlinePlay protected sealed override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { - dependencies = new DelegatedDependencyContainer(base.CreateChildDependencies(parent)); - return dependencies; + return dependencies = new DelegatedDependencyContainer(base.CreateChildDependencies(parent)) + { + OnlinePlayDependencies = initDependencies() + }; } public override void SetUpSteps() @@ -62,9 +62,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay AddStep("setup dependencies", () => { // Reset the room dependencies to a fresh state. - drawableDependenciesContainer.Clear(); - dependencies.OnlinePlayDependencies = CreateOnlinePlayDependencies(); - drawableDependenciesContainer.AddRange(OnlinePlayDependencies.DrawableComponents); + dependencies.OnlinePlayDependencies = initDependencies(); var handler = OnlinePlayDependencies.RequestsHandler; @@ -90,6 +88,14 @@ namespace osu.Game.Tests.Visual.OnlinePlay }); } + private OnlinePlayTestSceneDependencies initDependencies() + { + var newDependencies = CreateOnlinePlayDependencies(); + drawableDependenciesContainer.Clear(); + drawableDependenciesContainer.AddRange(newDependencies.DrawableComponents); + return newDependencies; + } + /// /// Creates the room dependencies. Called every . /// @@ -106,7 +112,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay /// /// The online play dependencies. /// - public OnlinePlayTestSceneDependencies OnlinePlayDependencies { get; set; } + public OnlinePlayTestSceneDependencies OnlinePlayDependencies { get; set; } = null!; private readonly IReadOnlyDependencyContainer parent; private readonly DependencyContainer injectableDependencies; @@ -122,10 +128,10 @@ namespace osu.Game.Tests.Visual.OnlinePlay } public object Get(Type type) - => OnlinePlayDependencies?.Get(type) ?? parent.Get(type); + => OnlinePlayDependencies.Get(type) ?? parent.Get(type); public object Get(Type type, CacheInfo info) - => OnlinePlayDependencies?.Get(type, info) ?? parent.Get(type, info); + => OnlinePlayDependencies.Get(type, info) ?? parent.Get(type, info); public void Inject(T instance) where T : class, IDependencyInjectionCandidate diff --git a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs index 975423d19b..64bd27b871 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs @@ -56,10 +56,10 @@ namespace osu.Game.Tests.Visual.OnlinePlay CacheAs(BeatmapLookupCache); } - public object Get(Type type) + public object? Get(Type type) => dependencies.Get(type); - public object Get(Type type, CacheInfo info) + public object? Get(Type type, CacheInfo info) => dependencies.Get(type, info); public void Inject(T instance) diff --git a/osu.Game/Tests/Visual/SkinnableTestScene.cs b/osu.Game/Tests/Visual/SkinnableTestScene.cs index f371cf721f..c9acfa0ee5 100644 --- a/osu.Game/Tests/Visual/SkinnableTestScene.cs +++ b/osu.Game/Tests/Visual/SkinnableTestScene.cs @@ -171,10 +171,10 @@ namespace osu.Game.Tests.Visual public IRenderer Renderer => host.Renderer; public AudioManager AudioManager => Audio; - public IResourceStore Files => null; + public IResourceStore Files => null!; public new IResourceStore Resources => base.Resources; public IResourceStore CreateTextureLoaderStore(IResourceStore underlyingStore) => host.CreateTextureLoaderStore(underlyingStore); - RealmAccess IStorageResourceProvider.RealmAccess => null; + RealmAccess IStorageResourceProvider.RealmAccess => null!; #endregion diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index c8c5d6745c..1bf8aa7b0b 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -66,6 +66,7 @@ HINT WARNING DO_NOT_SHOW + HINT WARNING WARNING WARNING @@ -81,6 +82,7 @@ WARNING WARNING HINT + HINT WARNING HINT DO_NOT_SHOW @@ -165,6 +167,7 @@ WARNING WARNING WARNING + HINT WARNING WARNING WARNING @@ -251,6 +254,7 @@ HINT DO_NOT_SHOW WARNING + HINT WARNING WARNING WARNING @@ -263,6 +267,7 @@ WARNING WARNING WARNING + HINT WARNING HINT HINT