OSDN Git Service

C# 8.0 のnull許容参照型を有効化
authorKimura Youichi <kim.upsilon@bucyou.net>
Thu, 15 Aug 2019 20:49:11 +0000 (05:49 +0900)
committerKimura Youichi <kim.upsilon@bucyou.net>
Fri, 30 Aug 2019 18:49:16 +0000 (03:49 +0900)
190 files changed:
OpenTween.Tests/Api/ApiLimitTest.cs
OpenTween.Tests/Api/TwitterApiStatusTest.cs
OpenTween.Tests/Connection/TwitterApiConnectionTest.cs
OpenTween.Tests/ExtensionsTest.cs
OpenTween.Tests/IndexedSortedSetTest.cs
OpenTween.Tests/LRUCacheDictionaryTest.cs
OpenTween.Tests/MediaSelectorTest.cs
OpenTween.Tests/Models/PostClassTest.cs
OpenTween.Tests/Models/PostFilterRuleTest.cs
OpenTween.Tests/Models/PostFilterRuleVersion113DeserializeTest.cs
OpenTween.Tests/Models/TabInformationTest.cs
OpenTween.Tests/OpenTween.Tests.csproj
OpenTween.Tests/TabsDialogTest.cs
OpenTween.Tests/TestUtils.cs
OpenTween.Tests/Thumbnail/Services/FoursquareCheckinTest.cs
OpenTween.Tests/Thumbnail/Services/ImgAzyobuziNetTest.cs
OpenTween.Tests/Thumbnail/Services/MetaThumbnailServiceTest.cs
OpenTween.Tests/Thumbnail/Services/SimpleThumbnailServiceTest.cs
OpenTween.Tests/Thumbnail/Services/TinamiTest.cs
OpenTween.Tests/Thumbnail/Services/TumblrTest.cs
OpenTween.Tests/TweenMainTest.cs
OpenTween.Tests/TweetFormatterTest.cs
OpenTween.Tests/TweetThumbnailTest.cs
OpenTween.Tests/TwitterTest.cs
OpenTween/Api/ApiLimit.cs
OpenTween/Api/BitlyApi.cs
OpenTween/Api/DataModel/GeoJson.cs
OpenTween/Api/DataModel/TwitterApiAccessLevel.cs
OpenTween/Api/DataModel/TwitterConfiguration.cs
OpenTween/Api/DataModel/TwitterEntity.cs
OpenTween/Api/DataModel/TwitterError.cs
OpenTween/Api/DataModel/TwitterFriendship.cs
OpenTween/Api/DataModel/TwitterList.cs
OpenTween/Api/DataModel/TwitterMessageEvent.cs
OpenTween/Api/DataModel/TwitterPageable.cs
OpenTween/Api/DataModel/TwitterPlace.cs
OpenTween/Api/DataModel/TwitterRateLimits.cs
OpenTween/Api/DataModel/TwitterSearchResult.cs
OpenTween/Api/DataModel/TwitterStatus.cs
OpenTween/Api/DataModel/TwitterStreamEvent.cs
OpenTween/Api/DataModel/TwitterStreamMessage.cs
OpenTween/Api/DataModel/TwitterTextConfiguration.cs
OpenTween/Api/DataModel/TwitterUploadMediaResult.cs
OpenTween/Api/DataModel/TwitterUser.cs
OpenTween/Api/JsonUtils.cs
OpenTween/Api/MicrosoftTranslatorApi.cs
OpenTween/Api/TwitterApi.cs
OpenTween/Api/TwitterApiException.cs
OpenTween/Api/TwitterApiStatus.cs
OpenTween/Api/TwitterStreamObservable.cs
OpenTween/ApiInfoDialog.cs
OpenTween/AppendSettingDialog.cs
OpenTween/ApplicationEvents.cs
OpenTween/ApplicationSettings.cs
OpenTween/AtIdSupplement.cs
OpenTween/AuthDialog.cs
OpenTween/Bing.cs
OpenTween/Connection/IApiConnection.cs
OpenTween/Connection/IMediaUploadService.cs
OpenTween/Connection/Imgur.cs
OpenTween/Connection/LazyJson.cs
OpenTween/Connection/Mobypicture.cs
OpenTween/Connection/Networking.cs
OpenTween/Connection/OAuthEchoHandler.cs
OpenTween/Connection/OAuthHandler.cs
OpenTween/Connection/OAuthUtility.cs
OpenTween/Connection/TwitterApiConnection.cs
OpenTween/Connection/TwitterPhoto.cs
OpenTween/ControlTransaction.cs
OpenTween/DateTimeUtc.cs
OpenTween/DetailsListView.cs
OpenTween/EventViewerDialog.cs
OpenTween/Extensions.cs
OpenTween/FilterDialog.cs
OpenTween/Growl.cs
OpenTween/HashtagManage.cs
OpenTween/HookGlobalHotkey.cs
OpenTween/ImageCache.cs
OpenTween/ImageListViewItem.cs
OpenTween/IndexedSortedSet.cs
OpenTween/InputDialog.cs
OpenTween/InputTabName.cs
OpenTween/LRUCacheDictionary.cs
OpenTween/ListAvailable.cs
OpenTween/ListElement.cs
OpenTween/ListManage.cs
OpenTween/LoginDialog.cs
OpenTween/MediaItem.cs
OpenTween/MediaSelector.cs
OpenTween/MemoryImage.cs
OpenTween/Models/ComparerMode.cs
OpenTween/Models/DirectMessagesTabModel.cs
OpenTween/Models/FavoritesTabModel.cs
OpenTween/Models/FilterTabModel.cs
OpenTween/Models/HomeTabModel.cs
OpenTween/Models/IReadOnlyTabCollection.cs
OpenTween/Models/InternalStorageTabModel.cs
OpenTween/Models/ListTimelineTabModel.cs
OpenTween/Models/LocalSearchTabModel.cs
OpenTween/Models/MediaInfo.cs
OpenTween/Models/MentionsTabModel.cs
OpenTween/Models/MuteTabModel.cs
OpenTween/Models/PostClass.cs
OpenTween/Models/PostFilterRule.cs
OpenTween/Models/PublicSearchTabModel.cs
OpenTween/Models/RelatedPostsTabModel.cs
OpenTween/Models/TabCollection.cs
OpenTween/Models/TabInformations.cs
OpenTween/Models/TabModel.cs
OpenTween/Models/TabUsageTypeExt.cs
OpenTween/Models/UserTimelineTabModel.cs
OpenTween/MouseWheelMessageFilter.cs
OpenTween/MyCommon.cs
OpenTween/MyLists.cs
OpenTween/NativeMethods.cs
OpenTween/NotifyPropertyChangedBase.cs
OpenTween/NullableAttributes.cs [new file with mode: 0644]
OpenTween/OTBaseForm.cs
OpenTween/OTPictureBox.cs
OpenTween/OTSplitContainer.cs
OpenTween/OpenTween.csproj
OpenTween/OpenURL.cs
OpenTween/PostStatusParams.cs
OpenTween/ReaderWriterLockTransaction.cs
OpenTween/RegexAsync.cs
OpenTween/SearchWordDialog.cs
OpenTween/SendErrorReportForm.cs
OpenTween/Setting/Panel/ActionPanel.cs
OpenTween/Setting/Panel/BasedPanel.cs
OpenTween/Setting/Panel/ConnectionPanel.cs
OpenTween/Setting/Panel/CooperatePanel.cs
OpenTween/Setting/Panel/FontPanel.cs
OpenTween/Setting/Panel/FontPanel2.cs
OpenTween/Setting/Panel/GetCountPanel.cs
OpenTween/Setting/Panel/GetPeriodPanel.cs
OpenTween/Setting/Panel/NotifyPanel.cs
OpenTween/Setting/Panel/PreviewPanel.cs
OpenTween/Setting/Panel/ProxyPanel.cs
OpenTween/Setting/Panel/SettingPanelBase.cs
OpenTween/Setting/Panel/ShortUrlPanel.cs
OpenTween/Setting/Panel/StartupPanel.cs
OpenTween/Setting/Panel/TweetActPanel.cs
OpenTween/Setting/Panel/TweetPrvPanel.cs
OpenTween/Setting/SettingAtIdList.cs
OpenTween/Setting/SettingBase.cs
OpenTween/Setting/SettingCommon.cs
OpenTween/Setting/SettingLocal.cs
OpenTween/Setting/SettingManager.cs
OpenTween/Setting/SettingTabs.cs
OpenTween/ShortUrl.cs
OpenTween/ShortcutCommand.cs
OpenTween/TabException.cs
OpenTween/TabsDialog.cs
OpenTween/ThrottlingTimer.cs
OpenTween/Thumbnail/MapThumb.cs
OpenTween/Thumbnail/MapThumbGoogle.cs
OpenTween/Thumbnail/MapThumbOSM.cs
OpenTween/Thumbnail/Services/FoursquareCheckin.cs
OpenTween/Thumbnail/Services/IThumbnailService.cs
OpenTween/Thumbnail/Services/ImgAzyobuziNet.cs
OpenTween/Thumbnail/Services/MetaThumbnailService.cs
OpenTween/Thumbnail/Services/Nicovideo.cs
OpenTween/Thumbnail/Services/PbsTwimgCom.cs
OpenTween/Thumbnail/Services/Pixiv.cs
OpenTween/Thumbnail/Services/SimpleThumbnailService.cs
OpenTween/Thumbnail/Services/Tinami.cs
OpenTween/Thumbnail/Services/TonTwitterCom.cs
OpenTween/Thumbnail/Services/Tumblr.cs
OpenTween/Thumbnail/Services/TwitterComVideo.cs
OpenTween/Thumbnail/Services/Vimeo.cs
OpenTween/Thumbnail/Services/Youtube.cs
OpenTween/Thumbnail/ThumbnailGenerator.cs
OpenTween/Thumbnail/ThumbnailInfo.cs
OpenTween/TimelineScheduler.cs
OpenTween/ToolStripAPIGauge.cs
OpenTween/ToolStripLabelHistory.cs
OpenTween/Tween.cs
OpenTween/TweenAboutBox.cs
OpenTween/TweetDetailsView.cs
OpenTween/TweetExtractor.cs
OpenTween/TweetFormatter.cs
OpenTween/TweetThumbnail.cs
OpenTween/Twitter.cs
OpenTween/UpdateDialog.cs
OpenTween/UserInfo.cs
OpenTween/UserInfoDialog.cs
OpenTween/WaitingDialog.cs
OpenTween/WebApiException.cs
OpenTween/WebBrowserController.cs
OpenTween/nicoms.cs

index 17d0359..e2e53d1 100644 (file)
@@ -30,7 +30,7 @@ namespace OpenTween.Api
 {
     public class ApiLimitTest
     {
-        public static readonly TheoryData<object, bool> Equals_TestCase = new TheoryData<object, bool>
+        public static readonly TheoryData<object?, bool> Equals_TestCase = new TheoryData<object?, bool>
         {
             { new ApiLimit(150, 100, new DateTimeUtc(2013, 1, 1, 0, 0, 0)), true },
             { new ApiLimit(350, 100, new DateTimeUtc(2013, 1, 1, 0, 0, 0)), false },
@@ -42,7 +42,7 @@ namespace OpenTween.Api
 
         [Theory]
         [MemberData(nameof(Equals_TestCase))]
-        public void EqualsTest(object obj2, bool expected)
+        public void EqualsTest(object? obj2, bool expected)
         {
             var obj1 = new ApiLimit(150, 100, new DateTimeUtc(2013, 1, 1, 0, 0, 0));
 
index 105a5d0..0c87126 100644 (file)
@@ -49,7 +49,7 @@ namespace OpenTween.Api
             Assert.Equal(TwitterApiAccessLevel.Anonymous, apiStatus.AccessLevel);
         }
 
-        public static readonly TheoryData<IDictionary<string, string>, ApiLimit> ParseRateLimit_TestCase = new TheoryData<IDictionary<string, string>, ApiLimit>
+        public static readonly TheoryData<Dictionary<string, string>, ApiLimit?> ParseRateLimit_TestCase = new TheoryData<Dictionary<string, string>, ApiLimit?>
         {
             {
                 new Dictionary<string, string> {
@@ -86,13 +86,13 @@ namespace OpenTween.Api
 
         [Theory]
         [MemberData(nameof(ParseRateLimit_TestCase))]
-        public void ParseRateLimitTest(IDictionary<string, string> header, ApiLimit expected)
+        public void ParseRateLimitTest(IDictionary<string, string> header, ApiLimit? expected)
         {
             var limit = TwitterApiStatus.ParseRateLimit(header, "X-RateLimit-");
             Assert.Equal(expected, limit);
         }
 
-        public static readonly TheoryData<IDictionary<string, string>, ApiLimit> ParseMediaRateLimit_TestCase = new TheoryData<IDictionary<string, string>, ApiLimit>
+        public static readonly TheoryData<Dictionary<string, string>, ApiLimit?> ParseMediaRateLimit_TestCase = new TheoryData<Dictionary<string, string>, ApiLimit?>
         {
             {
                 new Dictionary<string, string> {
@@ -121,13 +121,13 @@ namespace OpenTween.Api
 
         [Theory]
         [MemberData(nameof(ParseMediaRateLimit_TestCase))]
-        public void ParseMediaRateLimitTest(IDictionary<string, string> header, ApiLimit expected)
+        public void ParseMediaRateLimitTest(IDictionary<string, string> header, ApiLimit? expected)
         {
             var limit = TwitterApiStatus.ParseRateLimit(header, "X-MediaRateLimit-");
             Assert.Equal(expected, limit);
         }
 
-        public static readonly TheoryData<IDictionary<string, string>, TwitterApiAccessLevel?> ParseAccessLevel_TestCase = new TheoryData<IDictionary<string, string>, TwitterApiAccessLevel?>
+        public static readonly TheoryData<Dictionary<string, string>, TwitterApiAccessLevel?> ParseAccessLevel_TestCase = new TheoryData<Dictionary<string, string>, TwitterApiAccessLevel?>
         {
             {
                 new Dictionary<string, string> { {"X-Access-Level", "read"} },
@@ -181,12 +181,12 @@ namespace OpenTween.Api
                 () => status.UpdateFromHeader(header, "/statuses/home_timeline")
             );
 
-            var rateLimit = status.AccessLimit["/statuses/home_timeline"];
+            var rateLimit = status.AccessLimit["/statuses/home_timeline"]!;
             Assert.Equal(150, rateLimit.AccessLimitCount);
             Assert.Equal(100, rateLimit.AccessLimitRemain);
             Assert.Equal(new DateTimeUtc(2013, 1, 1, 0, 0, 0), rateLimit.AccessLimitResetDate);
 
-            var mediaLimit = status.MediaUploadLimit;
+            var mediaLimit = status.MediaUploadLimit!;
             Assert.Equal(30, mediaLimit.AccessLimitCount);
             Assert.Equal(20, mediaLimit.AccessLimitRemain);
             Assert.Equal(new DateTimeUtc(2013, 1, 2, 0, 0, 0), mediaLimit.AccessLimitResetDate);
@@ -219,12 +219,12 @@ namespace OpenTween.Api
                 () => status.UpdateFromHeader(response.Headers, "/statuses/home_timeline")
             );
 
-            var rateLimit = status.AccessLimit["/statuses/home_timeline"];
+            var rateLimit = status.AccessLimit["/statuses/home_timeline"]!;
             Assert.Equal(150, rateLimit.AccessLimitCount);
             Assert.Equal(100, rateLimit.AccessLimitRemain);
             Assert.Equal(new DateTimeUtc(2013, 1, 1, 0, 0, 0), rateLimit.AccessLimitResetDate);
 
-            var mediaLimit = status.MediaUploadLimit;
+            var mediaLimit = status.MediaUploadLimit!;
             Assert.Equal(30, mediaLimit.AccessLimitCount);
             Assert.Equal(20, mediaLimit.AccessLimitRemain);
             Assert.Equal(new DateTimeUtc(2013, 1, 2, 0, 0, 0), mediaLimit.AccessLimitResetDate);
@@ -245,7 +245,7 @@ namespace OpenTween.Api
                 () => status.UpdateFromJson(TwitterRateLimits.ParseJson(json))
             );
 
-            var rateLimit = status.AccessLimit["/statuses/home_timeline"];
+            var rateLimit = status.AccessLimit["/statuses/home_timeline"]!;
             Assert.Equal(150, rateLimit.AccessLimitCount);
             Assert.Equal(100, rateLimit.AccessLimitRemain);
             Assert.Equal(new DateTimeUtc(2013, 1, 1, 0, 0, 0), rateLimit.AccessLimitResetDate);
index dd344b0..a86270a 100644 (file)
@@ -221,8 +221,8 @@ namespace OpenTween.Connection
             // エラーレスポンスの JSON に含まれるエラーコードに基づいてメッセージを出力する
             Assert.Equal("DuplicateStatus", exception.Message);
 
-            Assert.Equal(TwitterErrorCode.DuplicateStatus, exception.ErrorResponse.Errors[0].Code);
-            Assert.Equal("Status is a duplicate.", exception.ErrorResponse.Errors[0].Message);
+            Assert.Equal(TwitterErrorCode.DuplicateStatus, exception.Errors[0].Code);
+            Assert.Equal("Status is a duplicate.", exception.Errors[0].Message);
 
             Assert.Equal(0, mockHandler.QueueCount);
         }
index d18f55a..7ee7cc0 100644 (file)
@@ -77,7 +77,7 @@ namespace OpenTween
 
         [Fact]
         public void ToCodepoints_ErrorTest()
-            => Assert.Throws<ArgumentNullException>(() => ((string)null).ToCodepoints());
+            => Assert.Throws<ArgumentNullException>(() => ((string)null!).ToCodepoints());
 
         [Theory]
         [InlineData("", 0, 0, 0)]
@@ -92,7 +92,7 @@ namespace OpenTween
         [Fact]
         public void GetCodepointCount_ErrorTest()
         {
-            Assert.Throws<ArgumentNullException>(() => ((string)null).GetCodepointCount(0, 0));
+            Assert.Throws<ArgumentNullException>(() => ((string)null!).GetCodepointCount(0, 0));
             Assert.Throws<ArgumentOutOfRangeException>(() => "abc".GetCodepointCount(-1, 3));
             Assert.Throws<ArgumentOutOfRangeException>(() => "abc".GetCodepointCount(0, 4));
             Assert.Throws<ArgumentOutOfRangeException>(() => "abc".GetCodepointCount(4, 5));
index 8a0ffbc..24bd4e0 100644 (file)
@@ -241,7 +241,7 @@ namespace OpenTween
             Assert.Throws<ArgumentException>(() => set.CopyTo(array, 3));
             Assert.Throws<ArgumentException>(() => set.CopyTo(array, 5));
             Assert.Throws<ArgumentOutOfRangeException>(() => set.CopyTo(array, -1));
-            Assert.Throws<ArgumentNullException>(() => set.CopyTo(null, 0));
+            Assert.Throws<ArgumentNullException>(() => set.CopyTo(null!, 0));
         }
 
         [Fact]
index 2114d97..046d6b4 100644 (file)
@@ -438,7 +438,7 @@ namespace OpenTween
             Assert.Throws<ArgumentException>(() => dict.CopyTo(array, 3));
             Assert.Throws<ArgumentException>(() => dict.CopyTo(array, 5));
             Assert.Throws<ArgumentOutOfRangeException>(() => dict.CopyTo(array, -1));
-            Assert.Throws<ArgumentNullException>(() => dict.CopyTo(null, 0));
+            Assert.Throws<ArgumentNullException>(() => dict.CopyTo(null!, 0));
         }
 
         [Fact]
index a4da436..8590e68 100644 (file)
@@ -205,7 +205,7 @@ namespace OpenTween
             Assert.False(mediaSelector.Visible);
             Assert.False(mediaSelector.Enabled);
 
-            Assert.True(displayImage.IsDisposed);
+            Assert.True(displayImage!.IsDisposed);
         }
 
         [Fact]
@@ -308,12 +308,12 @@ namespace OpenTween
 
             // 2 ページ目
             var page2Image = mediaSelector.ImageSelectedPicture.Image;
-            Assert.True(page1Image.IsDisposed); // 前ページの画像が破棄されているか
+            Assert.True(page1Image!.IsDisposed); // 前ページの画像が破棄されているか
 
             mediaSelector.ImagePageCombo.SelectedIndex = 2;
 
             // 3 ページ目 (新規ページ)
-            Assert.True(page2Image.IsDisposed); // 前ページの画像が破棄されているか
+            Assert.True(page2Image!.IsDisposed); // 前ページの画像が破棄されているか
         }
 
         [Fact]
@@ -366,7 +366,7 @@ namespace OpenTween
             }
 
             // 最初に入力されていたファイルパスの表示用の MemoryImage は破棄される
-            Assert.True(image1.IsDisposed);
+            Assert.True(image1!.IsDisposed);
         }
 
         [Fact]
@@ -402,7 +402,7 @@ namespace OpenTween
             }
 
             // 最初に入力されていたファイルパスの表示用の MemoryImage は破棄される
-            Assert.True(image1.IsDisposed);
+            Assert.True(image1!.IsDisposed);
 
             // 参照されなくなった MemoryImageMediaItem も破棄される
             Assert.True(mediaItem.IsDisposed);
index ca42caf..7f97dcf 100644 (file)
@@ -38,11 +38,9 @@ namespace OpenTween.Models
             {
                 get
                 {
-                    var retweetedId = this.RetweetedId.Value;
+                    var retweetedId = this.RetweetedId!.Value;
 
-                    return PostClassTest.TestCases.ContainsKey(retweetedId) ?
-                        PostClassTest.TestCases[retweetedId] :
-                        null;
+                    return PostClassTest.TestCases[retweetedId];
                 }
             }
         }
@@ -69,7 +67,6 @@ namespace OpenTween.Models
         }
 
         [Theory]
-        [InlineData(null,  null)]
         [InlineData("", "")]
         [InlineData("aaa\nbbb", "aaa bbb")]
         public void TextSingleLineTest(string text, string expected)
@@ -384,7 +381,7 @@ namespace OpenTween.Models
 
         class FakeExpandedUrlInfo : PostClass.ExpandedUrlInfo
         {
-            public TaskCompletionSource<string> fakeResult;
+            public TaskCompletionSource<string> fakeResult = new TaskCompletionSource<string>();
 
             public FakeExpandedUrlInfo(string url, string expandedUrl, bool deepExpand)
                 : base(url, expandedUrl, deepExpand)
@@ -392,10 +389,7 @@ namespace OpenTween.Models
             }
 
             protected override async Task DeepExpandAsync()
-            {
-                this.fakeResult = new TaskCompletionSource<string>();
-                this._expandedUrl = await this.fakeResult.Task;
-            }
+                => this._expandedUrl = await this.fakeResult.Task;
         }
 
         [Fact]
index a406012..4e9485b 100644 (file)
@@ -56,14 +56,14 @@ namespace OpenTween.Models
 
             Assert.Equal(MyCommon.HITRESULT.None, filter.ExecFilter(post));
 
-            Assert.Throws<ArgumentNullException>(() => filter.FilterBody = null);
-            Assert.Throws<ArgumentNullException>(() => filter.ExFilterBody = null);
+            Assert.Throws<ArgumentNullException>(() => filter.FilterBody = null!);
+            Assert.Throws<ArgumentNullException>(() => filter.ExFilterBody = null!);
         }
 
         [Fact]
         public void FieldNullAwareTest()
         {
-            var nullPost = new PostClass { Source = null };
+            var nullPost = new PostClass { Source = null! };
 
             // Source が null であっても ArgumentNullException 等を投げない
             var filter1 = new PostFilterRule
index 578981f..52f09cb 100644 (file)
@@ -39,10 +39,10 @@ namespace OpenTween.Models
         // OpenTween v1.1.2 時点の FiltersClass クラス
         public sealed class FiltersClass
         {
-            public string NameFilter { get; set; }
-            public string ExNameFilter { get; set; }
-            public string[] BodyFilterArray { get; set; }
-            public string[] ExBodyFilterArray { get; set; }
+            public string? NameFilter { get; set; }
+            public string? ExNameFilter { get; set; }
+            public string[] BodyFilterArray { get; set; } = Array.Empty<string>();
+            public string[] ExBodyFilterArray { get; set; } = Array.Empty<string>();
             public bool SearchBoth { get; set; }
             public bool ExSearchBoth { get; set; }
             public bool MoveFrom { get; set; }
@@ -57,8 +57,8 @@ namespace OpenTween.Models
             public bool ExUseRegex { get; set; }
             public bool IsRt { get; set; }
             public bool IsExRt { get; set; }
-            public string Source { get; set; }
-            public string ExSource { get; set; }
+            public string? Source { get; set; }
+            public string? ExSource { get; set; }
         }
 
         [Fact]
index c6300c8..6789042 100644 (file)
@@ -35,7 +35,7 @@ namespace OpenTween.Models
 
         public TabInformationTest()
         {
-            this.tabinfo = Activator.CreateInstance(typeof(TabInformations), true) as TabInformations;
+            this.tabinfo = (TabInformations)Activator.CreateInstance(typeof(TabInformations), true);
 
             // TabInformation.GetInstance() で取得できるようにする
             var field = typeof(TabInformations).GetField("_instance",
@@ -403,7 +403,7 @@ namespace OpenTween.Models
         [Fact]
         public void SubmitUpdate_RemoveSubmit_Test()
         {
-            var homeTab = this.tabinfo.GetTabByType(MyCommon.TabUsageType.Home);
+            var homeTab = this.tabinfo.HomeTab;
 
             this.tabinfo.AddPost(new PostClass { StatusId = 100L });
             this.tabinfo.DistributePosts();
@@ -426,8 +426,8 @@ namespace OpenTween.Models
         [Fact]
         public void SubmitUpdate_RemoveSubmit_NotOrphaned_Test()
         {
-            var homeTab = this.tabinfo.GetTabByType<HomeTabModel>();
-            var favTab = this.tabinfo.GetTabByType<FavoritesTabModel>();
+            var homeTab = this.tabinfo.HomeTab;
+            var favTab = this.tabinfo.FavoriteTab;
 
             this.tabinfo.AddPost(new PostClass { StatusId = 100L, IsFav = true });
             this.tabinfo.DistributePosts();
@@ -456,15 +456,15 @@ namespace OpenTween.Models
         [Fact]
         public void SubmitUpdate_NotifyPriorityTest()
         {
-            var homeTab = this.tabinfo.GetTabByType(MyCommon.TabUsageType.Home);
+            var homeTab = this.tabinfo.HomeTab;
             homeTab.UnreadManage = true;
             homeTab.SoundFile = "home.wav";
 
-            var replyTab = this.tabinfo.GetTabByType(MyCommon.TabUsageType.Mentions);
+            var replyTab = this.tabinfo.MentionTab;
             replyTab.UnreadManage = true;
             replyTab.SoundFile = "reply.wav";
 
-            var dmTab = this.tabinfo.GetTabByType(MyCommon.TabUsageType.DirectMessage);
+            var dmTab = this.tabinfo.DirectMessageTab;
             dmTab.UnreadManage = true;
             dmTab.SoundFile = "dm.wav";
 
@@ -491,11 +491,11 @@ namespace OpenTween.Models
         [Fact]
         public void SubmitUpdate_IgnoreEmptySoundPath_Test()
         {
-            var homeTab = this.tabinfo.GetTabByType(MyCommon.TabUsageType.Home);
+            var homeTab = this.tabinfo.HomeTab;
             homeTab.UnreadManage = true;
             homeTab.SoundFile = "home.wav";
 
-            var replyTab = this.tabinfo.GetTabByType(MyCommon.TabUsageType.Mentions);
+            var replyTab = this.tabinfo.MentionTab;
             replyTab.UnreadManage = true;
             replyTab.SoundFile = "";
 
@@ -519,7 +519,7 @@ namespace OpenTween.Models
         [Fact]
         public void FilterAll_CopyFilterTest()
         {
-            var homeTab = this.tabinfo.GetTabByType(MyCommon.TabUsageType.Home);
+            var homeTab = this.tabinfo.HomeTab;
 
             var myTab1 = new FilterTabModel("MyTab1");
             this.tabinfo.AddTab(myTab1);
@@ -565,7 +565,7 @@ namespace OpenTween.Models
         [Fact]
         public void FilterAll_CopyAndMarkFilterTest()
         {
-            var homeTab = this.tabinfo.GetTabByType(MyCommon.TabUsageType.Home);
+            var homeTab = this.tabinfo.HomeTab;
 
             var myTab1 = new FilterTabModel("MyTab1");
             this.tabinfo.AddTab(myTab1);
@@ -608,13 +608,13 @@ namespace OpenTween.Models
             Assert.Equal(new[] { 200L }, myTab1.StatusIds);
 
             // [statusId: 200] は IsMark が true の状態になる
-            Assert.True(this.tabinfo[200L].IsMark);
+            Assert.True(this.tabinfo[200L]!.IsMark);
         }
 
         [Fact]
         public void FilterAll_MoveFilterTest()
         {
-            var homeTab = this.tabinfo.GetTabByType(MyCommon.TabUsageType.Home);
+            var homeTab = this.tabinfo.HomeTab;
 
             var myTab1 = new FilterTabModel("MyTab1");
             this.tabinfo.AddTab(myTab1);
@@ -659,7 +659,7 @@ namespace OpenTween.Models
         [Fact]
         public void FilterAll_MoveFilterTest2()
         {
-            var homeTab = this.tabinfo.GetTabByType(MyCommon.TabUsageType.Home);
+            var homeTab = this.tabinfo.HomeTab;
 
             var myTab1 = new FilterTabModel("MyTab1");
             var myTab2 = new FilterTabModel("MyTab2");
@@ -723,8 +723,8 @@ namespace OpenTween.Models
         [Fact]
         public void FilterAll_ExcludeReplyFilterTest()
         {
-            var homeTab = this.tabinfo.GetTabByType<HomeTabModel>();
-            var replyTab = this.tabinfo.GetTabByType<MentionsTabModel>();
+            var homeTab = this.tabinfo.HomeTab;
+            var replyTab = this.tabinfo.MentionTab;
 
             var filter = new PostFilterRule
             {
@@ -745,7 +745,7 @@ namespace OpenTween.Models
             Assert.Equal(new[] { 200L, 300L }, replyTab.StatusIds, AnyOrderComparer<long>.Instance);
 
             // [statusId: 100] は IsExcludeReply が true の状態になっている
-            Assert.True(this.tabinfo[100L].IsExcludeReply);
+            Assert.True(this.tabinfo[100L]!.IsExcludeReply);
 
             // Reply のフィルタを変更する
             filter.ExFilterName = "bbb";
@@ -764,10 +764,10 @@ namespace OpenTween.Models
             Assert.Equal(new[] { 100L, 300L }, replyTab.StatusIds, AnyOrderComparer<long>.Instance);
 
             // [statusId: 100] は IsExcludeReply が false の状態になる
-            Assert.False(this.tabinfo[100L].IsExcludeReply);
+            Assert.False(this.tabinfo[100L]!.IsExcludeReply);
 
             // [statusId: 200] は IsExcludeReply が true の状態になる
-            Assert.True(this.tabinfo[200L].IsExcludeReply);
+            Assert.True(this.tabinfo[200L]!.IsExcludeReply);
         }
 
         class TestPostFilterRule : PostFilterRule
index 5e6a3ea..0e23601 100644 (file)
@@ -4,6 +4,7 @@
     <RootNamespace>OpenTween</RootNamespace>
     <TargetFramework>net472</TargetFramework>
     <LangVersion>8.0</LangVersion>
+    <Nullable>enable</Nullable>
     <DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences>
   </PropertyGroup>
   <ItemGroup>
index 12331db..0b3ca53 100644 (file)
@@ -37,7 +37,7 @@ namespace OpenTween
 
         public TabsDialogTest()
         {
-            this.tabinfo = Activator.CreateInstance(typeof(TabInformations), true) as TabInformations;
+            this.tabinfo = (TabInformations)Activator.CreateInstance(typeof(TabInformations), true);
 
             // タブを追加
             this.tabinfo.AddTab(new HomeTabModel("Recent"));
@@ -75,17 +75,17 @@ namespace OpenTween
             using (var dialog = new TabsDialog(this.tabinfo))
             {
                 // MultiSelect = false (default)
-                var firstItem = dialog.TabList.Items[0] as TabsDialog.TabListItem;
+                var firstItem = (TabsDialog.TabListItem)dialog.TabList.Items[0];
                 Assert.Null(firstItem.Tab); // 「(新規タブ)」
                 Assert.Equal(SelectionMode.One, dialog.TabList.SelectionMode);
 
                 dialog.MultiSelect = true;
-                firstItem = dialog.TabList.Items[0] as TabsDialog.TabListItem;
+                firstItem = (TabsDialog.TabListItem)dialog.TabList.Items[0];
                 Assert.NotNull(firstItem.Tab);
                 Assert.Equal(SelectionMode.MultiExtended, dialog.TabList.SelectionMode);
 
                 dialog.MultiSelect = false;
-                firstItem = dialog.TabList.Items[0] as TabsDialog.TabListItem;
+                firstItem = (TabsDialog.TabListItem)dialog.TabList.Items[0];
                 Assert.Null(firstItem.Tab);
                 Assert.Equal(SelectionMode.One, dialog.TabList.SelectionMode);
             }
@@ -117,13 +117,13 @@ namespace OpenTween
             {
                 dialog.MultiSelect = false;
 
-                var item = dialog.TabList.Items[0] as TabsDialog.TabListItem;
+                var item = (TabsDialog.TabListItem)dialog.TabList.Items[0];
                 Assert.Null(item.Tab);
 
-                item = dialog.TabList.Items[1] as TabsDialog.TabListItem;
+                item = (TabsDialog.TabListItem)dialog.TabList.Items[1];
                 Assert.Equal(this.tabinfo.Tabs["Reply"], item.Tab);
 
-                item = dialog.TabList.Items[2] as TabsDialog.TabListItem;
+                item = (TabsDialog.TabListItem)dialog.TabList.Items[2];
                 Assert.Equal(this.tabinfo.Tabs["MyTab1"], item.Tab);
             }
         }
index f0eb41a..aef4bcd 100644 (file)
@@ -57,7 +57,7 @@ namespace OpenTween
         public static async Task NotRaisesAsync<T>(Action<EventHandler<T>> attach, Action<EventHandler<T>> detach, Func<Task> testCode)
             where T : EventArgs
         {
-            T raisedEvent = null;
+            T? raisedEvent = null;
 
             void handler(object s, T e)
                 => raisedEvent = e;
index fe97164..8c506d0 100644 (file)
@@ -232,7 +232,7 @@ namespace OpenTween.Thumbnail.Services
             var location = FoursquareCheckin.ParseIntoLocation(jsonBytes);
 
             Assert.NotNull(location);
-            Assert.Equal(34.35067978344854, location.Latitude);
+            Assert.Equal(34.35067978344854, location!.Latitude);
             Assert.Equal(134.04693603515625, location.Longitude);
         }
 
@@ -265,7 +265,7 @@ namespace OpenTween.Thumbnail.Services
             Thread.CurrentThread.CurrentCulture = origCulture;
 
             Assert.NotNull(location);
-            Assert.Equal(34.35067978344854, location.Latitude);
+            Assert.Equal(34.35067978344854, location!.Latitude);
             Assert.Equal(134.04693603515625, location.Longitude);
         }
 
index 903e035..76cec5c 100644 (file)
@@ -51,7 +51,7 @@ namespace OpenTween.Thumbnail.Services
                 this.LoadRegexAsync().Wait();
             }
 
-            public string GetApiBase()
+            public string? GetApiBase()
                 => this.ApiBase;
 
             protected override Task<byte[]> FetchRegexAsync(string apiBase)
@@ -104,7 +104,7 @@ namespace OpenTween.Thumbnail.Services
             await service.LoadRegexAsync();
             Assert.Null(service.GetApiBase());
 
-            var thumbinfo = await service.GetThumbnailInfoAsync("http://example.com/abcd", null, CancellationToken.None);
+            var thumbinfo = await service.GetThumbnailInfoAsync("http://example.com/abcd", new PostClass(), CancellationToken.None);
             Assert.Null(thumbinfo);
         }
 
@@ -112,10 +112,10 @@ namespace OpenTween.Thumbnail.Services
         public async Task MatchTest()
         {
             var service = new TestImgAzyobuziNet();
-            var thumbinfo = await service.GetThumbnailInfoAsync("http://example.com/abcd", null, CancellationToken.None);
+            var thumbinfo = await service.GetThumbnailInfoAsync("http://example.com/abcd", new PostClass(), CancellationToken.None);
 
             Assert.NotNull(thumbinfo);
-            Assert.Equal("http://example.com/abcd", thumbinfo.MediaPageUrl);
+            Assert.Equal("http://example.com/abcd", thumbinfo!.MediaPageUrl);
             Assert.Equal("http://img.azyobuzi.net/api/redirect?size=large&uri=http%3A%2F%2Fexample.com%2Fabcd", thumbinfo.ThumbnailImageUrl);
             Assert.Null(thumbinfo.TooltipText);
         }
@@ -124,7 +124,7 @@ namespace OpenTween.Thumbnail.Services
         public async Task NotMatchTest()
         {
             var service = new TestImgAzyobuziNet();
-            var thumbinfo = await service.GetThumbnailInfoAsync("http://hogehoge.com/abcd", null, CancellationToken.None);
+            var thumbinfo = await service.GetThumbnailInfoAsync("http://hogehoge.com/abcd", new PostClass(), CancellationToken.None);
 
             Assert.Null(thumbinfo);
         }
@@ -152,7 +152,7 @@ namespace OpenTween.Thumbnail.Services
             var service = new TestImgAzyobuziNet();
             service.Enabled = false;
 
-            var thumbinfo = await service.GetThumbnailInfoAsync("http://example.com/abcd", null, CancellationToken.None);
+            var thumbinfo = await service.GetThumbnailInfoAsync("http://example.com/abcd", new PostClass(), CancellationToken.None);
 
             Assert.Null(thumbinfo);
         }
index 8515d16..9dec5fc 100644 (file)
@@ -28,6 +28,7 @@ using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
 using Moq;
+using OpenTween.Models;
 using Xunit;
 using Xunit.Extensions;
 
@@ -37,7 +38,7 @@ namespace OpenTween.Thumbnail.Services
     {
         class TestMetaThumbnailService : MetaThumbnailService
         {
-            public string FakeHtml { get; set; }
+            public string FakeHtml { get; set; } = "";
 
             public TestMetaThumbnailService(string urlPattern)
                 : base(null, urlPattern)
@@ -66,10 +67,10 @@ namespace OpenTween.Thumbnail.Services
 </body>
 </html>
 ";
-            var thumbinfo = await service.GetThumbnailInfoAsync("http://example.com/abcd", null, CancellationToken.None);
+            var thumbinfo = await service.GetThumbnailInfoAsync("http://example.com/abcd", new PostClass(), CancellationToken.None);
 
             Assert.NotNull(thumbinfo);
-            Assert.Equal("http://example.com/abcd", thumbinfo.MediaPageUrl);
+            Assert.Equal("http://example.com/abcd", thumbinfo!.MediaPageUrl);
             Assert.Equal("http://img.example.com/abcd", thumbinfo.ThumbnailImageUrl);
             Assert.Null(thumbinfo.TooltipText);
         }
@@ -88,10 +89,10 @@ namespace OpenTween.Thumbnail.Services
 
 <p>hogehoge
 ";
-            var thumbinfo = await service.GetThumbnailInfoAsync("http://example.com/abcd", null, CancellationToken.None);
+            var thumbinfo = await service.GetThumbnailInfoAsync("http://example.com/abcd", new PostClass(), CancellationToken.None);
 
             Assert.NotNull(thumbinfo);
-            Assert.Equal("http://example.com/abcd", thumbinfo.MediaPageUrl);
+            Assert.Equal("http://example.com/abcd", thumbinfo!.MediaPageUrl);
             Assert.Equal("http://img.example.com/abcd", thumbinfo.ThumbnailImageUrl);
             Assert.Null(thumbinfo.TooltipText);
         }
@@ -110,10 +111,10 @@ namespace OpenTween.Thumbnail.Services
 
 <p>hogehoge
 ";
-            var thumbinfo = await service.GetThumbnailInfoAsync("http://example.com/abcd", null, CancellationToken.None);
+            var thumbinfo = await service.GetThumbnailInfoAsync("http://example.com/abcd", new PostClass(), CancellationToken.None);
 
             Assert.NotNull(thumbinfo);
-            Assert.Equal("http://example.com/abcd", thumbinfo.MediaPageUrl);
+            Assert.Equal("http://example.com/abcd", thumbinfo!.MediaPageUrl);
             Assert.Equal("http://img.example.com/abcd", thumbinfo.ThumbnailImageUrl);
             Assert.Null(thumbinfo.TooltipText);
         }
@@ -132,10 +133,10 @@ namespace OpenTween.Thumbnail.Services
 
 <p>hogehoge
 ";
-            var thumbinfo = await service.GetThumbnailInfoAsync("http://example.com/abcd", null, CancellationToken.None);
+            var thumbinfo = await service.GetThumbnailInfoAsync("http://example.com/abcd", new PostClass(), CancellationToken.None);
 
             Assert.NotNull(thumbinfo);
-            Assert.Equal("http://example.com/abcd", thumbinfo.MediaPageUrl);
+            Assert.Equal("http://example.com/abcd", thumbinfo!.MediaPageUrl);
             Assert.Equal("http://img.example.com/abcd", thumbinfo.ThumbnailImageUrl);
             Assert.Null(thumbinfo.TooltipText);
         }
@@ -155,10 +156,10 @@ namespace OpenTween.Thumbnail.Services
 
 <p>hogehoge
 ";
-            var thumbinfo = await service.GetThumbnailInfoAsync("http://example.com/abcd", null, CancellationToken.None);
+            var thumbinfo = await service.GetThumbnailInfoAsync("http://example.com/abcd", new PostClass(), CancellationToken.None);
 
             Assert.NotNull(thumbinfo);
-            Assert.Equal("http://example.com/abcd", thumbinfo.MediaPageUrl);
+            Assert.Equal("http://example.com/abcd", thumbinfo!.MediaPageUrl);
             Assert.Equal("http://img.example.com/abcd", thumbinfo.ThumbnailImageUrl);
             Assert.Null(thumbinfo.TooltipText);
         }
@@ -177,10 +178,10 @@ namespace OpenTween.Thumbnail.Services
 
 <p>hogehoge
 ";
-            var thumbinfo = await service.GetThumbnailInfoAsync("http://example.com/abcd", null, CancellationToken.None);
+            var thumbinfo = await service.GetThumbnailInfoAsync("http://example.com/abcd", new PostClass(), CancellationToken.None);
 
             Assert.NotNull(thumbinfo);
-            Assert.Equal("http://example.com/abcd", thumbinfo.MediaPageUrl);
+            Assert.Equal("http://example.com/abcd", thumbinfo!.MediaPageUrl);
             Assert.Equal("http://img.example.com/abcd", thumbinfo.ThumbnailImageUrl);
             Assert.Null(thumbinfo.TooltipText);
         }
@@ -199,10 +200,10 @@ namespace OpenTween.Thumbnail.Services
 
 <p>hogehoge
 ";
-            var thumbinfo = await service.GetThumbnailInfoAsync("http://example.com/abcd", null, CancellationToken.None);
+            var thumbinfo = await service.GetThumbnailInfoAsync("http://example.com/abcd", new PostClass(), CancellationToken.None);
 
             Assert.NotNull(thumbinfo);
-            Assert.Equal("http://example.com/abcd", thumbinfo.MediaPageUrl);
+            Assert.Equal("http://example.com/abcd", thumbinfo!.MediaPageUrl);
             Assert.Equal("http://img.example.com/abcd", thumbinfo.ThumbnailImageUrl);
             Assert.Null(thumbinfo.TooltipText);
         }
@@ -220,7 +221,7 @@ namespace OpenTween.Thumbnail.Services
 
 <p>hogehoge
 ";
-            var thumbinfo = await service.GetThumbnailInfoAsync("http://example.com/abcd", null, CancellationToken.None);
+            var thumbinfo = await service.GetThumbnailInfoAsync("http://example.com/abcd", new PostClass(), CancellationToken.None);
 
             Assert.Null(thumbinfo);
         }
index 98c991f..a2ef8a5 100644 (file)
@@ -28,6 +28,7 @@ using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
 using Moq;
+using OpenTween.Models;
 using Xunit;
 using Xunit.Extensions;
 
@@ -40,10 +41,10 @@ namespace OpenTween.Thumbnail.Services
         {
             var service = new SimpleThumbnailService(@"http://example.com/(.+)", @"http://img.example.com/$1");
 
-            var thumbinfo = await service.GetThumbnailInfoAsync("http://example.com/abcd", null, CancellationToken.None);
+            var thumbinfo = await service.GetThumbnailInfoAsync("http://example.com/abcd", new PostClass(), CancellationToken.None);
 
             Assert.NotNull(thumbinfo);
-            Assert.Equal("http://example.com/abcd", thumbinfo.MediaPageUrl);
+            Assert.Equal("http://example.com/abcd", thumbinfo!.MediaPageUrl);
             Assert.Equal("http://img.example.com/abcd", thumbinfo.ThumbnailImageUrl);
             Assert.Null(thumbinfo.TooltipText);
         }
@@ -53,7 +54,7 @@ namespace OpenTween.Thumbnail.Services
         {
             var service = new SimpleThumbnailService(@"http://example.com/(.+)", @"http://img.example.com/\1");
 
-            var thumbinfo = await service.GetThumbnailInfoAsync("http://hogehoge.com/abcd", null, CancellationToken.None);
+            var thumbinfo = await service.GetThumbnailInfoAsync("http://hogehoge.com/abcd", new PostClass(), CancellationToken.None);
 
             Assert.Null(thumbinfo);
         }
index b68ce1f..5e2e6c9 100644 (file)
@@ -30,6 +30,7 @@ using System.Threading;
 using System.Threading.Tasks;
 using System.Xml.Linq;
 using Moq;
+using OpenTween.Models;
 using Xunit;
 using Xunit.Extensions;
 
@@ -39,7 +40,7 @@ namespace OpenTween.Thumbnail.Services
     {
         class TestTinami : Tinami
         {
-            public string FakeXml { get; set; }
+            public string FakeXml { get; set; } = "";
 
             public TestTinami()
                 : base(null)
@@ -70,10 +71,10 @@ namespace OpenTween.Thumbnail.Services
     </image>
   </content>
 </rsp>";
-            var thumbinfo = await service.GetThumbnailInfoAsync("http://www.tinami.com/view/12345", null, CancellationToken.None);
+            var thumbinfo = await service.GetThumbnailInfoAsync("http://www.tinami.com/view/12345", new PostClass(), CancellationToken.None);
 
             Assert.NotNull(thumbinfo);
-            Assert.Equal("http://www.tinami.com/view/12345", thumbinfo.MediaPageUrl);
+            Assert.Equal("http://www.tinami.com/view/12345", thumbinfo!.MediaPageUrl);
             Assert.Equal("http://img.tinami.com/hogehoge_150.gif", thumbinfo.ThumbnailImageUrl);
             Assert.Equal("説明", thumbinfo.TooltipText);
         }
@@ -87,7 +88,7 @@ namespace OpenTween.Thumbnail.Services
 <rsp stat='user_only'>
   <err msg='この作品は登録ユーザー限定の作品です。'/>
 </rsp>";
-            var thumbinfo = await service.GetThumbnailInfoAsync("http://www.tinami.com/view/12345", null, CancellationToken.None);
+            var thumbinfo = await service.GetThumbnailInfoAsync("http://www.tinami.com/view/12345", new PostClass(), CancellationToken.None);
 
             Assert.Null(thumbinfo);
         }
index 99acfd0..fd56ed6 100644 (file)
@@ -7,6 +7,7 @@ using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Web;
+using OpenTween.Models;
 using Xunit;
 
 namespace OpenTween.Thumbnail.Services
@@ -86,7 +87,7 @@ namespace OpenTween.Thumbnail.Services
                 var service = new Tumblr(http);
 
                 var url = "http://hoge.tumblr.com/post/1234567/tetetete";
-                await service.GetThumbnailInfoAsync(url, null, CancellationToken.None)
+                await service.GetThumbnailInfoAsync(url, new PostClass(), CancellationToken.None)
                     .ConfigureAwait(false);
             }
 
@@ -124,7 +125,7 @@ namespace OpenTween.Thumbnail.Services
 
                 // Tumblrのカスタムドメイン名を使ってるっぽいURL
                 var url = "http://tumblr.example.com/post/1234567/tetetete";
-                await service.GetThumbnailInfoAsync(url, null, CancellationToken.None)
+                await service.GetThumbnailInfoAsync(url, new PostClass(), CancellationToken.None)
                     .ConfigureAwait(false);
             }
 
index 984dc31..de1d426 100644 (file)
@@ -67,7 +67,7 @@ namespace OpenTween
             {
                 var data = new DataObject("UniformResourceLocatorW", memstream);
 
-                var expected = ("https://twitter.com/", (string)null);
+                var expected = ("https://twitter.com/", (string?)null);
                 Assert.Equal(expected, TweenMain.GetUrlFromDataObject(data));
             }
         }
index 1c42aa3..c8c8eba 100644 (file)
@@ -206,7 +206,7 @@ namespace OpenTween
         public void AutoLinkHtml_EntityNullTest()
         {
             var text = "てすとてすとー";
-            TwitterEntities entities = null;
+            TwitterEntities? entities = null;
 
             var expected = "てすとてすとー";
             Assert.Equal(expected, TweetFormatter.AutoLinkHtml(text, entities));
@@ -232,17 +232,7 @@ namespace OpenTween
         public void AutoLinkHtml_EntityNullTest3()
         {
             var text = "てすとてすとー";
-            IEnumerable<TwitterEntity> entities = null;
-
-            var expected = "てすとてすとー";
-            Assert.Equal(expected, TweetFormatter.AutoLinkHtml(text, entities));
-        }
-
-        [Fact]
-        public void AutoLinkHtml_EntityNullTest4()
-        {
-            var text = "てすとてすとー";
-            IEnumerable<TwitterEntity> entities = new TwitterEntity[] { null };
+            IEnumerable<TwitterEntity>? entities = null;
 
             var expected = "てすとてすとー";
             Assert.Equal(expected, TweetFormatter.AutoLinkHtml(text, entities));
@@ -412,7 +402,7 @@ namespace OpenTween
         public void AutoLinkHtml_BreakLineTest()
         {
             var text = "てすと\nてすと\nてすと";
-            TwitterEntities entities = null;
+            TwitterEntities? entities = null;
 
             var expected = "てすと<br>てすと<br>てすと";
             Assert.Equal(expected, TweetFormatter.AutoLinkHtml(text, entities));
index 7dc9458..0af4079 100644 (file)
@@ -45,16 +45,16 @@ namespace OpenTween
         {
             private readonly Regex regex;
             private readonly string replaceUrl;
-            private readonly string replaceTooltip;
+            private readonly string? replaceTooltip;
 
-            public TestThumbnailService(string pattern, string replaceUrl, string replaceTooltip)
+            public TestThumbnailService(string pattern, string replaceUrl, string? replaceTooltip)
             {
                 this.regex = new Regex(pattern);
                 this.replaceUrl = replaceUrl;
                 this.replaceTooltip = replaceTooltip;
             }
 
-            public override async Task<ThumbnailInfo> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token)
+            public override async Task<ThumbnailInfo?> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token)
             {
                 var match = this.regex.Match(url);
 
@@ -112,7 +112,7 @@ namespace OpenTween
                 var picbox = method.Invoke(thumbBox, new[] { "pictureBox1" }) as PictureBox;
 
                 Assert.NotNull(picbox);
-                Assert.Equal("pictureBox1", picbox.Name);
+                Assert.Equal("pictureBox1", picbox!.Name);
                 Assert.Equal(PictureBoxSizeMode.Zoom, picbox.SizeMode);
                 Assert.False(picbox.WaitOnLoad);
                 Assert.Equal(DockStyle.Fill, picbox.Dock);
index fa9550c..56b2bf8 100644 (file)
@@ -236,7 +236,7 @@ namespace OpenTween
                     },
                 },
             };
-            var quotedStatus = (TwitterStatus)null;
+            var quotedStatus = (TwitterStatus?)null;
 
             var expectedText = "twitter.com/hoge/status/1…";
 
@@ -319,7 +319,7 @@ namespace OpenTween
         {
             var sourceHtml = "web";
 
-            var expected = ("web", (Uri)null);
+            var expected = ("web", (Uri?)null);
             Assert.Equal(expected, Twitter.ParseSource(sourceHtml));
         }
 
@@ -339,16 +339,16 @@ namespace OpenTween
             // 参照: https://twitter.com/kim_upsilon/status/595156014032244738
             var sourceHtml = "";
 
-            var expected = ("", (Uri)null);
+            var expected = ("", (Uri?)null);
             Assert.Equal(expected, Twitter.ParseSource(sourceHtml));
         }
 
         [Fact]
         public void ParseSource_NullTest()
         {
-            string sourceHtml = null;
+            string? sourceHtml = null;
 
-            var expected = ("", (Uri)null);
+            var expected = ("", (Uri?)null);
             Assert.Equal(expected, Twitter.ParseSource(sourceHtml));
         }
 
@@ -366,7 +366,7 @@ namespace OpenTween
         {
             var sourceHtml = "&lt;&lt;hogehoge&gt;&gt;";
 
-            var expected = ("<<hogehoge>>", (Uri)null);
+            var expected = ("<<hogehoge>>", (Uri?)null);
             Assert.Equal(expected, Twitter.ParseSource(sourceHtml));
         }
 
index dc9d979..25d605f 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -61,10 +63,10 @@ namespace OpenTween.Api
             this.UpdatedAt = updatedAt;
         }
 
-        public override bool Equals(object obj)
+        public override bool Equals(object? obj)
             => this.Equals(obj as ApiLimit);
 
-        public bool Equals(ApiLimit obj)
+        public bool Equals(ApiLimit? obj)
             => obj != null && this.AccessLimitCount == obj.AccessLimitCount &&
                 this.AccessLimitRemain == obj.AccessLimitRemain && this.AccessLimitResetDate == obj.AccessLimitResetDate;
 
index 09d6780..92b8ccb 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -38,23 +40,23 @@ namespace OpenTween.Api
     {
         public static readonly Uri ApiBase = new Uri("https://api-ssl.bitly.com/");
 
-        public string EndUserAccessToken { get; set; }
+        public string EndUserAccessToken { get; set; } = "";
 
-        public string EndUserLoginName { get; set; }
-        public string EndUserApiKey { get; set; }
+        public string EndUserLoginName { get; set; } = "";
+        public string EndUserApiKey { get; set; } = "";
 
         private HttpClient http => this.localHttpClient ?? Networking.Http;
-        private readonly HttpClient localHttpClient;
+        private readonly HttpClient? localHttpClient;
 
         public BitlyApi()
             : this(null)
         {
         }
 
-        public BitlyApi(HttpClient http)
+        public BitlyApi(HttpClient? http)
             => this.localHttpClient = http;
 
-        public async Task<Uri> ShortenAsync(Uri srcUri, string domain = null)
+        public async Task<Uri> ShortenAsync(Uri srcUri, string? domain = null)
         {
             var query = new Dictionary<string, string>
             {
index 2956ab4..8818ac3 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable annotations
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
index a134fb4..b221ed0 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable annotations
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
index 900f671..6d864d1 100644 (file)
@@ -25,6 +25,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable annotations
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
index f2d240f..0220aba 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable annotations
+
 using System;
 using System.Collections;
 using System.Collections.Generic;
@@ -35,19 +37,19 @@ namespace OpenTween.Api.DataModel
     public class TwitterEntities : IEnumerable<TwitterEntity>
     {
         [DataMember(Name = "hashtags", IsRequired = false)]
-        public TwitterEntityHashtag[] Hashtags { get; set; }
+        public TwitterEntityHashtag[]? Hashtags { get; set; }
 
         [DataMember(Name = "media", IsRequired = false)]
-        public TwitterEntityMedia[] Media { get; set; }
+        public TwitterEntityMedia[]? Media { get; set; }
 
         [DataMember(Name = "symbols", IsRequired = false)]
-        public TwitterEntitySymbol[] Symbols { get; set; }
+        public TwitterEntitySymbol[]? Symbols { get; set; }
 
         [DataMember(Name = "urls", IsRequired = false)]
-        public TwitterEntityUrl[] Urls { get; set; }
+        public TwitterEntityUrl[]? Urls { get; set; }
 
         [DataMember(Name = "user_mentions", IsRequired = false)]
-        public TwitterEntityMention[] UserMentions { get; set; }
+        public TwitterEntityMention[]? UserMentions { get; set; }
 
         public IEnumerator<TwitterEntity> GetEnumerator()
         {
@@ -93,7 +95,7 @@ namespace OpenTween.Api.DataModel
     public class TwitterEntityMedia : TwitterEntityUrl
     {
         [DataMember(Name = "additional_media_info", IsRequired = false)]
-        public TwitterMediaAdditionalInfo AdditionalMediaInfo { get; set; }
+        public TwitterMediaAdditionalInfo? AdditionalMediaInfo { get; set; }
 
         [DataMember(Name = "id")]
         public long Id { get; set; }
@@ -117,10 +119,10 @@ namespace OpenTween.Api.DataModel
         public string Type { get; set; }
 
         [DataMember(Name = "video_info", IsRequired = false)]
-        public TwitterMediaVideoInfo VideoInfo { get; set; }
+        public TwitterMediaVideoInfo? VideoInfo { get; set; }
 
         [DataMember(Name = "ext_alt_text", IsRequired = false)]
-        public string AltText { get; set; }
+        public string? AltText { get; set; }
     }
 
     [DataContract]
index c570ead..c2d4b21 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable annotations
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
index 40298dd..b3d01b8 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable annotations
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
index 955083f..4473f84 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable annotations
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
index d3d6129..c1883aa 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable annotations
+
 using System;
 using System.Collections.Generic;
 using System.Runtime.Serialization;
@@ -48,7 +50,7 @@ namespace OpenTween.Api.DataModel
         public TwitterMessageEvent[] Events { get; set; }
 
         [DataMember(Name = "next_cursor", IsRequired = false)]
-        public string NextCursor { get; set; }
+        public string? NextCursor { get; set; }
     }
 
     [DataContract]
@@ -84,7 +86,7 @@ namespace OpenTween.Api.DataModel
         public class Data
         {
             [DataMember(Name = "attachment", IsRequired = false)]
-            public MessageAttachment Attachment { get; set; }
+            public MessageAttachment? Attachment { get; set; }
 
             [DataContract]
             public class MessageAttachment
@@ -107,7 +109,7 @@ namespace OpenTween.Api.DataModel
         public string SenderId { get; set; }
 
         [DataMember(Name = "source_app_id", IsRequired = false)]
-        public string SourceAppId { get; set; }
+        public string? SourceAppId { get; set; }
 
         [DataMember(Name = "target")]
         public MessageTarget Target { get; set; }
index 3b58b85..e7b9e57 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable annotations
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
index 6ebda2d..a82c796 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable annotations
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
index 6b0d881..2799b94 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable annotations
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
index 3b60b24..90be31e 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable annotations
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
index 27e4f48..0386882 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable annotations
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -34,7 +36,7 @@ namespace OpenTween.Api.DataModel
     public class TwitterStatus
     {
         [DataMember(Name = "coordinates", IsRequired = false)]
-        public GeoJsonPoint Coordinates { get; set; }
+        public GeoJsonPoint? Coordinates { get; set; }
 
         [DataMember(Name = "created_at")]
         public string CreatedAt { get; set; }
@@ -46,7 +48,7 @@ namespace OpenTween.Api.DataModel
         public TwitterEntities Entities { get; set; }
 
         [DataMember(Name = "extended_entities", IsRequired = false)]
-        public TwitterEntities ExtendedEntities { get; set; }
+        public TwitterEntities? ExtendedEntities { get; set; }
 
         [DataMember(Name = "favorite_count")]
         public int? FavoriteCount { get; set; }
@@ -67,28 +69,28 @@ namespace OpenTween.Api.DataModel
         public string IdStr { get; set; }
 
         [DataMember(Name = "in_reply_to_screen_name")]
-        public string InReplyToScreenName { get; set; } // Nullable
+        public string? InReplyToScreenName { get; set; }
 
         [DataMember(Name = "in_reply_to_status_id")]
         public long? InReplyToStatusId { get; set; }
 
         [DataMember(Name = "in_reply_to_status_id_str")]
-        public string InReplyToStatusIdStr { get; set; } // Nullable
+        public string? InReplyToStatusIdStr { get; set; }
 
         [DataMember(Name = "in_reply_to_user_id")]
         public long? InReplyToUserId { get; set; }
 
         [DataMember(Name = "in_reply_to_user_id_str")]
-        public string InReplyToUserIdStr { get; set; } // Nullable
+        public string? InReplyToUserIdStr { get; set; }
 
         [DataMember(Name = "is_quote_status")]
         public bool IsQuoteStatus { get; set; }
 
         [DataMember(Name = "lang")]
-        public string Lang { get; set; } // Nullable
+        public string? Lang { get; set; }
 
         [DataMember(Name = "place", IsRequired = false)]
-        public TwitterPlace Place { get; set; }
+        public TwitterPlace? Place { get; set; }
 
         [DataMember(Name = "possibly_sensitive")]
         public bool? PossiblySensitive { get; set; }
@@ -100,13 +102,13 @@ namespace OpenTween.Api.DataModel
         public long? QuotedStatusId { get; set; }
 
         [DataMember(Name = "quoted_status_id_str", IsRequired = false)]
-        public string QuotedStatusIdStr { get; set; }
+        public string? QuotedStatusIdStr { get; set; }
 
         [DataMember(Name = "quoted_status", IsRequired = false)]
-        public TwitterStatus QuotedStatus { get; set; }
+        public TwitterStatus? QuotedStatus { get; set; }
 
         [DataMember(Name = "quoted_status_permalink", IsRequired = false)]
-        public TwitterQuotedStatusPermalink QuotedStatusPermalink { get; set; } // https://twittercommunity.com/t/105473
+        public TwitterQuotedStatusPermalink? QuotedStatusPermalink { get; set; } // https://twittercommunity.com/t/105473
 
         [DataMember(Name = "reply_count")]
         public int ReplyCount { get; set; }
@@ -118,7 +120,7 @@ namespace OpenTween.Api.DataModel
         public bool Retweeted { get; set; }
 
         [DataMember(Name = "retweeted_status", IsRequired = false)]
-        public TwitterStatus RetweetedStatus { get; set; }
+        public TwitterStatus? RetweetedStatus { get; set; }
 
         [DataMember(Name = "source")]
         public string Source { get; set; }
@@ -189,7 +191,7 @@ namespace OpenTween.Api.DataModel
     public class TwitterStatusCompat
     {
         [DataMember(Name = "coordinates", IsRequired = false)]
-        public GeoJsonPoint Coordinates { get; set; }
+        public GeoJsonPoint? Coordinates { get; set; }
 
         [DataMember(Name = "created_at")]
         public string CreatedAt { get; set; }
@@ -198,10 +200,10 @@ namespace OpenTween.Api.DataModel
         public TwitterEntities Entities { get; set; }
 
         [DataMember(Name = "extended_entities", IsRequired = false)]
-        public TwitterEntities ExtendedEntities { get; set; }
+        public TwitterEntities? ExtendedEntities { get; set; }
 
         [DataMember(Name = "extended_tweet", IsRequired = false)]
-        public TwitterStatusCompat.Extended ExtendedTweet { get; set; }
+        public TwitterStatusCompat.Extended? ExtendedTweet { get; set; }
 
         [DataContract]
         public class Extended
@@ -213,7 +215,7 @@ namespace OpenTween.Api.DataModel
             public TwitterEntities Entities { get; set; }
 
             [DataMember(Name = "extended_entities", IsRequired = false)]
-            public TwitterEntities ExtendedEntities { get; set; }
+            public TwitterEntities? ExtendedEntities { get; set; }
 
             [DataMember(Name = "full_text")]
             public string FullText { get; set; }
@@ -235,28 +237,28 @@ namespace OpenTween.Api.DataModel
         public string IdStr { get; set; }
 
         [DataMember(Name = "in_reply_to_screen_name")]
-        public string InReplyToScreenName { get; set; } // Nullable
+        public string? InReplyToScreenName { get; set; }
 
         [DataMember(Name = "in_reply_to_status_id")]
         public long? InReplyToStatusId { get; set; }
 
         [DataMember(Name = "in_reply_to_status_id_str")]
-        public string InReplyToStatusIdStr { get; set; } // Nullable
+        public string? InReplyToStatusIdStr { get; set; }
 
         [DataMember(Name = "in_reply_to_user_id")]
         public long? InReplyToUserId { get; set; }
 
         [DataMember(Name = "in_reply_to_user_id_str")]
-        public string InReplyToUserIdStr { get; set; } // Nullable
+        public string? InReplyToUserIdStr { get; set; }
 
         [DataMember(Name = "is_quote_status")]
         public bool IsQuoteStatus { get; set; }
 
         [DataMember(Name = "lang")]
-        public string Lang { get; set; } // Nullable
+        public string? Lang { get; set; }
 
         [DataMember(Name = "place", IsRequired = false)]
-        public TwitterPlace Place { get; set; }
+        public TwitterPlace? Place { get; set; }
 
         [DataMember(Name = "possibly_sensitive")]
         public bool? PossiblySensitive { get; set; }
@@ -268,13 +270,13 @@ namespace OpenTween.Api.DataModel
         public long? QuotedStatusId { get; set; }
 
         [DataMember(Name = "quoted_status_id_str", IsRequired = false)]
-        public string QuotedStatusIdStr { get; set; }
+        public string? QuotedStatusIdStr { get; set; }
 
         [DataMember(Name = "quoted_status", IsRequired = false)]
-        public TwitterStatusCompat QuotedStatus { get; set; }
+        public TwitterStatusCompat? QuotedStatus { get; set; }
 
         [DataMember(Name = "quoted_status_permalink", IsRequired = false)]
-        public TwitterQuotedStatusPermalink QuotedStatusPermalink { get; set; } // https://twittercommunity.com/t/105473
+        public TwitterQuotedStatusPermalink? QuotedStatusPermalink { get; set; } // https://twittercommunity.com/t/105473
 
         [DataMember(Name = "reply_count")]
         public int ReplyCount { get; set; }
@@ -286,7 +288,7 @@ namespace OpenTween.Api.DataModel
         public bool Retweeted { get; set; }
 
         [DataMember(Name = "retweeted_status", IsRequired = false)]
-        public TwitterStatusCompat RetweetedStatus { get; set; }
+        public TwitterStatusCompat? RetweetedStatus { get; set; }
 
         [DataMember(Name = "source")]
         public string Source { get; set; }
@@ -385,7 +387,7 @@ namespace OpenTween.Api.DataModel
     public class TwitterDirectMessage
     {
         [DataMember(Name = "entities", IsRequired = false)]
-        public TwitterEntities Entities { get; set; }
+        public TwitterEntities? Entities { get; set; }
 
         [DataMember(Name = "created_at")]
         public string CreatedAt { get; set; }
@@ -409,7 +411,7 @@ namespace OpenTween.Api.DataModel
         public string SenderScreenName { get; set; }
 
         [DataMember(Name = "sender", IsRequired = false)]
-        public TwitterUser Sender { get; set; }
+        public TwitterUser? Sender { get; set; }
 
         [DataMember(Name = "recipient_id")]
         public long RecipientId { get; set; }
@@ -421,7 +423,7 @@ namespace OpenTween.Api.DataModel
         public string RecipientScreenName { get; set; }
 
         [DataMember(Name = "recipient", IsRequired = false)]
-        public TwitterUser Recipient { get; set; }
+        public TwitterUser? Recipient { get; set; }
 
         /// <exception cref="SerializationException"/>
         public static TwitterDirectMessage ParseJson(string json)
index da1fa0b..e2aa6a2 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable annotations
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
index 50df25b..1bf42b1 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable annotations
+
 using System.Runtime.Serialization;
 
 namespace OpenTween.Api.DataModel
@@ -77,10 +79,10 @@ namespace OpenTween.Api.DataModel
         }
 
         [DataMember(Name = "direct_message", IsRequired = false)]
-        public DeletedId DirectMessage { get; set; } // Nullable
+        public DeletedId? DirectMessage { get; set; }
 
         [DataMember(Name = "status", IsRequired = false)]
-        public DeletedId Status { get; set; } // Nullable
+        public DeletedId? Status { get; set; }
 
         public static StreamMessageDelete ParseJson(string json)
             => MyCommon.CreateDataFromJson<StreamMessageDelete>(json);
index d0c0488..95de392 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable annotations
+
 using System.Runtime.Serialization;
 
 namespace OpenTween.Api.DataModel
index a7a731e..1a57a9a 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable annotations
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -68,7 +70,7 @@ namespace OpenTween.Api.DataModel
         }
 
         [DataMember(Name = "image", IsRequired = false)]
-        public ImageInfo Image { get; set; }
+        public ImageInfo? Image { get; set; }
 
         [DataMember(Name = "media_id")]
         public long MediaId { get; set; }
@@ -96,7 +98,7 @@ namespace OpenTween.Api.DataModel
             }
 
             [DataMember(Name = "error", IsRequired = false)]
-            public MediaProcessingError Error { get; set; }
+            public MediaProcessingError? Error { get; set; }
 
             [DataMember(Name = "progress_percent")]
             public int ProgressPercent { get; set; }
@@ -106,7 +108,7 @@ namespace OpenTween.Api.DataModel
         }
 
         [DataMember(Name = "processing_info", IsRequired = false)]
-        public MediaProcessingInfo ProcessingInfo { get; set; }
+        public MediaProcessingInfo? ProcessingInfo { get; set; }
 
         [DataMember(Name = "size", IsRequired = false)]
         public long? Size { get; set; }
@@ -119,7 +121,7 @@ namespace OpenTween.Api.DataModel
         }
 
         [DataMember(Name = "video", IsRequired = false)]
-        public VideoInfo Video { get; set; }
+        public VideoInfo? Video { get; set; }
 
         /// <exception cref="SerializationException"/>
         public static TwitterUploadMediaResult ParseJson(string json)
index 655561b..dfb9a45 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable annotations
+
 using System;
 using System.Collections.Generic;
 using System.IO;
@@ -38,7 +40,7 @@ namespace OpenTween.Api.DataModel
         public string CreatedAt { get; set; }
 
         [DataMember(Name = "description")]
-        public string Description { get; set; } // Nullable
+        public string? Description { get; set; }
 
         [DataMember(Name = "default_profile")]
         public bool DefaultProfile { get; set; }
@@ -47,16 +49,16 @@ namespace OpenTween.Api.DataModel
         public bool DefaultProfileImage { get; set; }
 
         [DataMember(Name = "entities", IsRequired = false)]
-        public TwitterUser.TwitterUserEntity Entities { get; set; }
+        public TwitterUser.TwitterUserEntity? Entities { get; set; }
 
         [DataContract]
         public class TwitterUserEntity
         {
             [DataMember(Name = "url", IsRequired = false)]
-            public TwitterEntities Url { get; set; }
+            public TwitterEntities? Url { get; set; }
 
             [DataMember(Name = "description", IsRequired = false)]
-            public TwitterEntities Description { get; set; }
+            public TwitterEntities? Description { get; set; }
         }
 
         [DataMember(Name = "favourites_count")]
@@ -78,7 +80,7 @@ namespace OpenTween.Api.DataModel
         public int? ListedCount { get; set; }
 
         [DataMember(Name = "location")]
-        public string Location { get; set; } // Nullable
+        public string? Location { get; set; }
 
         [DataMember(Name = "name")]
         public string Name { get; set; }
@@ -99,13 +101,13 @@ namespace OpenTween.Api.DataModel
         public bool ShowAllInlineMedia { get; set; }
 
         [DataMember(Name = "status", IsRequired = false)]
-        public TwitterStatus Status { get; set; } // Nullable
+        public TwitterStatus? Status { get; set; }
 
         [DataMember(Name = "statuses_count")]
         public int StatusesCount { get; set; }
 
         [DataMember(Name = "url")]
-        public string Url { get; set; } // Nullable
+        public string? Url { get; set; }
 
         [DataMember(Name = "verified")]
         public bool Verified { get; set; }
index ece4051..c237fba 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System.Text;
 
 namespace OpenTween.Api
index 57f1bb8..4736df3 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -39,21 +41,21 @@ namespace OpenTween.Api
         public static readonly Uri IssueTokenEndpoint = new Uri("https://api.cognitive.microsoft.com/sts/v1.0/issueToken");
         public static readonly Uri TranslateEndpoint = new Uri("https://api.cognitive.microsofttranslator.com/translate");
 
-        public string AccessToken { get; internal set; }
-        public DateTimeUtc RefreshAccessTokenAt { get; internal set; }
+        public string AccessToken { get; internal set; } = "";
+        public DateTimeUtc RefreshAccessTokenAt { get; internal set; } = DateTimeUtc.MinValue;
 
         private HttpClient Http => this.localHttpClient ?? Networking.Http;
-        private readonly HttpClient localHttpClient;
+        private readonly HttpClient? localHttpClient;
 
         public MicrosoftTranslatorApi()
             : this(null)
         {
         }
 
-        public MicrosoftTranslatorApi(HttpClient http)
+        public MicrosoftTranslatorApi(HttpClient? http)
             => this.localHttpClient = http;
 
-        public async Task<string> TranslateAsync(string text, string langTo, string langFrom = null)
+        public async Task<string> TranslateAsync(string text, string langTo, string? langFrom = null)
         {
             await this.UpdateAccessTokenIfExpired()
                 .ConfigureAwait(false);
@@ -95,7 +97,7 @@ namespace OpenTween.Api
 
         public async Task UpdateAccessTokenIfExpired()
         {
-            if (this.AccessToken != null && this.RefreshAccessTokenAt > DateTimeUtc.Now)
+            if (!string.IsNullOrEmpty(this.AccessToken) && this.RefreshAccessTokenAt > DateTimeUtc.Now)
                 return;
 
             var (accessToken, expiresIn) = await this.GetAccessTokenAsync()
index f57b52d..e812798 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.IO;
@@ -34,11 +36,11 @@ namespace OpenTween.Api
     public sealed class TwitterApi : IDisposable
     {
         public long CurrentUserId { get; private set; }
-        public string CurrentScreenName { get; private set; }
+        public string CurrentScreenName { get; private set; } = "";
 
-        public IApiConnection Connection => this.apiConnection;
+        public IApiConnection Connection => this.apiConnection ?? throw new InvalidOperationException();
 
-        internal IApiConnection apiConnection;
+        internal IApiConnection? apiConnection;
 
         public void Initialize(string accessToken, string accessSecret, long userId, string screenName)
         {
@@ -67,7 +69,7 @@ namespace OpenTween.Api
             if (sinceId != null)
                 param["since_id"] = sinceId.ToString();
 
-            return this.apiConnection.GetAsync<TwitterStatus[]>(endpoint, param, "/statuses/home_timeline");
+            return this.Connection.GetAsync<TwitterStatus[]>(endpoint, param, "/statuses/home_timeline");
         }
 
         public Task<TwitterStatus[]> StatusesMentionsTimeline(int? count = null, long? maxId = null, long? sinceId = null)
@@ -87,7 +89,7 @@ namespace OpenTween.Api
             if (sinceId != null)
                 param["since_id"] = sinceId.ToString();
 
-            return this.apiConnection.GetAsync<TwitterStatus[]>(endpoint, param, "/statuses/mentions_timeline");
+            return this.Connection.GetAsync<TwitterStatus[]>(endpoint, param, "/statuses/mentions_timeline");
         }
 
         public Task<TwitterStatus[]> StatusesUserTimeline(string screenName, int? count = null, long? maxId = null, long? sinceId = null)
@@ -109,7 +111,7 @@ namespace OpenTween.Api
             if (sinceId != null)
                 param["since_id"] = sinceId.ToString();
 
-            return this.apiConnection.GetAsync<TwitterStatus[]>(endpoint, param, "/statuses/user_timeline");
+            return this.Connection.GetAsync<TwitterStatus[]>(endpoint, param, "/statuses/user_timeline");
         }
 
         public Task<TwitterStatus> StatusesShow(long statusId)
@@ -123,11 +125,11 @@ namespace OpenTween.Api
                 ["tweet_mode"] = "extended",
             };
 
-            return this.apiConnection.GetAsync<TwitterStatus>(endpoint, param, "/statuses/show/:id");
+            return this.Connection.GetAsync<TwitterStatus>(endpoint, param, "/statuses/show/:id");
         }
 
-        public Task<LazyJson<TwitterStatus>> StatusesUpdate(string status, long? replyToId, IReadOnlyList<long> mediaIds,
-            bool? autoPopulateReplyMetadata = null, IReadOnlyList<long> excludeReplyUserIds = null, string attachmentUrl = null)
+        public Task<LazyJson<TwitterStatus>> StatusesUpdate(string status, long? replyToId, IReadOnlyList<long>? mediaIds,
+            bool? autoPopulateReplyMetadata = null, IReadOnlyList<long>? excludeReplyUserIds = null, string? attachmentUrl = null)
         {
             var endpoint = new Uri("statuses/update.json", UriKind.Relative);
             var param = new Dictionary<string, string>
@@ -149,7 +151,7 @@ namespace OpenTween.Api
             if (attachmentUrl != null)
                 param["attachment_url"] = attachmentUrl;
 
-            return this.apiConnection.PostLazyAsync<TwitterStatus>(endpoint, param);
+            return this.Connection.PostLazyAsync<TwitterStatus>(endpoint, param);
         }
 
         public Task<LazyJson<TwitterStatus>> StatusesDestroy(long statusId)
@@ -160,7 +162,7 @@ namespace OpenTween.Api
                 ["id"] = statusId.ToString(),
             };
 
-            return this.apiConnection.PostLazyAsync<TwitterStatus>(endpoint, param);
+            return this.Connection.PostLazyAsync<TwitterStatus>(endpoint, param);
         }
 
         public Task<LazyJson<TwitterStatus>> StatusesRetweet(long statusId)
@@ -174,10 +176,10 @@ namespace OpenTween.Api
                 ["tweet_mode"] = "extended",
             };
 
-            return this.apiConnection.PostLazyAsync<TwitterStatus>(endpoint, param);
+            return this.Connection.PostLazyAsync<TwitterStatus>(endpoint, param);
         }
 
-        public Task<TwitterSearchResult> SearchTweets(string query, string lang = null, int? count = null, long? maxId = null, long? sinceId = null)
+        public Task<TwitterSearchResult> SearchTweets(string query, string? lang = null, int? count = null, long? maxId = null, long? sinceId = null)
         {
             var endpoint = new Uri("search/tweets.json", UriKind.Relative);
             var param = new Dictionary<string, string>
@@ -198,7 +200,7 @@ namespace OpenTween.Api
             if (sinceId != null)
                 param["since_id"] = sinceId.ToString();
 
-            return this.apiConnection.GetAsync<TwitterSearchResult>(endpoint, param, "/search/tweets");
+            return this.Connection.GetAsync<TwitterSearchResult>(endpoint, param, "/search/tweets");
         }
 
         public Task<TwitterLists> ListsOwnerships(string screenName, long? cursor = null, int? count = null)
@@ -214,7 +216,7 @@ namespace OpenTween.Api
             if (count != null)
                 param["count"] = count.ToString();
 
-            return this.apiConnection.GetAsync<TwitterLists>(endpoint, param, "/lists/ownerships");
+            return this.Connection.GetAsync<TwitterLists>(endpoint, param, "/lists/ownerships");
         }
 
         public Task<TwitterLists> ListsSubscriptions(string screenName, long? cursor = null, int? count = null)
@@ -230,7 +232,7 @@ namespace OpenTween.Api
             if (count != null)
                 param["count"] = count.ToString();
 
-            return this.apiConnection.GetAsync<TwitterLists>(endpoint, param, "/lists/subscriptions");
+            return this.Connection.GetAsync<TwitterLists>(endpoint, param, "/lists/subscriptions");
         }
 
         public Task<TwitterLists> ListsMemberships(string screenName, long? cursor = null, int? count = null, bool? filterToOwnedLists = null)
@@ -248,10 +250,10 @@ namespace OpenTween.Api
             if (filterToOwnedLists != null)
                 param["filter_to_owned_lists"] = filterToOwnedLists.Value ? "true" : "false";
 
-            return this.apiConnection.GetAsync<TwitterLists>(endpoint, param, "/lists/memberships");
+            return this.Connection.GetAsync<TwitterLists>(endpoint, param, "/lists/memberships");
         }
 
-        public Task<LazyJson<TwitterList>> ListsCreate(string name, string description = null, bool? @private = null)
+        public Task<LazyJson<TwitterList>> ListsCreate(string name, string? description = null, bool? @private = null)
         {
             var endpoint = new Uri("lists/create.json", UriKind.Relative);
             var param = new Dictionary<string, string>
@@ -264,10 +266,10 @@ namespace OpenTween.Api
             if (@private != null)
                 param["mode"] = @private.Value ? "private" : "public";
 
-            return this.apiConnection.PostLazyAsync<TwitterList>(endpoint, param);
+            return this.Connection.PostLazyAsync<TwitterList>(endpoint, param);
         }
 
-        public Task<LazyJson<TwitterList>> ListsUpdate(long listId, string name = null, string description = null, bool? @private = null)
+        public Task<LazyJson<TwitterList>> ListsUpdate(long listId, string? name = null, string? description = null, bool? @private = null)
         {
             var endpoint = new Uri("lists/update.json", UriKind.Relative);
             var param = new Dictionary<string, string>
@@ -282,7 +284,7 @@ namespace OpenTween.Api
             if (@private != null)
                 param["mode"] = @private.Value ? "private" : "public";
 
-            return this.apiConnection.PostLazyAsync<TwitterList>(endpoint, param);
+            return this.Connection.PostLazyAsync<TwitterList>(endpoint, param);
         }
 
         public Task<LazyJson<TwitterList>> ListsDestroy(long listId)
@@ -293,7 +295,7 @@ namespace OpenTween.Api
                 ["list_id"] = listId.ToString(),
             };
 
-            return this.apiConnection.PostLazyAsync<TwitterList>(endpoint, param);
+            return this.Connection.PostLazyAsync<TwitterList>(endpoint, param);
         }
 
         public Task<TwitterStatus[]> ListsStatuses(long listId, int? count = null, long? maxId = null, long? sinceId = null, bool? includeRTs = null)
@@ -316,7 +318,7 @@ namespace OpenTween.Api
             if (includeRTs != null)
                 param["include_rts"] = includeRTs.Value ? "true" : "false";
 
-            return this.apiConnection.GetAsync<TwitterStatus[]>(endpoint, param, "/lists/statuses");
+            return this.Connection.GetAsync<TwitterStatus[]>(endpoint, param, "/lists/statuses");
         }
 
         public Task<TwitterUsers> ListsMembers(long listId, long? cursor = null)
@@ -333,7 +335,7 @@ namespace OpenTween.Api
             if (cursor != null)
                 param["cursor"] = cursor.ToString();
 
-            return this.apiConnection.GetAsync<TwitterUsers>(endpoint, param, "/lists/members");
+            return this.Connection.GetAsync<TwitterUsers>(endpoint, param, "/lists/members");
         }
 
         public Task<TwitterUser> ListsMembersShow(long listId, string screenName)
@@ -348,7 +350,7 @@ namespace OpenTween.Api
                 ["tweet_mode"] = "extended",
             };
 
-            return this.apiConnection.GetAsync<TwitterUser>(endpoint, param, "/lists/members/show");
+            return this.Connection.GetAsync<TwitterUser>(endpoint, param, "/lists/members/show");
         }
 
         public Task<LazyJson<TwitterUser>> ListsMembersCreate(long listId, string screenName)
@@ -363,7 +365,7 @@ namespace OpenTween.Api
                 ["tweet_mode"] = "extended",
             };
 
-            return this.apiConnection.PostLazyAsync<TwitterUser>(endpoint, param);
+            return this.Connection.PostLazyAsync<TwitterUser>(endpoint, param);
         }
 
         public Task<LazyJson<TwitterUser>> ListsMembersDestroy(long listId, string screenName)
@@ -378,10 +380,10 @@ namespace OpenTween.Api
                 ["tweet_mode"] = "extended",
             };
 
-            return this.apiConnection.PostLazyAsync<TwitterUser>(endpoint, param);
+            return this.Connection.PostLazyAsync<TwitterUser>(endpoint, param);
         }
 
-        public Task<TwitterMessageEventList> DirectMessagesEventsList(int? count = null, string cursor = null)
+        public Task<TwitterMessageEventList> DirectMessagesEventsList(int? count = null, string? cursor = null)
         {
             var endpoint = new Uri("direct_messages/events/list.json", UriKind.Relative);
             var param = new Dictionary<string, string>();
@@ -391,7 +393,7 @@ namespace OpenTween.Api
             if (cursor != null)
                 param["cursor"] = cursor;
 
-            return this.apiConnection.GetAsync<TwitterMessageEventList>(endpoint, param, "/direct_messages/events/list");
+            return this.Connection.GetAsync<TwitterMessageEventList>(endpoint, param, "/direct_messages/events/list");
         }
 
         public Task<LazyJson<TwitterMessageEventSingle>> DirectMessagesEventsNew(long recipientId, string text, long? mediaId = null)
@@ -424,7 +426,7 @@ namespace OpenTween.Api
   }}
 }}";
 
-            return this.apiConnection.PostJsonAsync<TwitterMessageEventSingle>(endpoint, json);
+            return this.Connection.PostJsonAsync<TwitterMessageEventSingle>(endpoint, json);
         }
 
         public Task DirectMessagesEventsDestroy(string eventId)
@@ -438,7 +440,7 @@ namespace OpenTween.Api
             // なぜか application/x-www-form-urlencoded でパラメーターを送ると Bad Request になる謎仕様
             endpoint = new Uri(endpoint.OriginalString + "?" + MyCommon.BuildQueryString(param), UriKind.Relative);
 
-            return this.apiConnection.DeleteAsync(endpoint);
+            return this.Connection.DeleteAsync(endpoint);
         }
 
         public Task<TwitterUser> UsersShow(string screenName)
@@ -452,7 +454,7 @@ namespace OpenTween.Api
                 ["tweet_mode"] = "extended",
             };
 
-            return this.apiConnection.GetAsync<TwitterUser>(endpoint, param, "/users/show/:id");
+            return this.Connection.GetAsync<TwitterUser>(endpoint, param, "/users/show/:id");
         }
 
         public Task<TwitterUser[]> UsersLookup(IReadOnlyList<string> userIds)
@@ -466,7 +468,7 @@ namespace OpenTween.Api
                 ["tweet_mode"] = "extended",
             };
 
-            return this.apiConnection.GetAsync<TwitterUser[]>(endpoint, param, "/users/lookup");
+            return this.Connection.GetAsync<TwitterUser[]>(endpoint, param, "/users/lookup");
         }
 
         public Task<LazyJson<TwitterUser>> UsersReportSpam(string screenName)
@@ -478,7 +480,7 @@ namespace OpenTween.Api
                 ["tweet_mode"] = "extended",
             };
 
-            return this.apiConnection.PostLazyAsync<TwitterUser>(endpoint, param);
+            return this.Connection.PostLazyAsync<TwitterUser>(endpoint, param);
         }
 
         public Task<TwitterStatus[]> FavoritesList(int? count = null, long? maxId = null, long? sinceId = null)
@@ -498,7 +500,7 @@ namespace OpenTween.Api
             if (sinceId != null)
                 param["since_id"] = sinceId.ToString();
 
-            return this.apiConnection.GetAsync<TwitterStatus[]>(endpoint, param, "/favorites/list");
+            return this.Connection.GetAsync<TwitterStatus[]>(endpoint, param, "/favorites/list");
         }
 
         public Task<LazyJson<TwitterStatus>> FavoritesCreate(long statusId)
@@ -510,7 +512,7 @@ namespace OpenTween.Api
                 ["tweet_mode"] = "extended",
             };
 
-            return this.apiConnection.PostLazyAsync<TwitterStatus>(endpoint, param);
+            return this.Connection.PostLazyAsync<TwitterStatus>(endpoint, param);
         }
 
         public Task<LazyJson<TwitterStatus>> FavoritesDestroy(long statusId)
@@ -522,7 +524,7 @@ namespace OpenTween.Api
                 ["tweet_mode"] = "extended",
             };
 
-            return this.apiConnection.PostLazyAsync<TwitterStatus>(endpoint, param);
+            return this.Connection.PostLazyAsync<TwitterStatus>(endpoint, param);
         }
 
         public Task<TwitterFriendship> FriendshipsShow(string sourceScreenName, string targetScreenName)
@@ -534,7 +536,7 @@ namespace OpenTween.Api
                 ["target_screen_name"] = targetScreenName,
             };
 
-            return this.apiConnection.GetAsync<TwitterFriendship>(endpoint, param, "/friendships/show");
+            return this.Connection.GetAsync<TwitterFriendship>(endpoint, param, "/friendships/show");
         }
 
         public Task<LazyJson<TwitterFriendship>> FriendshipsCreate(string screenName)
@@ -545,7 +547,7 @@ namespace OpenTween.Api
                 ["screen_name"] = screenName,
             };
 
-            return this.apiConnection.PostLazyAsync<TwitterFriendship>(endpoint, param);
+            return this.Connection.PostLazyAsync<TwitterFriendship>(endpoint, param);
         }
 
         public Task<LazyJson<TwitterFriendship>> FriendshipsDestroy(string screenName)
@@ -556,14 +558,14 @@ namespace OpenTween.Api
                 ["screen_name"] = screenName,
             };
 
-            return this.apiConnection.PostLazyAsync<TwitterFriendship>(endpoint, param);
+            return this.Connection.PostLazyAsync<TwitterFriendship>(endpoint, param);
         }
 
         public Task<long[]> NoRetweetIds()
         {
             var endpoint = new Uri("friendships/no_retweets/ids.json", UriKind.Relative);
 
-            return this.apiConnection.GetAsync<long[]>(endpoint, null, "/friendships/no_retweets/ids");
+            return this.Connection.GetAsync<long[]>(endpoint, null, "/friendships/no_retweets/ids");
         }
 
         public Task<TwitterIds> FollowersIds(long? cursor = null)
@@ -574,7 +576,7 @@ namespace OpenTween.Api
             if (cursor != null)
                 param["cursor"] = cursor.ToString();
 
-            return this.apiConnection.GetAsync<TwitterIds>(endpoint, param, "/followers/ids");
+            return this.Connection.GetAsync<TwitterIds>(endpoint, param, "/followers/ids");
         }
 
         public Task<TwitterIds> MutesUsersIds(long? cursor = null)
@@ -585,7 +587,7 @@ namespace OpenTween.Api
             if (cursor != null)
                 param["cursor"] = cursor.ToString();
 
-            return this.apiConnection.GetAsync<TwitterIds>(endpoint, param, "/mutes/users/ids");
+            return this.Connection.GetAsync<TwitterIds>(endpoint, param, "/mutes/users/ids");
         }
 
         public Task<TwitterIds> BlocksIds(long? cursor = null)
@@ -596,7 +598,7 @@ namespace OpenTween.Api
             if (cursor != null)
                 param["cursor"] = cursor.ToString();
 
-            return this.apiConnection.GetAsync<TwitterIds>(endpoint, param, "/blocks/ids");
+            return this.Connection.GetAsync<TwitterIds>(endpoint, param, "/blocks/ids");
         }
 
         public Task<LazyJson<TwitterUser>> BlocksCreate(string screenName)
@@ -608,7 +610,7 @@ namespace OpenTween.Api
                 ["tweet_mode"] = "extended",
             };
 
-            return this.apiConnection.PostLazyAsync<TwitterUser>(endpoint, param);
+            return this.Connection.PostLazyAsync<TwitterUser>(endpoint, param);
         }
 
         public Task<LazyJson<TwitterUser>> BlocksDestroy(string screenName)
@@ -620,7 +622,7 @@ namespace OpenTween.Api
                 ["tweet_mode"] = "extended",
             };
 
-            return this.apiConnection.PostLazyAsync<TwitterUser>(endpoint, param);
+            return this.Connection.PostLazyAsync<TwitterUser>(endpoint, param);
         }
 
         public async Task<TwitterUser> AccountVerifyCredentials()
@@ -633,7 +635,7 @@ namespace OpenTween.Api
                 ["tweet_mode"] = "extended",
             };
 
-            var user = await this.apiConnection.GetAsync<TwitterUser>(endpoint, param, "/account/verify_credentials")
+            var user = await this.Connection.GetAsync<TwitterUser>(endpoint, param, "/account/verify_credentials")
                 .ConfigureAwait(false);
 
             this.CurrentUserId = user.Id;
@@ -642,7 +644,7 @@ namespace OpenTween.Api
             return user;
         }
 
-        public Task<LazyJson<TwitterUser>> AccountUpdateProfile(string name, string url, string location, string description)
+        public Task<LazyJson<TwitterUser>> AccountUpdateProfile(string name, string url, string? location, string? description)
         {
             var endpoint = new Uri("account/update_profile.json", UriKind.Relative);
             var param = new Dictionary<string, string>
@@ -667,7 +669,7 @@ namespace OpenTween.Api
                 param["description"] = escapedDescription;
             }
 
-            return this.apiConnection.PostLazyAsync<TwitterUser>(endpoint, param);
+            return this.Connection.PostLazyAsync<TwitterUser>(endpoint, param);
         }
 
         public Task<LazyJson<TwitterUser>> AccountUpdateProfileImage(IMediaItem image)
@@ -684,24 +686,24 @@ namespace OpenTween.Api
                 ["image"] = image,
             };
 
-            return this.apiConnection.PostLazyAsync<TwitterUser>(endpoint, param, paramMedia);
+            return this.Connection.PostLazyAsync<TwitterUser>(endpoint, param, paramMedia);
         }
 
         public Task<TwitterRateLimits> ApplicationRateLimitStatus()
         {
             var endpoint = new Uri("application/rate_limit_status.json", UriKind.Relative);
 
-            return this.apiConnection.GetAsync<TwitterRateLimits>(endpoint, null, "/application/rate_limit_status");
+            return this.Connection.GetAsync<TwitterRateLimits>(endpoint, null, "/application/rate_limit_status");
         }
 
         public Task<TwitterConfiguration> Configuration()
         {
             var endpoint = new Uri("help/configuration.json", UriKind.Relative);
 
-            return this.apiConnection.GetAsync<TwitterConfiguration>(endpoint, null, "/help/configuration");
+            return this.Connection.GetAsync<TwitterConfiguration>(endpoint, null, "/help/configuration");
         }
 
-        public Task<LazyJson<TwitterUploadMediaInit>> MediaUploadInit(long totalBytes, string mediaType, string mediaCategory = null)
+        public Task<LazyJson<TwitterUploadMediaInit>> MediaUploadInit(long totalBytes, string mediaType, string? mediaCategory = null)
         {
             var endpoint = new Uri("https://upload.twitter.com/1.1/media/upload.json");
             var param = new Dictionary<string, string>
@@ -714,7 +716,7 @@ namespace OpenTween.Api
             if (mediaCategory != null)
                 param["media_category"] = mediaCategory;
 
-            return this.apiConnection.PostLazyAsync<TwitterUploadMediaInit>(endpoint, param);
+            return this.Connection.PostLazyAsync<TwitterUploadMediaInit>(endpoint, param);
         }
 
         public Task MediaUploadAppend(long mediaId, int segmentIndex, IMediaItem media)
@@ -731,7 +733,7 @@ namespace OpenTween.Api
                 ["media"] = media,
             };
 
-            return this.apiConnection.PostAsync(endpoint, param, paramMedia);
+            return this.Connection.PostAsync(endpoint, param, paramMedia);
         }
 
         public Task<LazyJson<TwitterUploadMediaResult>> MediaUploadFinalize(long mediaId)
@@ -743,7 +745,7 @@ namespace OpenTween.Api
                 ["media_id"] = mediaId.ToString(),
             };
 
-            return this.apiConnection.PostLazyAsync<TwitterUploadMediaResult>(endpoint, param);
+            return this.Connection.PostLazyAsync<TwitterUploadMediaResult>(endpoint, param);
         }
 
         public Task<TwitterUploadMediaResult> MediaUploadStatus(long mediaId)
@@ -755,7 +757,7 @@ namespace OpenTween.Api
                 ["media_id"] = mediaId.ToString(),
             };
 
-            return this.apiConnection.GetAsync<TwitterUploadMediaResult>(endpoint, param, endpointName: null);
+            return this.Connection.GetAsync<TwitterUploadMediaResult>(endpoint, param, endpointName: null);
         }
 
         public Task MediaMetadataCreate(long mediaId, string altText)
@@ -765,10 +767,10 @@ namespace OpenTween.Api
             var escapedAltText = JsonUtils.EscapeJsonString(altText);
             var json = $@"{{""media_id"": ""{mediaId}"", ""alt_text"": {{""text"": ""{escapedAltText}""}}}}";
 
-            return this.apiConnection.PostJsonAsync(endpoint, json);
+            return this.Connection.PostJsonAsync(endpoint, json);
         }
 
-        public TwitterStreamObservable UserStreams(string replies = null, string track = null)
+        public TwitterStreamObservable UserStreams(string? replies = null, string? track = null)
         {
             var endpoint = new Uri("https://userstream.twitter.com/1.1/user.json");
             var param = new Dictionary<string, string>();
@@ -779,13 +781,13 @@ namespace OpenTween.Api
                 param["track"] = track;
 
             Task<Stream> openStream()
-                => this.apiConnection.GetStreamingStreamAsync(endpoint, param);
+                => this.Connection.GetStreamingStreamAsync(endpoint, param);
 
             return new TwitterStreamObservable(openStream);
         }
 
-        public OAuthEchoHandler CreateOAuthEchoHandler(Uri authServiceProvider, Uri realm = null)
-            => ((TwitterApiConnection)this.apiConnection).CreateOAuthEchoHandler(authServiceProvider, realm);
+        public OAuthEchoHandler CreateOAuthEchoHandler(Uri authServiceProvider, Uri? realm = null)
+            => ((TwitterApiConnection)this.Connection).CreateOAuthEchoHandler(authServiceProvider, realm);
 
         public void Dispose()
             => this.apiConnection?.Dispose();
index dc93bb4..fd25a8e 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -35,7 +37,10 @@ namespace OpenTween.Api
     public class TwitterApiException : WebApiException
     {
         public HttpStatusCode StatusCode { get; }
-        public TwitterError ErrorResponse { get; }
+        public TwitterError? ErrorResponse { get; }
+
+        public TwitterErrorItem[] Errors
+            => this.ErrorResponse != null ? this.ErrorResponse.Errors : Array.Empty<TwitterErrorItem>();
 
         public TwitterApiException()
         {
index adf488d..c26815f 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Concurrent;
 using System.Collections.Generic;
@@ -38,13 +40,13 @@ namespace OpenTween.Api
     {
         public TwitterApiAccessLevel AccessLevel { get; set; }
         public EndpointLimits AccessLimit { get; }
-        public ApiLimit MediaUploadLimit { get; set; }
+        public ApiLimit? MediaUploadLimit { get; set; }
 
         public class AccessLimitUpdatedEventArgs : EventArgs
         {
-            public string EndpointName { get; }
+            public string? EndpointName { get; }
 
-            public AccessLimitUpdatedEventArgs(string endpointName)
+            public AccessLimitUpdatedEventArgs(string? endpointName)
                 => this.EndpointName = endpointName;
         }
         public event EventHandler<AccessLimitUpdatedEventArgs> AccessLimitUpdated;
@@ -59,7 +61,7 @@ namespace OpenTween.Api
             this.MediaUploadLimit = null;
         }
 
-        internal static ApiLimit ParseRateLimit(IDictionary<string, string> header, string prefix)
+        internal static ApiLimit? ParseRateLimit(IDictionary<string, string> header, string prefix)
         {
             var limitCount = (int?)ParseHeaderValue(header, prefix + "Limit");
             var limitRemain = (int?)ParseHeaderValue(header, prefix + "Remaining");
@@ -157,12 +159,16 @@ namespace OpenTween.Api
             public EndpointLimits(TwitterApiStatus owner)
                 => this.Owner = owner;
 
-            public ApiLimit this[string endpoint]
+            public ApiLimit? this[string endpoint]
             {
                 get => this.innerDict.TryGetValue(endpoint, out var limit) ? limit : null;
                 set
                 {
-                    this.innerDict[endpoint] = value;
+                    if (value == null)
+                        this.innerDict.TryRemove(endpoint, out var _);
+                    else
+                        this.innerDict[endpoint] = value;
+
                     this.Owner.OnAccessLimitUpdated(new AccessLimitUpdatedEventArgs(endpoint));
                 }
             }
index eaf3a6f..a7e945a 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using OpenTween.Api.DataModel;
 using System;
 using System.IO;
index a666af8..d722c7e 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
@@ -58,6 +60,9 @@ namespace OpenTween
             foreach (var endpoint in _tlEndpoints)
             {
                 var apiLimit = MyCommon.TwitterApiInfo.AccessLimit[endpoint];
+                if (apiLimit == null)
+                    continue;
+
                 AddListViewItem(endpoint, apiLimit, group);
             }
 
@@ -90,10 +95,10 @@ namespace OpenTween
 
         private void UpdateEndpointLimit(string endpoint)
         {
-            var item = this.ListViewApi.Items.Cast<ListViewItem>().FirstOrDefault(x => x.SubItems[0].Text == endpoint);
-            if (item != null)
+            var apiLimit = MyCommon.TwitterApiInfo.AccessLimit[endpoint];
+            if (apiLimit != null)
             {
-                var apiLimit = MyCommon.TwitterApiInfo.AccessLimit[endpoint];
+                var item = this.ListViewApi.Items.Cast<ListViewItem>().Single(x => x.SubItems[0].Text == endpoint);
                 item.SubItems[1].Text = apiLimit.AccessLimitRemain + "/" + apiLimit.AccessLimitCount;
                 item.SubItems[2].Text = apiLimit.AccessLimitResetDate.ToLocalTimeString();
             }
@@ -109,8 +114,9 @@ namespace OpenTween
                 }
                 else
                 {
-                    var endpoint = (e as TwitterApiStatus.AccessLimitUpdatedEventArgs).EndpointName;
-                    UpdateEndpointLimit(endpoint);
+                    var endpoint = ((TwitterApiStatus.AccessLimitUpdatedEventArgs)e).EndpointName;
+                    if (endpoint != null)
+                        UpdateEndpointLimit(endpoint);
                 }
             }
             catch (ObjectDisposedException)
index 5f21754..13f93ed 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
@@ -48,8 +50,8 @@ namespace OpenTween
     {
         public event EventHandler<IntervalChangedEventArgs> IntervalChanged;
 
-        internal Twitter tw;
-        internal TwitterApi twitterApi;
+        internal Twitter tw = null!;
+        internal TwitterApi twitterApi = null!;
 
         public AppendSettingDialog()
         {
@@ -275,7 +277,7 @@ namespace OpenTween
             TwitterApiConnection.RestApiHost = this.ConnectionPanel.TwitterAPIText.Text.Trim();
         }
 
-        private async Task<UserAccount> PinAuth()
+        private async Task<UserAccount?> PinAuth()
         {
             var requestToken = await TwitterApiConnection.GetRequestTokenAsync();
 
index dace571..f384c04 100644 (file)
@@ -25,6 +25,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.IO;
@@ -185,7 +187,7 @@ namespace OpenTween
             }
         }
 
-        private static Process GetPreviousProcess()
+        private static Process? GetPreviousProcess()
         {
             var currentProcess = Process.GetCurrentProcess();
             try
index 2564a5f..e7a2973 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
index ed9565b..e2b17ff 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
index 5919ece..bdee1c7 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
@@ -75,7 +77,7 @@ namespace OpenTween
         /// <param name="owner">親ウィンドウ</param>
         /// <param name="authUri">認証URL</param>
         /// <returns>PIN文字列</returns>
-        public static string DoAuth(IWin32Window owner, Uri authUri)
+        public static string? DoAuth(IWin32Window owner, Uri authUri)
         {
             using var dialog = new AuthDialog();
             dialog.AuthUrl = authUri.AbsoluteUri;
index a0666cf..e043527 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Net.Http;
@@ -172,14 +174,14 @@ namespace OpenTween
         {
         }
 
-        public Bing(HttpClient http)
+        public Bing(HttpClient? http)
             => this.translatorApi = new MicrosoftTranslatorApi(http);
 
         /// <summary>
         /// Microsoft Translator API を使用した翻訳を非同期に行います
         /// </summary>
         /// <exception cref="HttpRequestException"/>
-        public async Task<string> TranslateAsync(string text, string langFrom, string langTo)
+        public async Task<string> TranslateAsync(string text, string? langFrom, string langTo)
             => await this.translatorApi.TranslateAsync(text, langTo, langFrom)
                 .ConfigureAwait(false);
 
index ed0a9a6..c25229e 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.IO;
@@ -30,17 +32,17 @@ namespace OpenTween.Connection
 {
     public interface IApiConnection : IDisposable
     {
-        Task<T> GetAsync<T>(Uri uri, IDictionary<string, string> param, string endpointName);
+        Task<T> GetAsync<T>(Uri uri, IDictionary<string, string>? param, string? endpointName);
 
-        Task<Stream> GetStreamAsync(Uri uri, IDictionary<string, string> param);
+        Task<Stream> GetStreamAsync(Uri uri, IDictionary<string, string>? param);
 
-        Task<Stream> GetStreamingStreamAsync(Uri uri, IDictionary<string, string> param);
+        Task<Stream> GetStreamingStreamAsync(Uri uri, IDictionary<string, string>? param);
 
-        Task<LazyJson<T>> PostLazyAsync<T>(Uri uri, IDictionary<string, string> param);
+        Task<LazyJson<T>> PostLazyAsync<T>(Uri uri, IDictionary<string, string>? param);
 
-        Task<LazyJson<T>> PostLazyAsync<T>(Uri uri, IDictionary<string, string> param, IDictionary<string, IMediaItem> media);
+        Task<LazyJson<T>> PostLazyAsync<T>(Uri uri, IDictionary<string, string>? param, IDictionary<string, IMediaItem>? media);
 
-        Task PostAsync(Uri uri, IDictionary<string, string> param, IDictionary<string, IMediaItem> media);
+        Task PostAsync(Uri uri, IDictionary<string, string>? param, IDictionary<string, IMediaItem>? media);
 
         Task PostJsonAsync(Uri uri, string json);
 
index c65645e..2929ec5 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.IO;
index 8ae866e..38e6269 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.IO;
index 25e88fb..6bcca45 100644 (file)
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable annotations
+
 using System;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using System.Net.Http;
 using System.Runtime.Serialization;
@@ -35,7 +38,7 @@ namespace OpenTween.Connection
     /// </summary>
     public sealed class LazyJson<T> : IDisposable
     {
-        public HttpResponseMessage Response { get; }
+        public HttpResponseMessage? Response { get; }
 
         private T instance;
         private bool completed = false;
@@ -54,7 +57,7 @@ namespace OpenTween.Connection
         public async Task<T> LoadJsonAsync()
         {
             if (this.completed)
-                return this.instance;
+                return this.instance!;
 
             using var content = this.Response.Content;
             var responseText = await content.ReadAsStringAsync()
index 041fa6f..931e233 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.IO;
index 40bf922..78fb59a 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Diagnostics.CodeAnalysis;
@@ -45,7 +47,7 @@ namespace OpenTween.Connection
         /// <summary>
         /// 通信に使用するプロキシ
         /// </summary>
-        public static IWebProxy Proxy { get; private set; } = null;
+        public static IWebProxy? Proxy { get; private set; } = null;
 
         /// <summary>
         /// OpenTween 内で共通して使用する HttpClient インスタンス
@@ -114,7 +116,7 @@ namespace OpenTween.Connection
         public static void SetWebProxy(ProxyType proxyType, string proxyAddress, int proxyPort,
             string proxyUser, string proxyPassword)
         {
-            IWebProxy proxy;
+            IWebProxy? proxy;
             switch (proxyType)
             {
                 case ProxyType.None:
@@ -214,7 +216,7 @@ namespace OpenTween.Connection
 
         private class ForceIPv4Handler : DelegatingHandler
         {
-            private readonly IPAddress ipv4Address;
+            private readonly IPAddress? ipv4Address;
 
             public ForceIPv4Handler(HttpMessageHandler innerHandler)
                 : base(innerHandler)
@@ -226,12 +228,15 @@ namespace OpenTween.Connection
 
             protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
             {
-                var requestUri = request.RequestUri;
-                if (requestUri.Host == "pbs.twimg.com")
+                if (this.ipv4Address != null)
                 {
-                    var rewriteUriStr = requestUri.GetLeftPart(UriPartial.Scheme) + this.ipv4Address + requestUri.PathAndQuery;
-                    request.RequestUri = new Uri(rewriteUriStr);
-                    request.Headers.Host = "pbs.twimg.com";
+                    var requestUri = request.RequestUri;
+                    if (requestUri.Host == "pbs.twimg.com")
+                    {
+                        var rewriteUriStr = requestUri.GetLeftPart(UriPartial.Scheme) + this.ipv4Address + requestUri.PathAndQuery;
+                        request.RequestUri = new Uri(rewriteUriStr);
+                        request.Headers.Host = "pbs.twimg.com";
+                    }
                 }
 
                 return base.SendAsync(request, cancellationToken);
index 8ffc24b..7fde554 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -51,7 +53,7 @@ namespace OpenTween.Connection
         }
 
         public static OAuthEchoHandler CreateHandler(HttpMessageHandler innerHandler, Uri authServiceProvider,
-            string consumerKey, string consumerSecret, string accessToken, string accessSecret, Uri realm = null)
+            string consumerKey, string consumerSecret, string accessToken, string accessSecret, Uri? realm = null)
         {
             var credential = OAuthUtility.CreateAuthorization("GET", authServiceProvider, null,
                 consumerKey, consumerSecret, accessToken, accessSecret, realm?.AbsoluteUri);
index 0e1a3cd..78175dc 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Diagnostics.CodeAnalysis;
@@ -72,7 +74,7 @@ namespace OpenTween.Connection
         /// <summary>
         /// OAuthの署名の対象となるパラメータを抽出します
         /// </summary>
-        internal static async Task<IEnumerable<KeyValuePair<string, string>>> GetParameters(Uri requestUri, HttpContent content)
+        internal static async Task<IEnumerable<KeyValuePair<string, string>>> GetParameters(Uri requestUri, HttpContent? content)
         {
             var parameters = Enumerable.Empty<KeyValuePair<string, string>>();
 
index 8431344..885aa9e 100644 (file)
@@ -25,6 +25,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -53,9 +55,9 @@ namespace OpenTween.Connection
         /// <param name="token">アクセストークン、もしくはリクエストトークン。未取得なら空文字列</param>
         /// <param name="tokenSecret">アクセストークンシークレット。認証処理では空文字列</param>
         /// <param name="realm">realm (必要な場合のみ)</param>
-        public static string CreateAuthorization(string httpMethod, Uri requestUri, IEnumerable<KeyValuePair<string, string>> query,
+        public static string CreateAuthorization(string httpMethod, Uri requestUri, IEnumerable<KeyValuePair<string, string>>? query,
             string consumerKey, string consumerSecret, string token, string tokenSecret,
-            string realm = null)
+            string? realm = null)
         {
             // OAuth共通情報取得
             var parameter = GetOAuthParameter(consumerKey, token);
@@ -107,7 +109,7 @@ namespace OpenTween.Connection
         /// <param name="uri">アクセス先Uri</param>
         /// <param name="parameter">クエリ、もしくはPOSTデータ</param>
         /// <returns>署名文字列</returns>
-        public static string CreateSignature(string consumerSecret, string tokenSecret, string method, Uri uri, Dictionary<string, string> parameter)
+        public static string CreateSignature(string consumerSecret, string? tokenSecret, string method, Uri uri, Dictionary<string, string> parameter)
         {
             // パラメタをソート済みディクショナリに詰替(OAuthの仕様)
             var sorted = new SortedDictionary<string, string>(parameter);
index 6e62623..f603554 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.IO;
@@ -52,9 +54,9 @@ namespace OpenTween.Connection
         public string AccessToken { get; }
         public string AccessSecret { get; }
 
-        internal HttpClient http;
-        internal HttpClient httpUpload;
-        internal HttpClient httpStreaming;
+        internal HttpClient http = null!;
+        internal HttpClient httpUpload = null!;
+        internal HttpClient httpStreaming = null!;
 
         public TwitterApiConnection(string accessToken, string accessSecret)
         {
@@ -76,7 +78,7 @@ namespace OpenTween.Connection
             this.httpStreaming.Timeout = Timeout.InfiniteTimeSpan;
         }
 
-        public async Task<T> GetAsync<T>(Uri uri, IDictionary<string, string> param, string endpointName)
+        public async Task<T> GetAsync<T>(Uri uri, IDictionary<string, string>? param, string? endpointName)
         {
             // レートリミット規制中はAPIリクエストを送信せずに直ちにエラーを発生させる
             if (endpointName != null)
@@ -145,7 +147,7 @@ namespace OpenTween.Connection
             }
         }
 
-        public async Task<Stream> GetStreamAsync(Uri uri, IDictionary<string, string> param)
+        public async Task<Stream> GetStreamAsync(Uri uri, IDictionary<string, string>? param)
         {
             var requestUri = new Uri(RestApiBase, uri);
 
@@ -167,7 +169,7 @@ namespace OpenTween.Connection
             }
         }
 
-        public async Task<Stream> GetStreamingStreamAsync(Uri uri, IDictionary<string, string> param)
+        public async Task<Stream> GetStreamingStreamAsync(Uri uri, IDictionary<string, string>? param)
         {
             var requestUri = new Uri(RestApiBase, uri);
 
@@ -196,7 +198,7 @@ namespace OpenTween.Connection
             }
         }
 
-        public async Task<LazyJson<T>> PostLazyAsync<T>(Uri uri, IDictionary<string, string> param)
+        public async Task<LazyJson<T>> PostLazyAsync<T>(Uri uri, IDictionary<string, string>? param)
         {
             var requestUri = new Uri(RestApiBase, uri);
             var request = new HttpRequestMessage(HttpMethod.Post, requestUri);
@@ -204,7 +206,7 @@ namespace OpenTween.Connection
             using var postContent = new FormUrlEncodedContent(param);
             request.Content = postContent;
 
-            HttpResponseMessage response = null;
+            HttpResponseMessage? response = null;
             try
             {
                 response = await this.http.SendAsync(request, HttpCompletionOption.ResponseHeadersRead)
@@ -232,7 +234,7 @@ namespace OpenTween.Connection
             }
         }
 
-        public async Task<LazyJson<T>> PostLazyAsync<T>(Uri uri, IDictionary<string, string> param, IDictionary<string, IMediaItem> media)
+        public async Task<LazyJson<T>> PostLazyAsync<T>(Uri uri, IDictionary<string, string>? param, IDictionary<string, IMediaItem>? media)
         {
             var requestUri = new Uri(RestApiBase, uri);
             var request = new HttpRequestMessage(HttpMethod.Post, requestUri);
@@ -251,7 +253,7 @@ namespace OpenTween.Connection
 
             request.Content = postContent;
 
-            HttpResponseMessage response = null;
+            HttpResponseMessage? response = null;
             try
             {
                 response = await this.httpUpload.SendAsync(request, HttpCompletionOption.ResponseHeadersRead)
@@ -279,7 +281,7 @@ namespace OpenTween.Connection
             }
         }
 
-        public async Task PostAsync(Uri uri, IDictionary<string, string> param, IDictionary<string, IMediaItem> media)
+        public async Task PostAsync(Uri uri, IDictionary<string, string>? param, IDictionary<string, IMediaItem>? media)
         {
             var requestUri = new Uri(RestApiBase, uri);
             var request = new HttpRequestMessage(HttpMethod.Post, requestUri);
@@ -329,7 +331,7 @@ namespace OpenTween.Connection
             using var postContent = new StringContent(json, Encoding.UTF8, "application/json");
             request.Content = postContent;
 
-            HttpResponseMessage response = null;
+            HttpResponseMessage? response = null;
             try
             {
                 response = await this.http.SendAsync(request, HttpCompletionOption.ResponseHeadersRead)
@@ -426,7 +428,7 @@ namespace OpenTween.Connection
             }
         }
 
-        public OAuthEchoHandler CreateOAuthEchoHandler(Uri authServiceProvider, Uri realm = null)
+        public OAuthEchoHandler CreateOAuthEchoHandler(Uri authServiceProvider, Uri? realm = null)
         {
             var uri = new Uri(RestApiBase, authServiceProvider);
 
@@ -475,7 +477,7 @@ namespace OpenTween.Connection
             return (response["oauth_token"], response["oauth_token_secret"]);
         }
 
-        public static Uri GetAuthorizeUri((string Token, string TokenSecret) requestToken, string screenName = null)
+        public static Uri GetAuthorizeUri((string Token, string TokenSecret) requestToken, string? screenName = null)
         {
             var param = new Dictionary<string, string>
             {
index 3240688..bb48db2 100644 (file)
@@ -25,6 +25,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Drawing;
@@ -139,9 +141,9 @@ namespace OpenTween.Connection
             return mediaId;
         }
 
-        private async Task<long> UploadMediaItem(IMediaItem mediaItem, string mediaCategory)
+        private async Task<long> UploadMediaItem(IMediaItem mediaItem, string? mediaCategory)
         {
-            async Task<long> UploadInternal(IMediaItem media, string category)
+            async Task<long> UploadInternal(IMediaItem media, string? category)
             {
                 var mediaId = await this.tw.UploadMedia(media, category)
                     .ConfigureAwait(false);
@@ -159,7 +161,7 @@ namespace OpenTween.Connection
 
             if (SettingManager.Common.AlphaPNGWorkaround && this.AddAlphaChannelIfNeeded(origImage.Image, out var newImage))
             {
-                using var newMediaItem = new MemoryImageMediaItem(newImage);
+                using var newMediaItem = new MemoryImageMediaItem(newImage!);
                 newMediaItem.AltText = mediaItem.AltText;
 
                 return await UploadInternal(newMediaItem, mediaCategory);
@@ -179,7 +181,7 @@ namespace OpenTween.Connection
         /// PNG 以外の画像や、すでにアルファチャンネルを持つ PNG 画像に対しては何もしません。
         /// </remarks>
         /// <returns>加工が行われた場合は true、そうでない場合は false</returns>
-        private bool AddAlphaChannelIfNeeded(Image origImage, out MemoryImage newImage)
+        private bool AddAlphaChannelIfNeeded(Image origImage, out MemoryImage? newImage)
         {
             newImage = null;
 
index e369589..2031159 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
index 54fa181..ffcac36 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Globalization;
 
index fee31e2..655e8bd 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -40,7 +42,7 @@ namespace OpenTween.OpenTweenCustomControl
     {
         private Rectangle changeBounds;
 
-        public ContextMenuStrip ColumnHeaderContextMenuStrip { get; set; }
+        public ContextMenuStrip? ColumnHeaderContextMenuStrip { get; set; }
 
         public event EventHandler VScrolled;
         public event EventHandler HScrolled;
index 95c01c6..0e135d8 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
@@ -43,14 +45,14 @@ namespace OpenTween
 {
     public partial class EventViewerDialog : OTBaseForm
     {
-        public List<Twitter.FormattedEvent> EventSource { get; set; }
+        public List<Twitter.FormattedEvent> EventSource { get; set; } = new List<Twitter.FormattedEvent>();
 
-        private Twitter.FormattedEvent[] _filterdEventSource;
+        private Twitter.FormattedEvent[] _filterdEventSource = Array.Empty<Twitter.FormattedEvent>();
 
-        private ListViewItem[] _ItemCache = null;
+        private ListViewItem[]? _ItemCache = null;
         private int _itemCacheIndex;
 
-        private TabPage _curTab = null;
+        private TabPage _curTab = null!;
 
         public EventViewerDialog()
         {
index f0a980e..2a4def3 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Globalization;
index 48c7941..845e5ca 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
@@ -89,7 +91,7 @@ namespace OpenTween
         }
         private EnableButtonMode _ruleEnableButtonMode = FilterDialog.EnableButtonMode.NotSelected;
 
-        public TabModel SelectedTab
+        public TabModel? SelectedTab
             => this.selectedTabIndex != -1 ? this.tabs[this.selectedTabIndex] : null;
 
         public FilterDialog()
@@ -427,7 +429,7 @@ namespace OpenTween
             if (rslt == DialogResult.Cancel) return;
 
             var indices = ListFilters.SelectedIndices.Cast<int>().Reverse().ToArray();  // 後ろの要素から削除
-            var tab = (FilterTabModel)this.SelectedTab;
+            var tab = (FilterTabModel)this.SelectedTab!;
 
             using (ControlTransaction.Update(ListFilters))
             {
@@ -633,7 +635,7 @@ namespace OpenTween
                 return;
             }
 
-            var tab = (FilterTabModel)this.SelectedTab;
+            var tab = (FilterTabModel)this.SelectedTab!;
             var i = ListFilters.SelectedIndex;
 
             PostFilterRule ft;
@@ -914,9 +916,9 @@ namespace OpenTween
             if (e.KeyCode == Keys.Escape)
             {
                 if (EditFilterGroup.Enabled)
-                    ButtonCancel_Click(null, null);
+                    ButtonCancel_Click(this.ButtonCancel, EventArgs.Empty);
                 else
-                    ButtonClose_Click(null, null);
+                    ButtonClose_Click(this.ButtonClose, EventArgs.Empty);
             }
         }
 
@@ -966,15 +968,16 @@ namespace OpenTween
         {
             this.selectedTabIndex = this.ListTabs.SelectedIndex;
 
-            if (ListTabs.SelectedIndex > -1)
-                SetFilters(this.SelectedTab);
+            var selectedTab = this.SelectedTab;
+            if (selectedTab != null)
+                SetFilters(selectedTab);
             else
                 ListFilters.Items.Clear();
         }
 
         private async void ButtonAddTab_Click(object sender, EventArgs e)
         {
-            string tabName = null;
+            string? tabName = null;
             MyCommon.TabUsageType tabType;
             using (var inputName = new InputTabName())
             {
@@ -988,7 +991,7 @@ namespace OpenTween
             if (!string.IsNullOrEmpty(tabName))
             {
                 //List対応
-                ListElement list = null;
+                ListElement? list = null;
                 if (tabType == MyCommon.TabUsageType.Lists)
                 {
                     try
@@ -1026,7 +1029,7 @@ namespace OpenTween
                         tab = new PublicSearchTabModel(tabName);
                         break;
                     case MyCommon.TabUsageType.Lists:
-                        tab = new ListTimelineTabModel(tabName, list);
+                        tab = new ListTimelineTabModel(tabName, list!);
                         break;
                     default:
                         return;
@@ -1048,9 +1051,10 @@ namespace OpenTween
 
         private void ButtonDeleteTab_Click(object sender, EventArgs e)
         {
-            if (ListTabs.SelectedIndex > -1)
+            var selectedTab = this.SelectedTab;
+            if (selectedTab != null)
             {
-                var tb = this.SelectedTab.TabName;
+                var tb = selectedTab.TabName;
                 var idx = ListTabs.SelectedIndex;
                 if (((TweenMain)this.Owner).RemoveSpecifiedTab(tb, true))
                 {
@@ -1064,9 +1068,10 @@ namespace OpenTween
 
         private void ButtonRenameTab_Click(object sender, EventArgs e)
         {
-            if (ListTabs.SelectedIndex > -1)
+            var selectedTab = this.SelectedTab;
+            if (selectedTab != null)
             {
-                var origTabName = this.SelectedTab.TabName;
+                var origTabName = selectedTab.TabName;
                 if (((TweenMain)this.Owner).TabRename(origTabName, out _))
                     this.RefreshListTabs();
             }
@@ -1074,10 +1079,11 @@ namespace OpenTween
 
         private void CheckManageRead_CheckedChanged(object sender, EventArgs e)
         {
-            if (ListTabs.SelectedIndex > -1)
+            var selectedTab = this.SelectedTab;
+            if (selectedTab != null)
             {
                 ((TweenMain)this.Owner).ChangeTabUnreadManage(
-                    this.SelectedTab.TabName,
+                    selectedTab.TabName,
                     CheckManageRead.Checked);
             }
         }
@@ -1130,28 +1136,31 @@ namespace OpenTween
 
         private void CheckLocked_CheckedChanged(object sender, EventArgs e)
         {
-            if (ListTabs.SelectedIndex > -1)
+            var selectedTab = this.SelectedTab;
+            if (selectedTab != null)
             {
-                this.SelectedTab.Protected = CheckProtected.Checked;
+                selectedTab.Protected = CheckProtected.Checked;
                 ButtonDeleteTab.Enabled = !CheckProtected.Checked;
             }
         }
 
         private void CheckNotifyNew_CheckedChanged(object sender, EventArgs e)
         {
-            if (ListTabs.SelectedIndex > -1)
+            var selectedTab = this.SelectedTab;
+            if (selectedTab != null)
             {
-                this.SelectedTab.Notify = CheckNotifyNew.Checked;
+                selectedTab.Notify = CheckNotifyNew.Checked;
             }
         }
 
         private void ComboSound_SelectedIndexChanged(object sender, EventArgs e)
         {
-            if (ListTabs.SelectedIndex > -1)
+            var selectedTab = this.SelectedTab;
+            if (selectedTab != null)
             {
                 var filename = "";
                 if (ComboSound.SelectedIndex > -1) filename = ComboSound.SelectedItem.ToString();
-                this.SelectedTab.SoundFile = filename;
+                selectedTab.SoundFile = filename;
             }
         }
 
@@ -1174,9 +1183,9 @@ namespace OpenTween
 
         private void MoveSelectedRules(bool up)
         {
-            var tabIdx = ListTabs.SelectedIndex;
-            if (tabIdx == -1 ||
-                ListFilters.SelectedIndices.Count == 0) return;
+            var selectedTab = this.SelectedTab;
+            if (selectedTab == null || ListFilters.SelectedIndices.Count == 0)
+                return;
 
             var indices = ListFilters.SelectedIndices.Cast<int>().ToArray();
 
@@ -1194,7 +1203,7 @@ namespace OpenTween
             }
 
             var lastSelIdx = indices[0] + diff;
-            var tab = (FilterTabModel)this.SelectedTab;
+            var tab = (FilterTabModel)selectedTab;
 
             try
             {
@@ -1255,9 +1264,10 @@ namespace OpenTween
 
         private void ButtonRuleCopy_Click(object sender, EventArgs e)
         {
-            if (ListTabs.SelectedIndex > -1 && ListFilters.SelectedItem != null)
+            var selectedTab = this.SelectedTab;
+            if (selectedTab != null && ListFilters.SelectedItem != null)
             {
-                TabModel[] selectedTabs;
+                TabModel[] destinationTabs;
                 using (var dialog = new TabsDialog(_sts))
                 {
                     dialog.MultiSelect = true;
@@ -1265,17 +1275,17 @@ namespace OpenTween
 
                     if (dialog.ShowDialog(this) == DialogResult.Cancel) return;
 
-                    selectedTabs = dialog.SelectedTabs;
+                    destinationTabs = dialog.SelectedTabs;
                 }
 
-                var currentTab = (FilterTabModel)this.SelectedTab;
+                var currentTab = (FilterTabModel)selectedTab;
                 var filters = new List<PostFilterRule>();
 
                 foreach (int idx in ListFilters.SelectedIndices)
                 {
                     filters.Add(currentTab.FilterArray[idx].Clone());
                 }
-                foreach (var tb in selectedTabs.Cast<FilterTabModel>())
+                foreach (var tb in destinationTabs.Cast<FilterTabModel>())
                 {
                     if (tb.TabName == currentTab.TabName) continue;
 
@@ -1285,15 +1295,16 @@ namespace OpenTween
                             tb.AddFilter(flt.Clone());
                     }
                 }
-                SetFilters(this.SelectedTab);
+                SetFilters(selectedTab);
             }
         }
 
         private void ButtonRuleMove_Click(object sender, EventArgs e)
         {
-            if (ListTabs.SelectedIndex > -1 && ListFilters.SelectedItem != null)
+            var selectedTab = this.SelectedTab;
+            if (selectedTab != null && ListFilters.SelectedItem != null)
             {
-                TabModel[] selectedTabs;
+                TabModel[] destinationTabs;
                 using (var dialog = new TabsDialog(_sts))
                 {
                     dialog.MultiSelect = true;
@@ -1301,17 +1312,17 @@ namespace OpenTween
 
                     if (dialog.ShowDialog(this) == DialogResult.Cancel) return;
 
-                    selectedTabs = dialog.SelectedTabs;
+                    destinationTabs = dialog.SelectedTabs;
                 }
-                var currentTab = (FilterTabModel)this.SelectedTab;
+                var currentTab = (FilterTabModel)selectedTab;
                 var filters = new List<PostFilterRule>();
 
                 foreach (int idx in ListFilters.SelectedIndices)
                 {
                     filters.Add(currentTab.FilterArray[idx].Clone());
                 }
-                if (selectedTabs.Length == 1 && selectedTabs[0].TabName == currentTab.TabName) return;
-                foreach (var tb in selectedTabs.Cast<FilterTabModel>())
+                if (destinationTabs.Length == 1 && destinationTabs[0].TabName == currentTab.TabName) return;
+                foreach (var tb in destinationTabs.Cast<FilterTabModel>())
                 {
                     if (tb.TabName == currentTab.TabName) continue;
 
@@ -1329,7 +1340,7 @@ namespace OpenTween
                         ListFilters.Items.RemoveAt(idx);
                     }
                 }
-                SetFilters(this.SelectedTab);
+                SetFilters(selectedTab);
             }
         }
 
index b0cd858..aff2021 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -41,16 +43,16 @@ namespace OpenTween
 {
     public class GrowlHelper
     {
-        private Assembly _connector = null;
-        private Assembly _core = null;
+        private Assembly? _connector = null;
+        private Assembly? _core = null;
 
-        private object _growlNTreply;
-        private object _growlNTdm;
-        private object _growlNTnew;
-        private object _growlNTusevent;
-        private object _growlApp;
+        private object? _growlNTreply;
+        private object? _growlNTdm;
+        private object? _growlNTnew;
+        private object? _growlNTusevent;
+        private object? _growlApp;
 
-        private object _targetConnector;
+        private object? _targetConnector;
         bool _initialized = false;
 
         public class NotifyCallbackEventArgs : EventArgs
@@ -252,7 +254,7 @@ namespace OpenTween
             return true;
         }
 
-        public void Notify(NotifyType notificationType, string id, string title, string text, Image icon = null, string url = "")
+        public void Notify(NotifyType notificationType, string id, string title, string text, Image? icon = null, string url = "")
         {
             if (!_initialized) return;
             var notificationName = "";
@@ -271,11 +273,11 @@ namespace OpenTween
                     notificationName = "USERSTREAM_EVENT";
                     break;
             }
-            object n;
+            object? n;
             if (icon != null || !string.IsNullOrEmpty(url))
             {
-                var gCore = _core.GetType("Growl.CoreLibrary.Resource");
-                object res;
+                var gCore = _core!.GetType("Growl.CoreLibrary.Resource");
+                object? res;
                 if (icon != null)
                 {
                     res = gCore.InvokeMember("op_Implicit",
@@ -295,9 +297,9 @@ namespace OpenTween
                                              CultureInfo.InvariantCulture);
                 }
                 var priority =
-                        _connector.GetType("Growl.Connector.Priority").InvokeMember(
+                        _connector!.GetType("Growl.Connector.Priority").InvokeMember(
                             "Normal", BindingFlags.GetField, null, null, null, CultureInfo.InvariantCulture);
-                n = _connector.GetType("Growl.Connector.Notification").InvokeMember(
+                n = _connector!.GetType("Growl.Connector.Notification").InvokeMember(
                         "Notification",
                         BindingFlags.CreateInstance,
                         null,
@@ -315,7 +317,7 @@ namespace OpenTween
             }
             else
             {
-                n = _connector.GetType("Growl.Connector.Notification").InvokeMember(
+                n = _connector!.GetType("Growl.Connector.Notification").InvokeMember(
                         "Notification",
                         BindingFlags.CreateInstance,
                         null,
@@ -332,7 +334,7 @@ namespace OpenTween
                 null, BindingFlags.CreateInstance, null, _connector,
                 new object[] { "some fake information", notificationName },
                 CultureInfo.InvariantCulture);
-            _targetConnector.GetType().InvokeMember("Notify", BindingFlags.InvokeMethod, null, _targetConnector, new object[] { n, cc }, CultureInfo.InvariantCulture);
+            _targetConnector!.GetType().InvokeMember("Notify", BindingFlags.InvokeMethod, null, _targetConnector, new object[] { n, cc }, CultureInfo.InvariantCulture);
         }
 
         private void GrowlCallbackHandler(object response, object callbackData, object state)
@@ -341,7 +343,7 @@ namespace OpenTween
             {
                 // 定数取得
                 var vCLICK =
-                _core.GetType("Growl.CoreLibrary.CallbackResult").GetField(
+                _core!.GetType("Growl.CoreLibrary.CallbackResult").GetField(
                             "CLICK",
                            BindingFlags.Public | BindingFlags.Static).GetRawConstantValue();
                 // 実際の値
index 814968e..7a5b419 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
@@ -129,7 +131,7 @@ namespace OpenTween
 
             foreach (var l in list)
             {
-                var src = l as string;
+                var src = (string)l;
                 if (string.IsNullOrEmpty(src))
                 {
                     idx += 1;
@@ -250,7 +252,7 @@ namespace OpenTween
         }
 
         private void HistoryHashList_DoubleClick(object sender, EventArgs e)
-            => this.OK_Button_Click(null, null);
+            => this.OK_Button_Click(this.OK_Button, EventArgs.Empty);
 
         public void ToggleHash()
         {
@@ -333,9 +335,9 @@ namespace OpenTween
         private void HistoryHashList_KeyDown(object sender, KeyEventArgs e)
         {
             if (e.KeyCode == Keys.Delete)
-                this.DeleteButton_Click(null, null);
+                this.DeleteButton_Click(this.DeleteButton, EventArgs.Empty);
             else if (e.KeyCode == Keys.Insert)
-                this.AddButton_Click(null, null);
+                this.AddButton_Click(this.AddButton, EventArgs.Empty);
         }
 
         private bool AdjustHashtags(ref string hashtag, bool isShowWarn)
@@ -403,17 +405,17 @@ namespace OpenTween
             {
                 e.Handled = true;
                 if (this.GroupDetail.Enabled)
-                    this.PermOK_Button_Click(null, null);
+                    this.PermOK_Button_Click(this.PermOK_Button, EventArgs.Empty);
                 else
-                    this.OK_Button_Click(null, null);
+                    this.OK_Button_Click(this.OK_Button, EventArgs.Empty);
             }
             else if (e.KeyCode == Keys.Escape)
             {
                 e.Handled = true;
                 if (this.GroupDetail.Enabled)
-                    this.PermCancel_Button_Click(null, null);
+                    this.PermCancel_Button_Click(this.PermCancel_Button, EventArgs.Empty);
                 else
-                    this.Cancel_Button_Click(null, null);
+                    this.Cancel_Button_Click(this.Cancel_Button, EventArgs.Empty);
             }
         }
 
index 0812849..a53f517 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
index 6e2d348..5b2bdd0 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -95,10 +97,7 @@ namespace OpenTween
                     if (cachedImageTask != null)
                     {
                         if (force)
-                        {
                             this.innerDictionary.Remove(address);
-                            cachedImageTask = null;
-                        }
                         else
                             return cachedImageTask;
                     }
@@ -127,7 +126,7 @@ namespace OpenTween
                 .ConfigureAwait(false);
         }
 
-        public MemoryImage TryGetFromCache(string address)
+        public MemoryImage? TryGetFromCache(string address)
         {
             lock (this.lockObject)
             {
index a006f15..0584095 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Net.Http;
 using System.Runtime.Serialization;
@@ -35,8 +37,8 @@ namespace OpenTween
     [Serializable]
     public class ImageListViewItem : ListViewItem
     {
-        protected readonly ImageCache imageCache;
-        protected readonly string imageUrl;
+        protected readonly ImageCache? imageCache;
+        protected readonly string? imageUrl;
 
         /// <summary>
         /// 状態表示に使用するアイコンのインデックスを取得・設定する。
@@ -47,7 +49,7 @@ namespace OpenTween
         public int StateIndex { get; set; }
 
         private readonly WeakReference imageReference = new WeakReference(null);
-        private Task imageTask = null;
+        private Task? imageTask = null;
 
         public event EventHandler ImageDownloaded;
 
@@ -56,14 +58,14 @@ namespace OpenTween
         {
         }
 
-        public ImageListViewItem(string[] items, ImageCache imageCache, string imageUrl)
+        public ImageListViewItem(string[] items, ImageCache? imageCache, string? imageUrl)
             : base(items)
         {
             this.imageCache = imageCache;
             this.imageUrl = imageUrl;
             this.StateIndex = -1;
 
-            var image = imageCache?.TryGetFromCache(imageUrl);
+            var image = imageUrl != null ? imageCache?.TryGetFromCache(imageUrl) : null;
 
             if (image != null)
                 this.imageReference.Target = image;
@@ -86,7 +88,7 @@ namespace OpenTween
 
         private async Task GetImageAsyncInternal(bool force)
         {
-            if (string.IsNullOrEmpty(this.imageUrl))
+            if (string.IsNullOrEmpty(this.imageUrl) || this.imageCache == null)
                 return;
 
             if (!force && this.imageReference.Target != null)
index b5cff49..1dea947 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections;
 using System.Collections.Generic;
index 4e5839f..869fb30 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
@@ -44,13 +46,13 @@ namespace OpenTween
         public static DialogResult Show(string text, out string inputText)
             => Show(null, text, "", out inputText);
 
-        public static DialogResult Show(IWin32Window owner, string text, out string inputText)
+        public static DialogResult Show(IWin32Window? owner, string text, out string inputText)
             => Show(owner, text, "", out inputText);
 
         public static DialogResult Show(string text, string caption, out string inputText)
             => Show(null, text, caption, out inputText);
 
-        public static DialogResult Show(IWin32Window owner, string text, string caption, out string inputText)
+        public static DialogResult Show(IWin32Window? owner, string text, string caption, out string inputText)
         {
             using var dialog = new InputDialog();
             dialog.labelMain.Text = text;
index 7623a77..603906b 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
index 4abbdf5..f5078fb 100644 (file)
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Collections;
+using System.Diagnostics.CodeAnalysis;
 
 namespace OpenTween
 {
@@ -131,7 +134,7 @@ namespace OpenTween
         {
             if (!this.innerDict.TryGetValue(item.Key, out var node)) return false;
 
-            return node.Value.Value.Equals(item.Value);
+            return EqualityComparer<TValue>.Default.Equals(node.Value.Value, item.Value);
         }
 
         public bool Remove(TKey key)
@@ -147,20 +150,21 @@ namespace OpenTween
         {
             if (!this.innerDict.TryGetValue(item.Key, out var node)) return false;
 
-            if (!node.Value.Value.Equals(item.Value)) return false;
+            if (!EqualityComparer<TValue>.Default.Equals(node.Value.Value, item.Value))
+                return false;
 
             this.innerList.Remove(node);
 
             return this.innerDict.Remove(item.Key);
         }
 
-        public bool TryGetValue(TKey key, out TValue value)
+        public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
         {
             var ret = this.innerDict.TryGetValue(key, out var node);
 
             if (!ret)
             {
-                value = default;
+                value = default!;
                 return false;
             }
 
index 6df7500..f894476 100644 (file)
@@ -23,6 +23,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
@@ -38,7 +40,7 @@ namespace OpenTween
 {
     public partial class ListAvailable : OTBaseForm
     {
-        public ListElement SelectedList { get; private set; }
+        public ListElement? SelectedList { get; private set; }
 
         public ListAvailable()
             => this.InitializeComponent();
@@ -86,7 +88,7 @@ namespace OpenTween
 
         private void ListsList_SelectedIndexChanged(object sender, EventArgs e)
         {
-            ListElement lst;
+            ListElement? lst;
             if (this.ListsList.SelectedIndex > -1)
             {
                 lst = (ListElement)this.ListsList.SelectedItem;
index d6e769c..179b170 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System.Collections.Generic;
 using System.Threading.Tasks;
 using System.Xml.Serialization;
@@ -44,9 +46,9 @@ namespace OpenTween
         public string Username = "";
         public string Nickname = "";
 
-        protected Twitter _tw;
+        protected Twitter _tw = null!;
 
-        private List<UserInfo> _members = null;
+        private List<UserInfo> _members = new List<UserInfo>();
 
         [XmlIgnore]
         public long Cursor { get; private set; } = -1;
@@ -90,13 +92,7 @@ namespace OpenTween
 
         [XmlIgnore]
         public List<UserInfo> Members
-        {
-            get
-            {
-                if (this._members == null) this._members = new List<UserInfo>();
-                return this._members;
-            }
-        }
+            => this._members;
 
         public async Task RefreshMembers()
         {
index 55c6cb5..fbbe78d 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
@@ -155,7 +157,7 @@ namespace OpenTween
                 }
 
                 this.ListsList.Items.Clear();
-                this.ListManage_Load(null, EventArgs.Empty);
+                this.ListManage_Load(this, EventArgs.Empty);
 
                 this.EditCheckBox.AutoCheck = true;
                 this.EditCheckBox.Checked = false;
@@ -332,7 +334,8 @@ namespace OpenTween
                 }
                 this.DeleteUserButton.Enabled = true;
 
-                await this.LoadUserIconAsync(user.ImageUrl, user.Id);
+                if (user.ImageUrl != null)
+                    await this.LoadUserIconAsync(user.ImageUrl, user.Id);
             }
         }
 
index 1645a30..e626a6d 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
@@ -36,7 +38,7 @@ namespace OpenTween
         public string LoginName => this.textboxLoginName.Text;
         public string Password => this.textboxPassword.Text;
 
-        public Func<Task<bool>> LoginCallback { get; set; } = null;
+        public Func<Task<bool>>? LoginCallback { get; set; } = null;
         public bool LoginSuccessed { get; set; } = false;
 
         public LoginDialog()
index 6fd1e46..e243c21 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Drawing;
 using System.IO;
@@ -62,7 +64,7 @@ namespace OpenTween
         /// <summary>
         /// 代替テキスト (アップロード先が対応している必要がある)
         /// </summary>
-        string AltText { get; set; }
+        string? AltText { get; set; }
 
         /// <summary>
         /// 表示用の MemoryImage を作成する
@@ -92,7 +94,7 @@ namespace OpenTween
     public class FileMediaItem : IMediaItem
     {
         public FileInfo FileInfo { get; }
-        public string AltText { get; set; }
+        public string? AltText { get; set; }
 
         public FileMediaItem(string path)
             => this.FileInfo = new FileInfo(path);
@@ -182,7 +184,7 @@ namespace OpenTween
         }
 
         public string Path { get; }
-        public string AltText { get; set; }
+        public string? AltText { get; set; }
 
         public string Name
             => this.Path.Substring(PathPrefix.Length);
@@ -204,7 +206,7 @@ namespace OpenTween
 
         public Stream OpenRead()
         {
-            MemoryStream memstream = null;
+            MemoryStream? memstream = null;
             try
             {
                 // コピーを作成する
index b73784f..5eec3e0 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
@@ -31,6 +33,7 @@ using System.Threading.Tasks;
 using System.Windows.Forms;
 using OpenTween.Api.DataModel;
 using OpenTween.Connection;
+using System.Diagnostics.CodeAnalysis;
 
 namespace OpenTween
 {
@@ -46,7 +49,7 @@ namespace OpenTween
 
         [Browsable(false)]
         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
-        public OpenFileDialog FilePickDialog { get; set; }
+        public OpenFileDialog? FilePickDialog { get; set; }
 
         /// <summary>
         /// 選択されている投稿先名を取得する。
@@ -69,7 +72,7 @@ namespace OpenTween
         /// </summary>
         [Browsable(false)]
         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
-        public IMediaUploadService SelectedService
+        public IMediaUploadService? SelectedService
         {
             get
             {
@@ -99,11 +102,11 @@ namespace OpenTween
 
         private class SelectedMedia
         {
-            public IMediaItem Item { get; set; }
+            public IMediaItem? Item { get; set; }
             public MyCommon.UploadFileType Type { get; set; }
             public string Text { get; set; }
 
-            public SelectedMedia(IMediaItem item, MyCommon.UploadFileType type, string text)
+            public SelectedMedia(IMediaItem? item, MyCommon.UploadFileType type, string text)
             {
                 this.Item = item;
                 this.Type = type;
@@ -127,12 +130,11 @@ namespace OpenTween
                 => this.Text;
         }
 
-        private Dictionary<string, IMediaUploadService> pictureService;
+        private Dictionary<string, IMediaUploadService> pictureService = new Dictionary<string, IMediaUploadService>();
 
         private void CreateServices(Twitter tw, TwitterConfiguration twitterConfig)
         {
             this.pictureService?.Clear();
-            this.pictureService = null;
 
             this.pictureService = new Dictionary<string, IMediaUploadService> {
                 ["Twitter"] = new TwitterPhoto(tw, twitterConfig),
@@ -330,7 +332,7 @@ namespace OpenTween
         /// <summary>
         /// 選択された投稿先名と投稿する MediaItem を取得する。MediaItem は不要になったら呼び出し側にて破棄すること。
         /// </summary>
-        public bool TryGetSelectedMedia(out string imageService, out IMediaItem[] mediaItems)
+        public bool TryGetSelectedMedia([NotNullWhen(true)] out string? imageService, [NotNullWhen(true)] out IMediaItem[]? mediaItems)
         {
             var validItems = ImagePageCombo.Items.Cast<SelectedMedia>()
                              .Where(x => x.IsValid).Select(x => x.Item).OfType<IMediaItem>().ToArray();
@@ -369,11 +371,11 @@ namespace OpenTween
             return false;
         }
 
-        private MemoryImageMediaItem CreateMemoryImageMediaItem(Image image, bool noMsgBox)
+        private MemoryImageMediaItem? CreateMemoryImageMediaItem(Image image, bool noMsgBox)
         {
             if (image == null) return null;
 
-            MemoryImage memoryImage = null;
+            MemoryImage? memoryImage = null;
             try
             {
                 // image から png 形式の MemoryImage を生成
@@ -390,7 +392,7 @@ namespace OpenTween
             }
         }
 
-        private IMediaItem CreateFileMediaItem(string path, bool noMsgBox)
+        private IMediaItem? CreateFileMediaItem(string path, bool noMsgBox)
         {
             if (string.IsNullOrEmpty(path)) return null;
 
@@ -426,7 +428,7 @@ namespace OpenTween
             ImageFromSelectedFile(item, noMsgBox);
         }
 
-        private void DisposeMediaItem(IMediaItem item)
+        private void DisposeMediaItem(IMediaItem? item)
         {
             var disposableItem = item as IDisposable;
             disposableItem?.Dispose();
@@ -466,10 +468,10 @@ namespace OpenTween
             ValidateNewFileMediaItem(ImagefilePathText.Text.Trim(), AlternativeTextBox.Text.Trim(), false);
         }
 
-        private void ImageFromSelectedFile(IMediaItem item, bool noMsgBox)
+        private void ImageFromSelectedFile(IMediaItem? item, bool noMsgBox)
             => this.ImageFromSelectedFile(-1, item, noMsgBox);
 
-        private void ImageFromSelectedFile(int index, IMediaItem item, bool noMsgBox)
+        private void ImageFromSelectedFile(int index, IMediaItem? item, bool noMsgBox)
         {
             var valid = false;
 
@@ -655,7 +657,11 @@ namespace OpenTween
         }
 
         private void UpdateAltTextPanelVisible()
-            => this.AlternativeTextPanel.Visible = this.SelectedService.CanUseAltText;
+            => this.AlternativeTextPanel.Visible = this.SelectedService switch
+            {
+                null => false,
+                var service => service.CanUseAltText,
+            };
 
         private void ImageServiceCombo_SelectedIndexChanged(object sender, EventArgs e)
         {
@@ -719,7 +725,7 @@ namespace OpenTween
             this.SelectedServiceChanged?.Invoke(this, EventArgs.Empty);
         }
 
-        private void SetImagePageCombo(SelectedMedia media = null)
+        private void SetImagePageCombo(SelectedMedia? media = null)
         {
             using (ControlTransaction.Update(ImagePageCombo))
             {
index d7f3f09..0be6990 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -181,10 +183,10 @@ namespace OpenTween
             return Convert.ToBase64String(hash).GetHashCode();
         }
 
-        public override bool Equals(object other)
+        public override bool Equals(object? other)
             => this.Equals(other as MemoryImage);
 
-        public bool Equals(MemoryImage other)
+        public bool Equals(MemoryImage? other)
         {
             if (object.ReferenceEquals(this, other))
                 return true;
@@ -251,7 +253,7 @@ namespace OpenTween
         /// <exception cref="InvalidImageException">不正な画像データが入力された場合</exception>
         public static MemoryImage CopyFromStream(Stream stream)
         {
-            MemoryStream memstream = null;
+            MemoryStream? memstream = null;
             try
             {
                 memstream = new MemoryStream();
@@ -279,7 +281,7 @@ namespace OpenTween
         /// <exception cref="InvalidImageException">不正な画像データが入力された場合</exception>
         public async static Task<MemoryImage> CopyFromStreamAsync(Stream stream)
         {
-            MemoryStream memstream = null;
+            MemoryStream? memstream = null;
             try
             {
                 memstream = new MemoryStream();
@@ -303,7 +305,7 @@ namespace OpenTween
         /// <exception cref="InvalidImageException">不正な画像データが入力された場合</exception>
         public static MemoryImage CopyFromBytes(byte[] bytes)
         {
-            MemoryStream memstream = null;
+            MemoryStream? memstream = null;
             try
             {
                 memstream = new MemoryStream(bytes);
@@ -326,7 +328,7 @@ namespace OpenTween
         /// <returns>作成された MemoryImage</returns>
         public static MemoryImage CopyFromImage(Image image)
         {
-            MemoryStream memstream = null;
+            MemoryStream? memstream = null;
             try
             {
                 memstream = new MemoryStream();
index 7e4e1c1..4a42aee 100644 (file)
@@ -25,6 +25,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
index daca78a..601dc49 100644 (file)
@@ -25,6 +25,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
index ed0367f..4afa68e 100644 (file)
@@ -25,6 +25,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
index dc2b479..6bad336 100644 (file)
@@ -25,6 +25,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
@@ -170,7 +172,7 @@ namespace OpenTween.Models
 
         public override Task RefreshAsync(Twitter tw, bool backward, bool startup, IProgress<string> progress)
         {
-            var homeTab = TabInformations.GetInstance().GetTabByType<HomeTabModel>();
+            var homeTab = TabInformations.GetInstance().HomeTab;
 
             return homeTab.RefreshAsync(tw, backward, startup, progress);
         }
index 98a599e..284e97c 100644 (file)
@@ -25,6 +25,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Concurrent;
 using System.Collections.Generic;
index 01f04d7..058ee1b 100644 (file)
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 
 namespace OpenTween.Models
 {
@@ -33,6 +36,6 @@ namespace OpenTween.Models
 
         bool Contains(string tabName);
 
-        bool TryGetValue(string tabName, out TabModel tab);
+        bool TryGetValue(string tabName, [NotNullWhen(true)] out TabModel? tab);
     }
 }
index 47f206c..0e39cd5 100644 (file)
@@ -25,6 +25,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Concurrent;
 using System.Collections.Generic;
index 2e59847..6769bc7 100644 (file)
@@ -25,6 +25,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
index 0e11401..4773cfe 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
index a3330ca..51fa8a5 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -30,22 +32,22 @@ namespace OpenTween.Models
     public class MediaInfo
     {
         public string Url { get; }
-        public string AltText { get; }
-        public string VideoUrl { get; }
+        public string? AltText { get; }
+        public string? VideoUrl { get; }
 
         public MediaInfo(string url)
             : this(url, altText: null, videoUrl: null)
         {
         }
 
-        public MediaInfo(string url, string altText, string videoUrl)
+        public MediaInfo(string url, string? altText, string? videoUrl)
         {
             this.Url = url;
             this.AltText = altText;
             this.VideoUrl = !string.IsNullOrEmpty(videoUrl) ? videoUrl : null;
         }
 
-        public override bool Equals(object obj)
+        public override bool Equals(object? obj)
             => obj is MediaInfo info && info.Url == this.Url && info.VideoUrl == this.VideoUrl;
 
         public override int GetHashCode()
index 5ff6966..2d38b60 100644 (file)
@@ -25,6 +25,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
index 64ebf6f..adc1c83 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
index 464af21..1e21938 100644 (file)
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using System.Net;
 using System.Text;
@@ -63,14 +66,15 @@ namespace OpenTween.Models
             public static bool operator !=(StatusGeo left, StatusGeo right)
                 => !left.Equals(right);
         }
-        public string Nickname { get; set; }
-        public string TextFromApi { get; set; }
+
+        public string Nickname { get; set; } = "";
+        public string TextFromApi { get; set; } = "";
 
         /// <summary>スクリーンリーダーでの読み上げを考慮したテキスト</summary>
-        public string AccessibleText { get; set; }
+        public string AccessibleText { get; set; } = "";
 
-        public string ImageUrl { get; set; }
-        public string ScreenName { get; set; }
+        public string ImageUrl { get; set; } = "";
+        public string ScreenName { get; set; } = "";
         public DateTimeUtc CreatedAt { get; set; }
         public long StatusId { get; set; }
         private bool _IsFav;
@@ -90,7 +94,7 @@ namespace OpenTween.Models
             }
             set => this._text = value;
         }
-        private string _text;
+        private string _text = "";
 
         public bool IsRead { get; set; }
         public bool IsReply { get; set; }
@@ -98,16 +102,16 @@ namespace OpenTween.Models
         private bool _IsProtect;
         public bool IsOwl { get; set; }
         private bool _IsMark;
-        public string InReplyToUser { get; set; }
+        public string? InReplyToUser { get; set; }
         private long? _InReplyToStatusId;
-        public string Source { get; set; }
-        public Uri SourceUri { get; set; }
+        public string Source { get; set; } = "";
+        public Uri? SourceUri { get; set; }
         public List<(long UserId, string ScreenName)> ReplyToList { get; set; }
         public bool IsMe { get; set; }
         public bool IsDm { get; set; }
         public long UserId { get; set; }
         public bool FilterHit { get; set; }
-        public string RetweetedBy { get; set; }
+        public string? RetweetedBy { get; set; }
         public long? RetweetedId { get; set; }
         private bool _IsDeleted = false;
         private StatusGeo? _postGeo = null;
@@ -189,7 +193,6 @@ namespace OpenTween.Models
 
         public PostClass()
         {
-            RetweetedBy = "";
             Media = new List<MediaInfo>();
             ReplyToList = new List<(long, string)>();
             QuoteStatusIds = Array.Empty<long>();
@@ -197,7 +200,7 @@ namespace OpenTween.Models
         }
 
         public string TextSingleLine
-            => this.TextFromApi?.Replace("\n", " ");
+            => this.TextFromApi.Replace("\n", " ");
 
         public bool IsFav
         {
@@ -286,8 +289,8 @@ namespace OpenTween.Models
             }
         }
 
-        protected virtual PostClass RetweetSource
-            => TabInformations.GetInstance().RetweetSource(this.RetweetedId.Value);
+        protected virtual PostClass? RetweetSource
+            => this.RetweetedId != null ? TabInformations.GetInstance().RetweetSource(this.RetweetedId.Value) : null;
 
         public StatusGeo? PostGeo
         {
@@ -433,13 +436,13 @@ namespace OpenTween.Models
         object ICloneable.Clone()
             => this.Clone();
 
-        public override bool Equals(object obj)
+        public override bool Equals(object? obj)
         {
             if (obj == null || this.GetType() != obj.GetType()) return false;
             return this.Equals((PostClass)obj);
         }
 
-        public bool Equals(PostClass other)
+        public bool Equals(PostClass? other)
         {
             if (other == null) return false;
             return (this.Nickname == other.Nickname) &&
index 17b7679..c8ad53e 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
@@ -47,7 +49,7 @@ namespace OpenTween.Models
         /// コンパイルされた振り分けルール
         /// </summary>
         [XmlIgnore]
-        protected Func<PostClass, MyCommon.HITRESULT> FilterDelegate;
+        protected Func<PostClass, MyCommon.HITRESULT>? FilterDelegate;
 
         /// <summary>
         /// 振り分けルールの概要
@@ -72,20 +74,20 @@ namespace OpenTween.Models
         private bool _enabled;
 
         [XmlElement("NameFilter")]
-        public string FilterName
+        public string? FilterName
         {
             get => this._FilterName;
             set => this.SetProperty(ref this._FilterName, value);
         }
-        private string _FilterName;
+        private string? _FilterName;
 
         [XmlElement("ExNameFilter")]
-        public string ExFilterName
+        public string? ExFilterName
         {
             get => this._ExFilterName;
             set => this.SetProperty(ref this._ExFilterName, value);
         }
-        private string _ExFilterName;
+        private string? _ExFilterName;
 
         [XmlArray("BodyFilterArray")]
         public string[] FilterBody
@@ -210,20 +212,20 @@ namespace OpenTween.Models
         private bool _ExFilterRt;
 
         [XmlElement("Source")]
-        public string FilterSource
+        public string? FilterSource
         {
             get => this._FilterSource;
             set => this.SetProperty(ref this._FilterSource, value);
         }
-        private string _FilterSource;
+        private string? _FilterSource;
 
         [XmlElement("ExSource")]
-        public string ExFilterSource
+        public string? ExFilterSource
         {
             get => this._ExFilterSource;
             set => this.SetProperty(ref this._ExFilterSource, value);
         }
-        private string _ExFilterSource;
+        private string? _ExFilterSource;
 
         public PostFilterRule()
         {
@@ -322,9 +324,9 @@ namespace OpenTween.Models
             this.IsDirty = false;
         }
 
-        protected virtual Expression MakeFiltersExpr(
+        protected virtual Expression? MakeFiltersExpr(
             ParameterExpression postParam,
-            string filterName, string[] filterBody, string filterSource, bool filterRt,
+            string? filterName, string[] filterBody, string? filterSource, bool filterRt,
             bool useRegex, bool caseSensitive, bool useNameField, bool useLambda, bool filterByUrl)
         {
             var filterExprs = new List<Expression>();
@@ -477,7 +479,7 @@ namespace OpenTween.Models
                 this.Compile();
             }
 
-            return this.FilterDelegate(post);
+            return this.FilterDelegate!(post);
         }
 
         public PostFilterRule Clone()
@@ -703,10 +705,10 @@ namespace OpenTween.Models
                 !string.IsNullOrEmpty(this.ExFilterSource) ||
                 this.ExFilterRt;
 
-        public override bool Equals(object obj)
+        public override bool Equals(object? obj)
             => this.Equals(obj as PostFilterRule);
 
-        public bool Equals(PostFilterRule other)
+        public bool Equals(PostFilterRule? other)
         {
             if (other == null)
                 return false;
index 43d3e1d..8e8fd8c 100644 (file)
@@ -25,6 +25,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
index a16badd..5575f23 100644 (file)
@@ -25,6 +25,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
index 6ad1886..45922f8 100644 (file)
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System.Collections.ObjectModel;
+using System.Diagnostics.CodeAnalysis;
 
 namespace OpenTween.Models
 {
@@ -28,7 +31,7 @@ namespace OpenTween.Models
         public int IndexOf(string tabName)
             => this.IndexOf(this[tabName]);
 
-        public bool TryGetValue(string tabName, out TabModel tab)
+        public bool TryGetValue(string tabName, [NotNullWhen(true)] out TabModel? tab)
             => this.Dictionary.TryGetValue(tabName, out tab);
 
         protected override string GetKeyForItem(TabModel tab)
index cb97fc9..d33b340 100644 (file)
@@ -25,6 +25,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Concurrent;
 using System.Collections.Generic;
@@ -43,7 +45,7 @@ namespace OpenTween.Models
         public IReadOnlyTabCollection Tabs
             => this.tabs;
 
-        public MuteTabModel MuteTab { get; private set; }
+        public MuteTabModel MuteTab { get; private set; } = new MuteTabModel();
 
         public ConcurrentDictionary<long, PostClass> Posts { get; } = new ConcurrentDictionary<long, PostClass>();
 
@@ -99,7 +101,7 @@ namespace OpenTween.Models
             get => this._lists;
             set
             {
-                if (value != null && value.Count > 0)
+                if (value.Count > 0)
                 {
                     foreach (var tb in this.GetTabsByType<ListTimelineTabModel>())
                     {
@@ -123,9 +125,6 @@ namespace OpenTween.Models
             {
                 if (tab is MuteTabModel muteTab)
                 {
-                    if (this.MuteTab != null)
-                        return false;
-
                     this.MuteTab = muteTab;
                     return true;
                 }
@@ -150,12 +149,12 @@ namespace OpenTween.Models
             lock (LockObj)
             {
                 var tb = GetTabByName(TabName);
-                if (tb.IsDefaultTabType) return; //念のため
+                if (tb == null || tb.IsDefaultTabType) return; //念のため
 
                 if (!tb.IsInnerStorageTabType)
                 {
-                    var homeTab = GetTabByType(MyCommon.TabUsageType.Home);
-                    var dmTab = GetTabByType(MyCommon.TabUsageType.DirectMessage);
+                    var homeTab = this.HomeTab;
+                    var dmTab = this.DirectMessageTab;
 
                     for (var idx = 0; idx < tb.AllCount; ++idx)
                     {
@@ -296,7 +295,7 @@ namespace OpenTween.Models
         //            }
         //        }
         //    }
-        public PostClass RetweetSource(long Id)
+        public PostClass? RetweetSource(long Id)
             => this.Posts.TryGetValue(Id, out var status) ? status : null;
 
         public void ScrubGeoReserve(long id, long upToStatusId)
@@ -443,9 +442,9 @@ namespace OpenTween.Models
         {
             lock (this.LockObj)
             {
-                var homeTab = this.GetTabByType(MyCommon.TabUsageType.Home);
-                var replyTab = this.GetTabByType(MyCommon.TabUsageType.Mentions);
-                var favTab = this.GetTabByType(MyCommon.TabUsageType.Favorites);
+                var homeTab = this.HomeTab;
+                var replyTab = this.MentionTab;
+                var favTab = this.FavoriteTab;
 
                 var distributableTabs = this.GetTabsByType<FilterTabModel>()
                     .ToArray();
@@ -591,6 +590,9 @@ namespace OpenTween.Models
 
         private int UpdateRetweetCount(PostClass retweetPost)
         {
+            if (retweetPost.RetweetedId == null)
+                throw new InvalidOperationException();
+
             var retweetedId = retweetPost.RetweetedId.Value;
 
             return this.retweetsCount.AddOrUpdate(retweetedId, 1, (k, v) => v >= 10 ? 1 : v + 1);
@@ -640,7 +642,7 @@ namespace OpenTween.Models
         /// </summary>
         public void SetReadHomeTab()
         {
-            var homeTab = this.GetTabByType(MyCommon.TabUsageType.Home);
+            var homeTab = this.HomeTab;
 
             lock (LockObj)
             {
@@ -657,7 +659,7 @@ namespace OpenTween.Models
             }
         }
 
-        public PostClass this[long ID]
+        public PostClass? this[long ID]
         {
             get
             {
@@ -698,7 +700,7 @@ namespace OpenTween.Models
         {
             lock (LockObj)
             {
-                var homeTab = GetTabByType(MyCommon.TabUsageType.Home);
+                var homeTab = this.HomeTab;
                 var detachedIdsAll = Enumerable.Empty<long>();
 
                 foreach (var tab in this.Tabs.OfType<FilterTabModel>().ToArray())
@@ -846,7 +848,19 @@ namespace OpenTween.Models
             }
         }
 
-        public TabModel GetTabByType(MyCommon.TabUsageType tabType)
+        public HomeTabModel HomeTab
+            => this.GetTabByType<HomeTabModel>()!;
+
+        public DirectMessagesTabModel DirectMessageTab
+            => this.GetTabByType<DirectMessagesTabModel>()!;
+
+        public MentionsTabModel MentionTab
+            => this.GetTabByType<MentionsTabModel>()!;
+
+        public FavoritesTabModel FavoriteTab
+            => this.GetTabByType<FavoritesTabModel>()!;
+
+        public TabModel? GetTabByType(MyCommon.TabUsageType tabType)
         {
             //Home,Mentions,DM,Favは1つに制限する
             //その他のタイプを指定されたら、最初に合致したものを返す
@@ -857,7 +871,7 @@ namespace OpenTween.Models
             }
         }
 
-        public T GetTabByType<T>() where T : TabModel
+        public T? GetTabByType<T>() where T : TabModel
         {
             lock (this.LockObj)
                 return this.Tabs.OfType<T>().FirstOrDefault();
@@ -889,7 +903,7 @@ namespace OpenTween.Models
             }
         }
 
-        public TabModel GetTabByName(string tabName)
+        public TabModel? GetTabByName(string tabName)
         {
             lock (LockObj)
             {
index 6f1c076..aa47d8b 100644 (file)
@@ -25,6 +25,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Concurrent;
 using System.Collections.Generic;
@@ -78,7 +80,7 @@ namespace OpenTween.Models
         public PostClass[] SelectedPosts
             => this.selectedStatusIds.Select(x => this.Posts[x]).ToArray();
 
-        public PostClass SelectedPost
+        public PostClass? SelectedPost
             => this.selectedStatusIds.Select(x => this.Posts[x]).FirstOrDefault();
 
         public int SelectedIndex
@@ -232,16 +234,16 @@ namespace OpenTween.Models
                 {
                     default:
                     case ComparerMode.Data:
-                        postComparison = (x, y) => Comparer<string>.Default.Compare(x?.TextFromApi, y?.TextFromApi);
+                        postComparison = (x, y) => Comparer<string?>.Default.Compare(x?.TextFromApi, y?.TextFromApi);
                         break;
                     case ComparerMode.Name:
-                        postComparison = (x, y) => Comparer<string>.Default.Compare(x?.ScreenName, y?.ScreenName);
+                        postComparison = (x, y) => Comparer<string?>.Default.Compare(x?.ScreenName, y?.ScreenName);
                         break;
                     case ComparerMode.Nickname:
-                        postComparison = (x, y) => Comparer<string>.Default.Compare(x?.Nickname, y?.Nickname);
+                        postComparison = (x, y) => Comparer<string?>.Default.Compare(x?.Nickname, y?.Nickname);
                         break;
                     case ComparerMode.Source:
-                        postComparison = (x, y) => Comparer<string>.Default.Compare(x?.Source, y?.Source);
+                        postComparison = (x, y) => Comparer<string?>.Default.Compare(x?.Source, y?.Source);
                         break;
                 }
 
index f217eb4..318f9d7 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
index 621bb16..f658754 100644 (file)
@@ -25,6 +25,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
index 0ab0345..eb2e691 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Drawing;
index ce83e65..982d67c 100644 (file)
@@ -25,6 +25,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -175,7 +177,7 @@ namespace OpenTween
             //}
         }
 
-        public static readonly object Block = null;
+        public static readonly object? Block = null;
         public static bool TraceFlag = false;
 
 #if DEBUG
@@ -436,7 +438,7 @@ namespace OpenTween
             }
         }
 
-        private static void OpenErrorReportDialog(Form owner, ErrorReport report)
+        private static void OpenErrorReportDialog(Form? owner, ErrorReport report)
         {
             if (owner != null && owner.InvokeRequired)
             {
@@ -458,7 +460,7 @@ namespace OpenTween
         /// </summary>
         /// <param name="inputUrl">展開対象のURL</param>
         /// <returns>IDNが含まれていた場合はPunycodeに展開したURLをを返します。Punycode展開時にエラーが発生した場合はnullを返します。</returns>
-        public static string IDNEncode(string inputUrl)
+        public static string? IDNEncode(string inputUrl)
         {
             try
             {
@@ -559,8 +561,8 @@ namespace OpenTween
             des.Key = ResizeBytesArray(bytesKey, des.Key.Length);
             des.IV = ResizeBytesArray(bytesKey, des.IV.Length);
 
-            MemoryStream msOut = null;
-            ICryptoTransform desdecrypt = null;
+            MemoryStream? msOut = null;
+            ICryptoTransform? desdecrypt = null;
 
             try
             {
@@ -611,9 +613,9 @@ namespace OpenTween
             //Base64で文字列をバイト配列に戻す
             var bytesIn = Convert.FromBase64String(str);
 
-            MemoryStream msIn = null;
-            ICryptoTransform desdecrypt = null;
-            CryptoStream cryptStreem = null;
+            MemoryStream? msIn = null;
+            ICryptoTransform? desdecrypt = null;
+            CryptoStream? cryptStreem = null;
 
             try
             {
@@ -700,7 +702,7 @@ namespace OpenTween
 
         public static bool IsAnimatedGif(string filename)
         {
-            Image img = null;
+            Image? img = null;
             try
             {
                 img = Image.FromFile(filename);
@@ -832,7 +834,7 @@ namespace OpenTween
         /// <returns>
         /// 生成されたバージョン番号の文字列
         /// </returns>
-        public static string GetReadableVersion(string versionStr = null)
+        public static string GetReadableVersion(string? versionStr = null)
         {
             var version = Version.Parse(versionStr ?? MyCommon.FileVersion);
 
index 111dc47..5a255d0 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
@@ -41,8 +43,8 @@ namespace OpenTween
 {
     public partial class MyLists : OTBaseForm
     {
-        private readonly TwitterApi twitterApi;
-        private readonly string contextScreenName;
+        private readonly TwitterApi twitterApi = null!;
+        private readonly string contextScreenName = null!;
 
         /// <summary>自分が所有しているリスト</summary>
         private ListElement[] ownedLists = Array.Empty<ListElement>();
@@ -93,7 +95,7 @@ namespace OpenTween
                 this.twitterApi.ListsOwnerships(this.twitterApi.CurrentScreenName, cursor: x, count: 1000))
                     .ConfigureAwait(false);
 
-            this.ownedLists = ownedListData.Select(x => new ListElement(x, null)).ToArray();
+            this.ownedLists = ownedListData.Select(x => new ListElement(x, null!)).ToArray();
 
             var listsUserAddedTo = await TwitterLists.GetAllItemsAsync(x =>
                 this.twitterApi.ListsMemberships(this.contextScreenName, cursor: x, count: 1000, filterToOwnedLists: true))
index d6a5c9f..b20e9e0 100644 (file)
@@ -25,6 +25,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.ComponentModel;
 using System.Diagnostics;
@@ -313,8 +315,8 @@ namespace OpenTween
         private struct InternetProxyInfo
         {
             public InternetOpenType dwAccessType;
-            public string proxy;
-            public string proxyBypass;
+            public string? proxy;
+            public string? proxyBypass;
         }
 
         private enum InternetOpenType
@@ -324,7 +326,7 @@ namespace OpenTween
             PROXY = 3, // Custom
         }
 
-        private static void RefreshProxySettings(string strProxy)
+        private static void RefreshProxySettings(string? strProxy)
         {
             InternetProxyInfo ipi;
 
@@ -377,7 +379,7 @@ namespace OpenTween
 
         public static void SetProxy(ProxyType pType, string host, int port)
         {
-            string proxy = null;
+            string? proxy = null;
             switch (pType)
             {
             case ProxyType.IE:
index 9e87db0..7cf65b4 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
diff --git a/OpenTween/NullableAttributes.cs b/OpenTween/NullableAttributes.cs
new file mode 100644 (file)
index 0000000..da10813
--- /dev/null
@@ -0,0 +1,43 @@
+// OpenTween - Client of Twitter
+// Copyright (c) 2019 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
+// All rights reserved.
+//
+// This file is part of OpenTween.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program. If not, see <http://www.gnu.org/licenses/>, or write to
+// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+#nullable enable
+
+namespace System.Diagnostics.CodeAnalysis
+{
+    [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
+    internal sealed class NotNullWhenAttribute : Attribute
+    {
+        public bool ReturnValue { get; }
+
+        public NotNullWhenAttribute(bool returnValue)
+            => this.ReturnValue = returnValue;
+    }
+
+    [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
+    internal sealed class MaybeNullWhenAttribute : Attribute
+    {
+        public bool ReturnValue { get; }
+
+        public MaybeNullWhenAttribute(bool returnValue)
+            => this.ReturnValue = returnValue;
+    }
+}
index b354259..3f65752 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
@@ -42,7 +44,7 @@ namespace OpenTween
         /// <remarks>
         /// SettingLocal.xml に FontUIGlobalStr 要素を追加する事で変更できます
         /// </remarks>
-        public static Font GlobalFont { get; set; }
+        public static Font? GlobalFont { get; set; }
 
         /// <summary>
         /// デザイン時のスケールと現在のスケールの比
index 1ff43a6..de72839 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -40,7 +42,7 @@ namespace OpenTween
     {
         [Browsable(false)]
         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
-        public new MemoryImage Image
+        public new MemoryImage? Image
         {
             get => this.memoryImage;
             set
@@ -51,7 +53,7 @@ namespace OpenTween
                 this.RestoreSizeMode();
             }
         }
-        private MemoryImage memoryImage;
+        private MemoryImage? memoryImage;
 
         [Localizable(true)]
         [DefaultValue(PictureBoxSizeMode.Normal)]
@@ -167,7 +169,7 @@ namespace OpenTween
         [Browsable(false)]
         [EditorBrowsable(EditorBrowsableState.Never)]
         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
-        public new string ImageLocation
+        public new string? ImageLocation
         {
             get => null;
             set { }
index 13eed70..dd96215 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Windows.Forms;
 using System.Collections.Generic;
index 3b43d55..961c361 100644 (file)
     <Compile Include="Models\UserTimelineTabModel.cs" />
     <Compile Include="MouseWheelMessageFilter.cs" />
     <Compile Include="NotifyPropertyChangedBase.cs" />
+    <Compile Include="NullableAttributes.cs" />
     <Compile Include="PostStatusParams.cs" />
     <Compile Include="ReaderWriterLockTransaction.cs" />
     <Compile Include="SendErrorReportForm.cs">
index 6d1dc95..7c98af1 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
@@ -37,7 +39,7 @@ namespace OpenTween
 {
     public partial class OpenURL : OTBaseForm
     {
-        private string _selUrl;
+        private string? _selUrl;
 
         public OpenURL()
             => this.InitializeComponent();
@@ -73,7 +75,7 @@ namespace OpenTween
             get
             {
                 if (UrlList.SelectedItems.Count == 1)
-                    return _selUrl;
+                    return _selUrl!;
                 else
                     return "";
             }
@@ -114,7 +116,7 @@ namespace OpenTween
             if (e.Control && e.KeyCode == Keys.Oem4)
             {
                 e.SuppressKeyPress = true;
-                Cancel_Button_Click(null, null);
+                Cancel_Button_Click(this.Cancel_Button, EventArgs.Empty);
             }
         }
     }
index a102b26..705f573 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -30,11 +32,11 @@ namespace OpenTween
 {
     public class PostStatusParams
     {
-        public string Text { get; set; }
+        public string Text { get; set; } = "";
         public long? InReplyToStatusId { get; set; }
-        public IReadOnlyList<long> MediaIds { get; set; }
+        public IReadOnlyList<long> MediaIds { get; set; } = Array.Empty<long>();
         public bool AutoPopulateReplyMetadata { get; set; }
-        public IReadOnlyList<long> ExcludeReplyUserIds { get; set; }
-        public string AttachmentUrl { get; set; }
+        public IReadOnlyList<long> ExcludeReplyUserIds { get; set; } = Array.Empty<long>();
+        public string? AttachmentUrl { get; set; }
     }
 }
index c932d8f..f3e5ba0 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
index 1a0c1c2..f21eca0 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Concurrent;
 using System.Collections.Generic;
index 2d9ea2c..58df000 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
@@ -69,13 +71,13 @@ namespace OpenTween
             }
         }
 
-        private SearchOptions resultOptoins = null;
-        public SearchOptions ResultOptions
+        private SearchOptions? resultOptions = null;
+        public SearchOptions? ResultOptions
         {
-            get => this.resultOptoins;
+            get => this.resultOptions;
             set
             {
-                this.resultOptoins = value;
+                this.resultOptions = value;
 
                 if (value == null)
                 {
index ec95b14..3c319a8 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
@@ -47,7 +49,7 @@ namespace OpenTween
                 this.bindingSource.DataSource = value;
             }
         }
-        private ErrorReport _errorReport;
+        private ErrorReport _errorReport = null!;
 
         public SendErrorReportForm()
             => this.InitializeComponent();
@@ -99,7 +101,7 @@ namespace OpenTween
                 this.UpdateEncodedReport();
             }
         }
-        private string _reportText;
+        private string _reportText = "";
 
         public bool AnonymousReport
         {
@@ -124,9 +126,9 @@ namespace OpenTween
             get => this._encodedReportForDM;
             private set => this.SetProperty(ref this._encodedReportForDM, value);
         }
-        private string _encodedReportForDM;
+        private string _encodedReportForDM = "";
 
-        private readonly Twitter tw;
+        private readonly Twitter? tw;
         private readonly string originalReportText;
 
         public ErrorReport(string reportText)
@@ -134,7 +136,7 @@ namespace OpenTween
         {
         }
 
-        public ErrorReport(Twitter tw, string reportText)
+        public ErrorReport(Twitter? tw, string reportText)
         {
             this.tw = tw;
             this.originalReportText = reportText;
@@ -156,7 +158,12 @@ namespace OpenTween
         }
 
         public async Task SendByDmAsync()
-            => await this.tw.SendDirectMessage(this.EncodedReportForDM);
+        {
+            if (!this.CheckDmAvailable())
+                return;
+
+            await this.tw!.SendDirectMessage(this.EncodedReportForDM);
+        }
 
         private void UpdateEncodedReport()
         {
@@ -181,7 +188,7 @@ namespace OpenTween
                 this.EncodedReportForDM = $"D {destScreenName} ErrorReport: {encodedReport}";
             }
 
-            this.CanSendByDM = this.tw.GetTextLengthRemain(this.EncodedReportForDM) >= 0;
+            this.CanSendByDM = this.tw!.GetTextLengthRemain(this.EncodedReportForDM) >= 0;
         }
 
         private bool CheckDmAvailable()
index 7762554..677dee4 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
index a1e7f61..78fa0ac 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
index 6551811..fe6176a 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
index be5cdfe..a4f9f3e 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
index b0b075f..0beaf3f 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
index fa0f1cd..3718da1 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
index 48f1ded..0866d7d 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
index 49d47f6..2c2cae5 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
index 60fe0f5..5a7c168 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
@@ -84,7 +86,7 @@ namespace OpenTween.Setting.Panel
 
         private class EventCheckboxTblElement
         {
-            public CheckBox CheckBox;
+            public CheckBox CheckBox = null!;
             public MyCommon.EVENTTYPE Type;
         }
 
index 77b779c..ab34ec0 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
index 5b82adc..13c33cd 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
index 8b5a274..7989899 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
index ae542d2..ccd0379 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
@@ -93,7 +95,7 @@ namespace OpenTween.Setting.Panel
             const string DialogText = "Bitly Login";
             dialog.Text = DialogText;
 
-            string accessToken = null;
+            string? accessToken = null;
             dialog.LoginCallback = async () =>
             {
                 try
index 05e5b07..6da9cfe 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
index 93115a4..69406d5 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
index 1055b71..03b27c6 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
index 5efd780..3201c4b 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
index 9321ea0..d197410 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -46,7 +48,7 @@ namespace OpenTween
         /// XML に含まれていた場合に破棄せず保持するため必要となる。
         /// </remarks>
         [XmlAnyElement]
-        public XmlElement[] ExtraElements;
+        public XmlElement[] ExtraElements = Array.Empty<XmlElement>();
 
         private static readonly object lockObj = new object();
 
@@ -119,7 +121,7 @@ namespace OpenTween
                 return;
 
             var retryCount = 0;
-            Exception lastException = null;
+            Exception? lastException = null;
 
             var filePath = GetSettingFilePath(fileId);
             do
index 353f425..dd1f359 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Xml.Serialization;
 using System.Collections.Generic;
@@ -42,7 +44,7 @@ namespace OpenTween
             => SaveSettings(this);
         #endregion
 
-        public List<UserAccount> UserAccounts;
+        public List<UserAccount> UserAccounts = new List<UserAccount>();
         public string UserName = "";
 
         [XmlIgnore]
@@ -99,7 +101,7 @@ namespace OpenTween
         }
 
         public long UserId = 0;
-        public List<string> TabList;
+        public List<string> TabList = new List<string>();
         public int TimelinePeriod = 90;
         public int ReplyPeriod = 180;
         public int DMPeriod = 600;
@@ -245,14 +247,14 @@ namespace OpenTween
 
         /// <summary>アップデート通知を無視するバージョン番号</summary>
         [XmlIgnore]
-        public Version SkipUpdateVersion
+        public Version? SkipUpdateVersion
         {
             get => string.IsNullOrEmpty(this.SkipUpdateVersionStr) ? null : Version.Parse(this.SkipUpdateVersionStr);
             set => this.SkipUpdateVersionStr = value == null ? "" : value.ToString();
         }
 
         [XmlElement(ElementName = nameof(SkipUpdateVersion))]
-        public string SkipUpdateVersionStr { get; set; }
+        public string SkipUpdateVersionStr { get; set; } = "";
     }
 
     public class UserAccount
index 44e1628..eb4a608 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -253,7 +255,7 @@ namespace OpenTween
         }
 
         [XmlIgnore]
-        public Font FontUIGlobal = null;
+        public Font? FontUIGlobal = null;
 
         /// <summary>
         /// [隠し設定] UI フォントを指定します
@@ -261,10 +263,10 @@ namespace OpenTween
         /// <remarks>
         /// フォントによっては一部レイアウトが崩れるためこっそり追加
         /// </remarks>
-        public string FontUIGlobalStr
+        public string? FontUIGlobalStr
         {
-            get => this.FontToString(this.FontUIGlobal);
-            set => this.FontUIGlobal = this.StringToFont(value);
+            get => this.FontUIGlobal != null ? this.FontToString(this.FontUIGlobal) : null;
+            set => this.FontUIGlobal = value != null ? this.StringToFont(value) : null;
         }
 
         [XmlIgnore]
@@ -319,10 +321,10 @@ namespace OpenTween
         private readonly FontConverter fontConverter = new FontConverter();
 
         protected string FontToString(Font font)
-            => font != null ? this.fontConverter.ConvertToString(font) : null;
+            => this.fontConverter.ConvertToString(font);
 
         protected Font StringToFont(string str)
-            => str != null ? (Font)this.fontConverter.ConvertFromString(str) : null;
+            => (Font)this.fontConverter.ConvertFromString(str);
 
         [XmlIgnore]
         private readonly ColorConverter colorConverter = new ColorConverter();
@@ -351,10 +353,10 @@ namespace OpenTween
         {
             if (disposing)
             {
-                this.FontUnread.Dispose();
-                this.FontRead.Dispose();
-                this.FontDetail.Dispose();
-                this.FontInputFont.Dispose();
+                this.FontUnread?.Dispose();
+                this.FontRead?.Dispose();
+                this.FontDetail?.Dispose();
+                this.FontInputFont?.Dispose();
             }
         }
     }
index b98c7cf..7da155c 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
index 26918e2..a612ef1 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -52,7 +54,7 @@ namespace OpenTween
         public class SettingTabItem
         {
             /// <summary>タブの表示名</summary>
-            public string TabName { get; set; }
+            public string TabName { get; set; } = "";
 
             /// <summary>タブの種類</summary>
             public MyCommon.TabUsageType TabType { get; set; }
@@ -68,7 +70,7 @@ namespace OpenTween
             public bool Notify { get; set; }
 
             /// <summary>通知音</summary>
-            public string SoundFile { get; set; }
+            public string SoundFile { get; set; } = "";
 
             /// <summary>
             /// 振り分けルール (<see cref="MyCommon.TabUsageType.UserDefined"/> で使用)
@@ -78,7 +80,7 @@ namespace OpenTween
             /// <summary>
             /// 表示するユーザーのスクリーンネーム (<see cref="MyCommon.TabUsageType.UserTimeline"/> で使用)
             /// </summary>
-            public string User { get; set; }
+            public string? User { get; set; }
 
             /// <summary>
             /// 検索文字列 (<see cref="MyCommon.TabUsageType.PublicSearch"/> で使用)
@@ -93,7 +95,7 @@ namespace OpenTween
             /// <summary>
             /// 表示するリスト (<see cref="MyCommon.TabUsageType.Lists"/> で使用)
             /// </summary>
-            public ListElement ListInfo { get; set; }
+            public ListElement? ListInfo { get; set; }
         }
     }
 }
index cc218e0..d887255 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Concurrent;
 using System.Collections.Generic;
@@ -63,9 +65,9 @@ namespace OpenTween
         /// </summary>
         public int PurgeCount { get; set; }
 
-        public string BitlyAccessToken { get; set; }
-        public string BitlyId { get; set; }
-        public string BitlyKey { get; set; }
+        public string BitlyAccessToken { get; set; } = "";
+        public string BitlyId { get; set; } = "";
+        public string BitlyKey { get; set; } = "";
 
         private HttpClient http;
         private readonly ConcurrentDictionary<Uri, Uri> urlCache = new ConcurrentDictionary<Uri, Uri>();
@@ -201,7 +203,8 @@ namespace OpenTween
                 if (!ShortUrlHosts.Contains(uri.Host) && !IsIrregularShortUrl(uri))
                     return uri;
 
-                if (this.urlCache.TryGetValue(uri, out var expanded))
+                Uri? expanded;
+                if (this.urlCache.TryGetValue(uri, out expanded))
                     return expanded;
 
                 if (this.urlCache.Count > this.PurgeCount)
@@ -459,7 +462,7 @@ namespace OpenTween
             return false;
         }
 
-        private async Task<Uri> GetRedirectTo(Uri url)
+        private async Task<Uri?> GetRedirectTo(Uri url)
         {
             url = this.UpgradeToHttpsIfAvailable(url);
 
index a06afa0..86305e3 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
index 4f885ec..124e58d 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
index b44a44c..9966b55 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
@@ -44,8 +46,8 @@ namespace OpenTween
 
         protected internal class TabListItem
         {
-            public TabModel Tab { get; set; }
-            public string Label { get; set; }
+            public TabModel? Tab { get; set; }
+            public string Label { get; set; } = "";
 
             public override string ToString()
                 => this.Label;
@@ -106,13 +108,14 @@ namespace OpenTween
                 this.OK_Button.Enabled = true;
         }
 
-        public TabModel SelectedTab
+        public TabModel? SelectedTab
             => this.TabList.SelectedItem is TabListItem item ? item.Tab : null;
 
         public TabModel[] SelectedTabs
             => this.TabList.SelectedItems
                     .Cast<TabListItem>()
                     .Select(x => x.Tab)
+                    .OfType<TabModel>()
                     .ToArray();
     }
 }
index 9b88463..3553c80 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Threading;
 using System.Threading.Tasks;
index b0f244a..310d8ae 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -34,7 +36,6 @@ namespace OpenTween.Thumbnail
     {
         public double Latitude { get; set; }
         public double Longitude { get; set; }
-        public string LocateInfo { get; set; }
     }
 
     public enum MapProvider
@@ -47,7 +48,7 @@ namespace OpenTween.Thumbnail
     {
         public abstract Task<ThumbnailInfo> GetThumbnailInfoAsync(PostClass.StatusGeo geo);
 
-        private static MapThumb defaultInstance = null;
+        private static MapThumb defaultInstance = null!;
 
         public static MapThumb GetDefaultInstance()
         {
@@ -68,7 +69,7 @@ namespace OpenTween.Thumbnail
 
             if (MapThumb.defaultInstance == null || MapThumb.defaultInstance.GetType() != classType)
             {
-                MapThumb.defaultInstance = Activator.CreateInstance(classType) as MapThumb;
+                MapThumb.defaultInstance = (MapThumb)Activator.CreateInstance(classType);
             }
 
             return MapThumb.defaultInstance;
index 0bb6464..ac1861c 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
index 044b2e1..c4a76fe 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Drawing;
@@ -135,7 +137,7 @@ namespace OpenTween.Thumbnail
                 }
             }
 
-            MemoryImage result = null;
+            MemoryImage? result = null;
             try
             {
                 result = MemoryImage.CopyFromImage(bitmap);
@@ -152,7 +154,7 @@ namespace OpenTween.Thumbnail
             using var stream = await http.GetStreamAsync(tileUrl)
                 .ConfigureAwait(false);
 
-            MemoryImage result = null;
+            MemoryImage? result = null;
             try
             {
                 result = await MemoryImage.CopyFromStreamAsync(stream).ConfigureAwait(false);
index d6827d5..d37f7be 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Globalization;
@@ -49,17 +51,17 @@ namespace OpenTween.Thumbnail.Services
         protected HttpClient http
             => this.localHttpClient ?? Networking.Http;
 
-        private readonly HttpClient localHttpClient;
+        private readonly HttpClient? localHttpClient;
 
         public FoursquareCheckin()
             : this(null)
         {
         }
 
-        public FoursquareCheckin(HttpClient http)
+        public FoursquareCheckin(HttpClient? http)
             => this.localHttpClient = http;
 
-        public override async Task<ThumbnailInfo> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token)
+        public override async Task<ThumbnailInfo?> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token)
         {
             // ツイートに位置情報が付与されている場合は何もしない
             if (post.PostGeo != null)
@@ -88,7 +90,7 @@ namespace OpenTween.Thumbnail.Services
         /// <summary>
         /// Foursquare のチェックイン URL から位置情報を取得します
         /// </summary>
-        public async Task<GlobalLocation> FetchCheckinLocation(string url, CancellationToken token)
+        public async Task<GlobalLocation?> FetchCheckinLocation(string url, CancellationToken token)
         {
             var match = UrlPatternRegex.Match(url);
             if (!match.Success)
@@ -131,7 +133,7 @@ namespace OpenTween.Thumbnail.Services
         /// <summary>
         /// Foursquare のチェックイン URL から位置情報を取得します (古い形式の URL)
         /// </summary>
-        public async Task<GlobalLocation> FetchCheckinLocationLegacy(string url, CancellationToken token)
+        public async Task<GlobalLocation?> FetchCheckinLocationLegacy(string url, CancellationToken token)
         {
             var match = LegacyUrlPatternRegex.Match(url);
 
@@ -174,7 +176,7 @@ namespace OpenTween.Thumbnail.Services
             }
         }
 
-        internal static GlobalLocation ParseIntoLocation(byte[] jsonBytes)
+        internal static GlobalLocation? ParseIntoLocation(byte[] jsonBytes)
         {
             using var jsonReader = JsonReaderWriterFactory.CreateJsonReader(jsonBytes, XmlDictionaryReaderQuotas.Max);
             var xElm = XElement.Load(jsonReader);
index 74df597..a2d970e 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -31,6 +33,6 @@ namespace OpenTween.Thumbnail.Services
 {
     abstract class IThumbnailService
     {
-        public abstract Task<ThumbnailInfo> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token);
+        public abstract Task<ThumbnailInfo?> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token);
     }
 }
index 89f2bde..670bf21 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -49,14 +51,14 @@ namespace OpenTween.Thumbnail.Services
             "Gyazo",
         };
 
-        protected string ApiBase;
-        protected IEnumerable<Regex> UrlRegex = null;
+        protected string? ApiBase;
+        protected IEnumerable<Regex>? UrlRegex = null;
         protected Timer UpdateTimer;
 
         protected HttpClient http
             => this.localHttpClient ?? Networking.Http;
 
-        private readonly HttpClient localHttpClient;
+        private readonly HttpClient? localHttpClient;
 
         private readonly object LockObj = new object();
 
@@ -65,12 +67,12 @@ namespace OpenTween.Thumbnail.Services
         {
         }
 
-        public ImgAzyobuziNet(HttpClient http)
+        public ImgAzyobuziNet(HttpClient? http)
             : this(http, autoupdate: false)
         {
         }
 
-        public ImgAzyobuziNet(HttpClient http, bool autoupdate)
+        public ImgAzyobuziNet(HttpClient? http, bool autoupdate)
         {
             this.UpdateTimer = new Timer(async _ => await this.LoadRegexAsync());
             this.AutoUpdate = autoupdate;
@@ -183,7 +185,7 @@ namespace OpenTween.Thumbnail.Services
                 .ConfigureAwait(false);
         }
 
-        public override Task<ThumbnailInfo> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token)
+        public override Task<ThumbnailInfo?> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token)
         {
             return Task.Run(() =>
             {
index a740f69..14f908a 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -48,7 +50,7 @@ namespace OpenTween.Thumbnail.Services
         protected HttpClient http
             => this.localHttpClient ?? Networking.Http;
 
-        private readonly HttpClient localHttpClient;
+        private readonly HttpClient? localHttpClient;
 
         protected readonly Regex regex;
         protected readonly string[] propertyNames;
@@ -58,24 +60,24 @@ namespace OpenTween.Thumbnail.Services
         {
         }
 
-        public MetaThumbnailService(string urlPattern, string[] propNames)
+        public MetaThumbnailService(string urlPattern, string[]? propNames)
             : this(null, urlPattern, propNames)
         {
         }
 
-        public MetaThumbnailService(HttpClient http, string urlPattern)
+        public MetaThumbnailService(HttpClient? http, string urlPattern)
             : this(http, urlPattern, null)
         {
         }
 
-        public MetaThumbnailService(HttpClient http, string urlPattern, string[] propNames)
+        public MetaThumbnailService(HttpClient? http, string urlPattern, string[]? propNames)
         {
             this.localHttpClient = http;
             this.regex = new Regex(urlPattern);
             this.propertyNames = propNames ?? MetaThumbnailService.PropertyNames;
         }
 
-        public override async Task<ThumbnailInfo> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token)
+        public override async Task<ThumbnailInfo?> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token)
         {
             if (!this.regex.IsMatch(url))
                 return null;
@@ -100,7 +102,7 @@ namespace OpenTween.Thumbnail.Services
             return null;
         }
 
-        protected virtual string GetThumbnailUrl(string html)
+        protected virtual string? GetThumbnailUrl(string html)
         {
             foreach (var pattern in MetaThumbnailService.MetaPatterns)
             {
index 344704d..8fa39a4 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Globalization;
@@ -45,7 +47,7 @@ namespace OpenTween.Thumbnail.Services
         public static readonly Regex UrlPatternRegex =
             new Regex(@"^https?://(?:(www|ext)\.nicovideo\.jp/watch|nico\.ms)/(?<id>(?:sm|nm)?[0-9]+)(\?.+)?$");
 
-        public override async Task<ThumbnailInfo> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token)
+        public override async Task<ThumbnailInfo?> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token)
         {
             var match = Nicovideo.UrlPatternRegex.Match(url);
             if (!match.Success)
index 0771f56..8e65b07 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -39,7 +41,7 @@ namespace OpenTween.Thumbnail.Services
         {
         }
 
-        public override async Task<ThumbnailInfo> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token)
+        public override async Task<ThumbnailInfo?> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token)
         {
             var thumb = await base.GetThumbnailInfoAsync(url, post, token)
                 .ConfigureAwait(false);
index ab2bf18..a8f233a 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -43,12 +45,12 @@ namespace OpenTween.Thumbnail.Services
         {
         }
 
-        public Pixiv(HttpClient http)
+        public Pixiv(HttpClient? http)
             : base(http, Pixiv.UrlPattern)
         {
         }
 
-        public override async Task<ThumbnailInfo> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token)
+        public override async Task<ThumbnailInfo?> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token)
         {
             var thumb = await base.GetThumbnailInfoAsync(url, post, token)
                 .ConfigureAwait(false);
index c0c79ae..8de0cd5 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -38,21 +40,21 @@ namespace OpenTween.Thumbnail.Services
     {
         protected Regex regex;
         protected string thumb_replacement;
-        protected string fullsize_replacement;
+        protected string? fullsize_replacement;
 
         public SimpleThumbnailService(string pattern, string replacement)
             : this(pattern, replacement, null)
         {
         }
 
-        public SimpleThumbnailService(string pattern, string replacement, string file_replacement)
+        public SimpleThumbnailService(string pattern, string replacement, string? file_replacement)
         {
             this.regex = new Regex(pattern, RegexOptions.IgnoreCase);
             this.thumb_replacement = replacement;
             this.fullsize_replacement = file_replacement;
         }
 
-        public override Task<ThumbnailInfo> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token)
+        public override Task<ThumbnailInfo?> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token)
         {
             return Task.Run(() =>
             {
@@ -69,10 +71,10 @@ namespace OpenTween.Thumbnail.Services
             }, token);
         }
 
-        protected string ReplaceUrl(string url)
+        protected string? ReplaceUrl(string url)
             => this.ReplaceUrl(url, this.thumb_replacement);
 
-        protected string ReplaceUrl(string url, string replacement)
+        protected string? ReplaceUrl(string url, string? replacement)
         {
             if (replacement == null) return null;
             var match = this.regex.Match(url);
index 57b3f44..de0979e 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -43,17 +45,17 @@ namespace OpenTween.Thumbnail.Services
         protected HttpClient http
             => this.localHttpClient ?? Networking.Http;
 
-        private readonly HttpClient localHttpClient;
+        private readonly HttpClient? localHttpClient;
 
         public Tinami()
             : this(null)
         {
         }
 
-        public Tinami(HttpClient http)
+        public Tinami(HttpClient? http)
             => this.localHttpClient = http;
 
-        public override async Task<ThumbnailInfo> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token)
+        public override async Task<ThumbnailInfo?> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token)
         {
             var match = Tinami.UrlPatternRegex.Match(url);
             if (!match.Success)
index e9b1ef5..2657876 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.IO;
@@ -40,9 +42,9 @@ namespace OpenTween.Thumbnail.Services
     {
         internal static Func<IApiConnection> GetApiConnection;
 
-        public override Task<ThumbnailInfo> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token)
+        public override Task<ThumbnailInfo?> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token)
         {
-            return Task.Run<ThumbnailInfo>(() =>
+            return Task.Run<ThumbnailInfo?>(() =>
             {
                 if (GetApiConnection == null)
                     return null;
index cee91f4..402edbd 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -44,17 +46,17 @@ namespace OpenTween.Thumbnail.Services
         protected HttpClient http
             => this.localHttpClient ?? Networking.Http;
 
-        private readonly HttpClient localHttpClient;
+        private readonly HttpClient? localHttpClient;
 
         public Tumblr()
             : this(null)
         {
         }
 
-        public Tumblr(HttpClient http)
+        public Tumblr(HttpClient? http)
             => this.localHttpClient = http;
 
-        public override async Task<ThumbnailInfo> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token)
+        public override async Task<ThumbnailInfo?> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token)
         {
             var match = Tumblr.UrlPatternRegex.Match(url);
             if (!match.Success)
index f53093a..d9c1bd4 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -43,12 +45,12 @@ namespace OpenTween.Thumbnail.Services
         {
         }
 
-        public TwitterComVideo(HttpClient http)
+        public TwitterComVideo(HttpClient? http)
             : base(http, TwitterComVideo.UrlPattern)
         {
         }
 
-        public override async Task<ThumbnailInfo> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token)
+        public override async Task<ThumbnailInfo?> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token)
         {
             // 前処理で動画用URLが準備されていればそれを使う
             var mediaInfo = post.Media.FirstOrDefault(x => x.Url == url);
index b1c851f..30354ad 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -45,17 +47,17 @@ namespace OpenTween.Thumbnail.Services
         protected HttpClient http
             => this.localHttpClient ?? Networking.Http;
 
-        private readonly HttpClient localHttpClient;
+        private readonly HttpClient? localHttpClient;
 
         public Vimeo()
             : this(null)
         {
         }
 
-        public Vimeo(HttpClient http)
+        public Vimeo(HttpClient? http)
             => this.localHttpClient = http;
 
-        public override async Task<ThumbnailInfo> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token)
+        public override async Task<ThumbnailInfo?> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token)
         {
             var match = Vimeo.UrlPatternRegex.Match(url);
             if (!match.Success)
index 261fa13..181f8a5 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -41,7 +43,7 @@ namespace OpenTween.Thumbnail.Services
         public static readonly Regex UrlPatternRegex =
             new Regex(@"^https?://(?:((?:www|m)\.youtube\.com)|(youtu\.be))/(watch\?v=)?(?<videoid>([\w\-]+))");
 
-        public override Task<ThumbnailInfo> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token)
+        public override Task<ThumbnailInfo?> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token)
         {
             return Task.Run(() =>
             {
index e303fb3..9a207c3 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -183,7 +185,7 @@ namespace OpenTween.Thumbnail
             return thumbnails;
         }
 
-        public static async Task<ThumbnailInfo> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token)
+        public static async Task<ThumbnailInfo?> GetThumbnailInfoAsync(string url, PostClass post, CancellationToken token)
         {
             foreach (var generator in ThumbnailGenerator.Services)
             {
index 8ed7d56..4dfe201 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -37,26 +39,26 @@ namespace OpenTween.Thumbnail
         /// 例えば Youtube のサムネイルの場合、動画そのものの URL ではなく
         /// https://www.youtube.com/watch?v=****** 形式の URL が含まれる
         /// </remarks>
-        public string MediaPageUrl { get; set; }
+        public string MediaPageUrl { get; set; } = "";
 
         /// <summary>サムネイルとして表示する画像の URL</summary>
         /// <remarks>
         /// ここに含まれる URL は直接画像として表示可能である必要がある
         /// </remarks>
-        public string ThumbnailImageUrl { get; set; }
+        public string ThumbnailImageUrl { get; set; } = "";
 
         /// <summary>最も高解像度な画像の URL</summary>
         /// <remarks>
         /// サムネイルとしては不適だが、より高解像度な画像を表示する場面に使用できる
         /// URL があればここに含まれる
         /// </remarks>
-        public string FullSizeImageUrl { get; set; }
+        public string? FullSizeImageUrl { get; set; }
 
         /// <summary>ツールチップとして表示するテキスト</summary>
         /// <remarks>
         /// サムネイル画像にマウスオーバーした際に表示されるテキスト
         /// </remarks>
-        public string TooltipText { get; set; }
+        public string? TooltipText { get; set; }
 
         /// <summary>
         /// 対象となるメディアが動画や音声など再生可能なものであるか否か
@@ -71,7 +73,7 @@ namespace OpenTween.Thumbnail
 
         public async virtual Task<MemoryImage> LoadThumbnailImageAsync(HttpClient http, CancellationToken cancellationToken)
         {
-            MemoryImage image = null;
+            MemoryImage? image = null;
             try
             {
                 using var response = await http.GetAsync(this.ThumbnailImageUrl, cancellationToken)
@@ -96,10 +98,10 @@ namespace OpenTween.Thumbnail
             }
         }
 
-        public override bool Equals(object obj)
+        public override bool Equals(object? obj)
             => this.Equals(obj as ThumbnailInfo);
 
-        public bool Equals(ThumbnailInfo other)
+        public bool Equals(ThumbnailInfo? other)
             => other != null &&
                 other.MediaPageUrl == this.MediaPageUrl &&
                 other.ThumbnailImageUrl == this.ThumbnailImageUrl &&
index 421dae1..434d151 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Threading;
@@ -76,13 +78,13 @@ namespace OpenTween
         public TimeSpan UpdateIntervalConfig { get; set; } = Timeout.InfiniteTimeSpan;
         public TimeSpan UpdateAfterSystemResume { get; set; } = Timeout.InfiniteTimeSpan;
 
-        public Func<Task> UpdateHome;
-        public Func<Task> UpdateMention;
-        public Func<Task> UpdateDm;
-        public Func<Task> UpdatePublicSearch;
-        public Func<Task> UpdateUser;
-        public Func<Task> UpdateList;
-        public Func<Task> UpdateConfig;
+        public Func<Task>? UpdateHome;
+        public Func<Task>? UpdateMention;
+        public Func<Task>? UpdateDm;
+        public Func<Task>? UpdatePublicSearch;
+        public Func<Task>? UpdateUser;
+        public Func<Task>? UpdateList;
+        public Func<Task>? UpdateConfig;
 
         [Flags]
         private enum UpdateTask
index 6e60632..992bf62 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -66,7 +68,7 @@ namespace OpenTween
         /// API 実行回数制限の値
         /// </summary>
         [Browsable(false)]
-        public ApiLimit ApiLimit
+        public ApiLimit? ApiLimit
         {
             get => this._ApiLimit;
             private set
@@ -79,13 +81,13 @@ namespace OpenTween
                 this.Invalidate();
             }
         }
-        private ApiLimit _ApiLimit = null;
+        private ApiLimit? _ApiLimit = null;
 
         /// <summary>
         /// API エンドポイント名
         /// </summary>
         [Browsable(false)]
-        public string ApiEndpoint
+        public string? ApiEndpoint
         {
             get => this._ApiEndpoint;
             set
@@ -117,7 +119,7 @@ namespace OpenTween
                 }
             }
         }
-        private string _ApiEndpoint = null;
+        private string? _ApiEndpoint = null;
 
         [Browsable(false)]
         [EditorBrowsable(EditorBrowsableState.Never)]
index c705682..7aa8492 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
index 7bd1bdb..c7efd06 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 //コンパイル後コマンド
 //"c:\Program Files\Microsoft.NET\SDK\v2.0\Bin\sgen.exe" /f /a:"$(TargetPath)"
 //"C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\sgen.exe" /f /a:"$(TargetPath)"
@@ -33,6 +35,7 @@ using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.ComponentModel;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Drawing;
 using System.Globalization;
 using System.IO;
@@ -93,11 +96,11 @@ namespace OpenTween
         /// <summary>タブドラッグ中フラグ(DoDragDropを実行するかの判定用)</summary>
         private bool _tabDrag;
 
-        private TabPage _beforeSelectedTab; // タブが削除されたときに前回選択されていたときのタブを選択する為に保持
+        private TabPage? _beforeSelectedTab; // タブが削除されたときに前回選択されていたときのタブを選択する為に保持
         private Point _tabMouseDownPoint;
 
         /// <summary>右クリックしたタブの名前(Tabコントロール機能不足対応)</summary>
-        private string _rclickTabName;
+        private string? _rclickTabName;
 
         private readonly object _syncObject = new object(); // ロック用
 
@@ -127,8 +130,8 @@ namespace OpenTween
             + "--></style>"
             + "</head><body><p>";
         private const string detailHtmlFormatFooterColor = "</p></body></html>";
-        private string detailHtmlFormatHeader;
-        private string detailHtmlFormatFooter;
+        private string detailHtmlFormatHeader = null!;
+        private string detailHtmlFormatFooter = null!;
 
         private bool _myStatusError = false;
         private bool _myStatusOnline = false;
@@ -137,7 +140,7 @@ namespace OpenTween
 
         //twitter解析部
         private readonly TwitterApi twitterApi = new TwitterApi();
-        private Twitter tw;
+        private Twitter tw = null!;
 
         //Growl呼び出し部
         private readonly GrowlHelper gh = new GrowlHelper(ApplicationSettings.ApplicationName);
@@ -150,24 +153,24 @@ namespace OpenTween
         private readonly OpenURL UrlDialog = new OpenURL();
 
         /// <summary>@id補助</summary>
-        public AtIdSupplement AtIdSupl;
+        public AtIdSupplement AtIdSupl = null!;
 
         /// <summary>Hashtag補助</summary>
-        public AtIdSupplement HashSupl;
+        public AtIdSupplement HashSupl = null!;
 
-        public HashtagManage HashMgr;
-        private EventViewerDialog evtDialog;
+        public HashtagManage HashMgr = null!;
+        private EventViewerDialog evtDialog = null!;
 
         //表示フォント、色、アイコン
 
         /// <summary>未読用フォント</summary>
-        private Font _fntUnread;
+        private Font _fntUnread = null!;
 
         /// <summary>未読用文字色</summary>
         private Color _clUnread;
 
         /// <summary>既読用フォント</summary>
-        private Font _fntReaded;
+        private Font _fntReaded = null!;
 
         /// <summary>既読用文字色</summary>
         private Color _clReaded;
@@ -185,7 +188,7 @@ namespace OpenTween
         private readonly Color _clHighLight = Color.FromKnownColor(KnownColor.HighlightText);
 
         /// <summary>発言詳細部用フォント</summary>
-        private Font _fntDetail;
+        private Font _fntDetail = null!;
 
         /// <summary>発言詳細部用色</summary>
         private Color _clDetail;
@@ -224,36 +227,36 @@ namespace OpenTween
         private Color _clInputFont;
 
         /// <summary>入力欄フォント</summary>
-        private Font _fntInputFont;
+        private Font _fntInputFont = null!;
 
         /// <summary>アイコン画像リスト</summary>
-        private ImageCache IconCache;
+        private ImageCache IconCache = null!;
 
         /// <summary>タスクトレイアイコン:通常時 (At.ico)</summary>
-        private Icon NIconAt;
+        private Icon NIconAt = null!;
 
         /// <summary>タスクトレイアイコン:通信エラー時 (AtRed.ico)</summary>
-        private Icon NIconAtRed;
+        private Icon NIconAtRed = null!;
 
         /// <summary>タスクトレイアイコン:オフライン時 (AtSmoke.ico)</summary>
-        private Icon NIconAtSmoke;
+        private Icon NIconAtSmoke = null!;
 
         /// <summary>タスクトレイアイコン:更新中 (Refresh.ico)</summary>
         private Icon[] NIconRefresh = new Icon[4];
 
         /// <summary>未読のあるタブ用アイコン (Tab.ico)</summary>
-        private Icon TabIcon;
+        private Icon TabIcon = null!;
 
         /// <summary>画面左上のアイコン (Main.ico)</summary>
-        private Icon MainIcon;
+        private Icon MainIcon = null!;
 
-        private Icon ReplyIcon;
-        private Icon ReplyIconBlink;
+        private Icon ReplyIcon = null!;
+        private Icon ReplyIconBlink = null!;
 
-        private readonly ImageList _listViewImageList = new ImageList(); // ListViewItemの高さ変更用
+        private readonly ImageList _listViewImageList = new ImageList();    //ListViewItemの高さ変更用
 
-        private PostClass _anchorPost;
-        private bool _anchorFlag; // true:関連発言移動中(関連移動以外のオペレーションをするとfalseへ。trueだとリスト背景色をアンカー発言選択中として描画)
+        private PostClass? _anchorPost;
+        private bool _anchorFlag;        //true:関連発言移動中(関連移動以外のオペレーションをするとfalseへ。trueだとリスト背景色をアンカー発言選択中として描画)
 
         /// <summary>発言履歴</summary>
         private readonly List<StatusTextHistory> _history = new List<StatusTextHistory>();
@@ -272,13 +275,13 @@ namespace OpenTween
 
         // 以下DrawItem関連
         private readonly SolidBrush _brsHighLight = new SolidBrush(Color.FromKnownColor(KnownColor.Highlight));
-        private SolidBrush _brsBackColorMine;
-        private SolidBrush _brsBackColorAt;
-        private SolidBrush _brsBackColorYou;
-        private SolidBrush _brsBackColorAtYou;
-        private SolidBrush _brsBackColorAtFromTarget;
-        private SolidBrush _brsBackColorAtTo;
-        private SolidBrush _brsBackColorNone;
+        private SolidBrush _brsBackColorMine = null!;
+        private SolidBrush _brsBackColorAt = null!;
+        private SolidBrush _brsBackColorYou = null!;
+        private SolidBrush _brsBackColorAtYou = null!;
+        private SolidBrush _brsBackColorAtFromTarget = null!;
+        private SolidBrush _brsBackColorAtTo = null!;
+        private SolidBrush _brsBackColorNone = null!;
 
         /// <summary>Listにフォーカスないときの選択行の背景色</summary>
         private readonly SolidBrush _brsDeactiveSelection = new SolidBrush(Color.FromKnownColor(KnownColor.ButtonFace));
@@ -286,7 +289,7 @@ namespace OpenTween
         private readonly StringFormat sfTab = new StringFormat();
 
         //////////////////////////////////////////////////////////////////////////////////////////////////////////
-        private TabInformations _statuses;
+        private TabInformations _statuses = null!;
 
         /// <summary>
         /// 現在表示している発言一覧の <see cref="ListView"/> に対するキャッシュ
@@ -296,12 +299,12 @@ namespace OpenTween
         /// 使用する場合には <see cref="_listItemCache"/> に対して直接メソッド等を呼び出さずに
         /// 一旦ローカル変数に代入してから参照すること。
         /// </remarks>
-        private ListViewItemCache _listItemCache = null;
+        private ListViewItemCache? _listItemCache = null;
 
         internal class ListViewItemCache
         {
             /// <summary>アイテムをキャッシュする対象の <see cref="ListView"/></summary>
-            public ListView TargetList { get; set; }
+            public ListView TargetList { get; set; } = null!;
 
             /// <summary>キャッシュする範囲の開始インデックス</summary>
             public int StartIndex { get; set; }
@@ -310,7 +313,7 @@ namespace OpenTween
             public int EndIndex { get; set; }
 
             /// <summary>キャッシュされた範囲に対応する <see cref="ListViewItem"/> と <see cref="PostClass"/> の組</summary>
-            public (ListViewItem, PostClass)[] Cache { get; set; }
+            public (ListViewItem, PostClass)[] Cache { get; set; } = null!;
 
             /// <summary>キャッシュされたアイテムの件数</summary>
             public int Count
@@ -328,7 +331,7 @@ namespace OpenTween
 
             /// <summary>指定されたインデックスの <see cref="ListViewItem"/> と <see cref="PostClass"/> をキャッシュから取得することを試みます</summary>
             /// <returns>取得に成功すれば true、それ以外は false</returns>
-            public bool TryGetValue(int index, out ListViewItem item, out PostClass post)
+            public bool TryGetValue(int index, [NotNullWhen(true)] out ListViewItem? item, [NotNullWhen(true)] out PostClass? post)
             {
                 if (this.Contains(index))
                 {
@@ -349,7 +352,7 @@ namespace OpenTween
         private const int MAX_WORKER_THREADS = 20;
         private readonly SemaphoreSlim workerSemaphore = new SemaphoreSlim(MAX_WORKER_THREADS);
         private readonly CancellationTokenSource workerCts = new CancellationTokenSource();
-        private readonly IProgress<string> workerProgress;
+        private readonly IProgress<string> workerProgress = null!;
 
         private int UnreadCounter = -1;
         private int UnreadAtCounter = -1;
@@ -362,12 +365,12 @@ namespace OpenTween
         //////////////////////////////////////////////////////////////////////////////////////////////////////////
 
         private readonly TimelineScheduler timelineScheduler = new TimelineScheduler();
-        private ThrottlingTimer RefreshThrottlingTimer;
-        private ThrottlingTimer colorizeDebouncer;
-        private ThrottlingTimer selectionDebouncer;
-        private ThrottlingTimer saveConfigDebouncer;
+        private ThrottlingTimer RefreshThrottlingTimer = null!;
+        private ThrottlingTimer colorizeDebouncer = null!;
+        private ThrottlingTimer selectionDebouncer = null!;
+        private ThrottlingTimer saveConfigDebouncer = null!;
 
-        private string recommendedStatusFooter;
+        private string recommendedStatusFooter = null!;
         private bool urlMultibyteSplit = false;
         private bool preventSmsCommand = true;
 
@@ -378,7 +381,7 @@ namespace OpenTween
             public string After;
         }
 
-        private List<urlUndo> urlUndoBuffer = null;
+        private List<urlUndo>? urlUndoBuffer = null;
 
         private readonly struct ReplyChain
         {
@@ -395,10 +398,10 @@ namespace OpenTween
         }
 
         /// <summary>[, ]でのリプライ移動の履歴</summary>
-        private Stack<ReplyChain> replyChains;
+        private Stack<ReplyChain>? replyChains;
 
         /// <summary>ポスト選択履歴</summary>
-        private readonly Stack<(TabModel, PostClass)> selectPostChains = new Stack<(TabModel, PostClass)>();
+        private readonly Stack<(TabModel, PostClass?)> selectPostChains = new Stack<(TabModel, PostClass?)>();
 
         public TabModel CurrentTab
             => this._statuses.SelectedTab;
@@ -412,7 +415,7 @@ namespace OpenTween
         public DetailsListView CurrentListView
             => (DetailsListView)this.CurrentTabPage.Tag;
 
-        public PostClass CurrentPost
+        public PostClass? CurrentPost
             => this.CurrentTab.SelectedPost;
 
         /// <summary>検索処理タイプ</summary>
@@ -431,7 +434,7 @@ namespace OpenTween
             /// <summary>画像投稿サービス名</summary>
             public string imageService = "";
 
-            public IMediaItem[] mediaItems = null;
+            public IMediaItem[]? mediaItems = null;
             public StatusTextHistory()
             {
             }
@@ -592,7 +595,7 @@ namespace OpenTween
             }
         }
 
-        private Icon LoadIcon(string filePath)
+        private Icon? LoadIcon(string filePath)
         {
             if (!File.Exists(filePath))
                 return null;
@@ -611,7 +614,7 @@ namespace OpenTween
         {
             this.InitColumnText();
 
-            ColumnHeader[] columns = null;
+            ColumnHeader[]? columns = null;
             try
             {
                 if (this._iconCol)
@@ -1241,7 +1244,7 @@ namespace OpenTween
             TimerRefreshIcon.Enabled = false;
 
             _ignoreConfigSave = false;
-            this.TweenMain_Resize(null, null);
+            this.TweenMain_Resize(this, EventArgs.Empty);
             if (saveRequired) SaveConfigsAll(false);
 
             foreach (var ua in SettingManager.Common.UserAccounts)
@@ -1344,7 +1347,7 @@ namespace OpenTween
                         tab = new FilterTabModel(tabSetting.TabName);
                         break;
                     case MyCommon.TabUsageType.UserTimeline:
-                        tab = new UserTimelineTabModel(tabSetting.TabName, tabSetting.User);
+                        tab = new UserTimelineTabModel(tabSetting.TabName, tabSetting.User!);
                         break;
                     case MyCommon.TabUsageType.PublicSearch:
                         tab = new PublicSearchTabModel(tabSetting.TabName)
@@ -1354,7 +1357,7 @@ namespace OpenTween
                         };
                         break;
                     case MyCommon.TabUsageType.Lists:
-                        tab = new ListTimelineTabModel(tabSetting.TabName, tabSetting.ListInfo);
+                        tab = new ListTimelineTabModel(tabSetting.TabName, tabSetting.ListInfo!);
                         break;
                     case MyCommon.TabUsageType.Mute:
                         tab = new MuteTabModel(tabSetting.TabName);
@@ -1604,7 +1607,7 @@ namespace OpenTween
 
         internal struct ListViewSelection
         {
-            public long[] SelectedStatusIds { get; set; }
+            public long[]? SelectedStatusIds { get; set; }
             public long? SelectionMarkStatusId { get; set; }
             public long? FocusedStatusId { get; set; }
         }
@@ -1706,7 +1709,7 @@ namespace OpenTween
         private void RestoreListViewSelection(DetailsListView listView, TabModel tab, ListViewSelection listSelection)
         {
             // status_id から ListView 上のインデックスに変換
-            int[] selectedIndices = null;
+            int[]? selectedIndices = null;
             if (listSelection.SelectedStatusIds != null)
                 selectedIndices = tab.IndexOf(listSelection.SelectedStatusIds).Where(x => x != -1).ToArray();
 
@@ -1982,7 +1985,7 @@ namespace OpenTween
 
             this.PushSelectPostChain();
 
-            var post = this.CurrentPost;
+            var post = this.CurrentPost!;
             this._statuses.SetReadAllTab(post.StatusId, read: true);
 
             //キャッシュの書き換え
@@ -2011,7 +2014,7 @@ namespace OpenTween
             ChangeItemStyleRead(Read, itm, post, (DetailsListView)listCache.TargetList);
         }
 
-        private void ChangeItemStyleRead(bool Read, ListViewItem Item, PostClass Post, DetailsListView DList)
+        private void ChangeItemStyleRead(bool Read, ListViewItem Item, PostClass Post, DetailsListView? DList)
         {
             Font fnt;
             string star;
@@ -2063,7 +2066,7 @@ namespace OpenTween
         {
             //Index:更新対象のListviewItem.Index。Colorを返す。
             //-1は全キャッシュ。Colorは返さない(ダミーを戻す)
-            PostClass _post;
+            PostClass? _post;
             if (_anchorFlag)
                 _post = _anchorPost;
             else
@@ -2091,7 +2094,7 @@ namespace OpenTween
         {
             //Index:更新対象のListviewItem.Index。Colorを返す。
             //-1は全キャッシュ。Colorは返さない(ダミーを戻す)
-            PostClass _post;
+            PostClass? _post;
             if (_anchorFlag)
                 _post = _anchorPost;
             else
@@ -2175,7 +2178,7 @@ namespace OpenTween
             }
 
             var currentPost = this.CurrentPost;
-            if (this.ExistCurrentPost && StatusText.Text.Trim() == string.Format("RT @{0}: {1}", currentPost.ScreenName, currentPost.TextFromApi))
+            if (this.ExistCurrentPost && currentPost != null && StatusText.Text.Trim() == string.Format("RT @{0}: {1}", currentPost.ScreenName, currentPost.TextFromApi))
             {
                 var rtResult = MessageBox.Show(string.Format(Properties.Resources.PostButton_Click1, Environment.NewLine),
                                                                "Retweet",
@@ -2259,8 +2262,8 @@ namespace OpenTween
                     return;
             }
 
-            IMediaUploadService uploadService = null;
-            IMediaItem[] uploadItems = null;
+            IMediaUploadService? uploadService = null;
+            IMediaItem[]? uploadItems = null;
             if (ImageSelector.Visible)
             {
                 //画像投稿
@@ -2465,7 +2468,7 @@ namespace OpenTween
                             .ConfigureAwait(false);
                     }
                     catch (TwitterApiException ex)
-                        when (ex.ErrorResponse.Errors.All(x => x.Code == TwitterErrorCode.AlreadyFavorited))
+                        when (ex.Errors.All(x => x.Code == TwitterErrorCode.AlreadyFavorited))
                     {
                         // エラーコード 139 のみの場合は成功と見なす
                     }
@@ -2482,12 +2485,11 @@ namespace OpenTween
                     this._favTimestamps.Add(DateTimeUtc.Now);
 
                     // TLでも取得済みならfav反映
-                    if (this._statuses.ContainsKey(statusId))
+                    if (this._statuses.Posts.TryGetValue(statusId, out var postTl))
                     {
-                        var postTl = this._statuses[statusId];
                         postTl.IsFav = true;
 
-                        var favTab = this._statuses.GetTabByType(MyCommon.TabUsageType.Favorites);
+                        var favTab = this._statuses.FavoriteTab;
                         favTab.AddPostQueue(postTl);
                     }
 
@@ -2600,10 +2602,8 @@ namespace OpenTween
                     successIds.Add(statusId);
                     post.IsFav = false; // リスト再描画必要
 
-                    if (this._statuses.ContainsKey(statusId))
-                    {
-                        this._statuses[statusId].IsFav = false;
-                    }
+                    if (this._statuses.Posts.TryGetValue(statusId, out var tabinfoPost))
+                        tabinfoPost.IsFav = false;
 
                     // 検索,リスト,UserTimeline,Relatedの各タブに反映
                     foreach (var tb in this._statuses.GetTabsInnerStorageType())
@@ -2617,7 +2617,7 @@ namespace OpenTween
             if (ct.IsCancellationRequested)
                 return;
 
-            var favTab = this._statuses.GetTabByType(MyCommon.TabUsageType.Favorites);
+            var favTab = this._statuses.FavoriteTab;
             foreach (var statusId in successIds)
             {
                 // ツイートが削除された訳ではないので IsDeleted はセットしない
@@ -2654,7 +2654,7 @@ namespace OpenTween
             }
         }
 
-        private async Task PostMessageAsync(PostStatusParams postParams, IMediaUploadService uploadService, IMediaItem[] uploadItems)
+        private async Task PostMessageAsync(PostStatusParams postParams, IMediaUploadService? uploadService, IMediaItem[]? uploadItems)
         {
             await this.workerSemaphore.WaitAsync();
             this.RefreshTasktrayIcon();
@@ -2677,7 +2677,7 @@ namespace OpenTween
         }
 
         private async Task PostMessageAsyncInternal(IProgress<string> p, CancellationToken ct, PostStatusParams postParams,
-            IMediaUploadService uploadService, IMediaItem[] uploadItems)
+            IMediaUploadService? uploadService, IMediaItem[]? uploadItems)
         {
             if (ct.IsCancellationRequested)
                 return;
@@ -2687,7 +2687,7 @@ namespace OpenTween
 
             p.Report("Posting...");
 
-            PostClass post = null;
+            PostClass? post = null;
             var errMsg = "";
 
             try
@@ -3032,13 +3032,13 @@ namespace OpenTween
                     await ShowUserTimeline();
                     break;
                 case 4:
-                    ShowRelatedStatusesMenuItem_Click(null, null);
+                    ShowRelatedStatusesMenuItem_Click(this.ShowRelatedStatusesMenuItem, EventArgs.Empty);
                     break;
                 case 5:
-                    MoveToHomeToolStripMenuItem_Click(null, null);
+                    MoveToHomeToolStripMenuItem_Click(this.MoveToHomeToolStripMenuItem, EventArgs.Empty);
                     break;
                 case 6:
-                    StatusOpenMenuItem_Click(null, null);
+                    StatusOpenMenuItem_Click(this.StatusOpenMenuItem, EventArgs.Empty);
                     break;
                 case 7:
                     //動作なし
@@ -3320,7 +3320,7 @@ namespace OpenTween
             }
             var tab = this.CurrentTab;
             var post = this.CurrentPost;
-            if (tab.TabType == MyCommon.TabUsageType.DirectMessage || !this.ExistCurrentPost || post.IsDm)
+            if (tab.TabType == MyCommon.TabUsageType.DirectMessage || !this.ExistCurrentPost || post == null || post.IsDm)
             {
                 FavAddToolStripMenuItem.Enabled = false;
                 FavRemoveToolStripMenuItem.Enabled = false;
@@ -3365,7 +3365,7 @@ namespace OpenTween
             //{
             //    RefreshMoreStripMenuItem.Enabled = false;
             //}
-            if (!this.ExistCurrentPost || post.InReplyToStatusId == null)
+            if (!this.ExistCurrentPost || post == null || post.InReplyToStatusId == null)
             {
                 RepliedStatusOpenMenuItem.Enabled = false;
             }
@@ -3373,7 +3373,7 @@ namespace OpenTween
             {
                 RepliedStatusOpenMenuItem.Enabled = true;
             }
-            if (!this.ExistCurrentPost || string.IsNullOrEmpty(post.RetweetedBy))
+            if (!this.ExistCurrentPost || post == null || string.IsNullOrEmpty(post.RetweetedBy))
             {
                 MoveToRTHomeMenuItem.Enabled = false;
             }
@@ -3382,7 +3382,7 @@ namespace OpenTween
                 MoveToRTHomeMenuItem.Enabled = true;
             }
 
-            if (this.ExistCurrentPost)
+            if (this.ExistCurrentPost && post != null)
             {
                 this.DeleteStripMenuItem.Enabled = post.CanDeleteBy(this.tw.UserId);
                 if (post.RetweetedByUserId == this.tw.UserId)
@@ -3421,7 +3421,7 @@ namespace OpenTween
 
             using (ControlTransaction.Cursor(this, Cursors.WaitCursor))
             {
-                Exception lastException = null;
+                Exception? lastException = null;
                 foreach (var post in posts)
                 {
                     if (!post.CanDeleteBy(this.tw.UserId))
@@ -3843,7 +3843,7 @@ namespace OpenTween
                     if (SettingManager.Common.IsUseNotifyGrowl) gh.RegisterGrowl();
                     try
                     {
-                        StatusText_TextChanged(null, null);
+                        StatusText_TextChanged(this.StatusText, EventArgs.Empty);
                     }
                     catch (Exception)
                     {
@@ -3985,13 +3985,14 @@ namespace OpenTween
             cmb.Text = searchWord;
             SaveConfigsTabs();
             //検索実行
-            this.SearchButton_Click(tabPage.Controls["panelSearch"].Controls["comboSearch"], null);
+            this.SearchButton_Click(tabPage.Controls["panelSearch"].Controls["comboSearch"], EventArgs.Empty);
         }
 
         private async Task ShowUserTimeline()
         {
-            if (!this.ExistCurrentPost) return;
-            await this.AddNewTabForUserTimeline(this.CurrentPost.ScreenName);
+            var post = this.CurrentPost;
+            if (post == null || !this.ExistCurrentPost) return;
+            await this.AddNewTabForUserTimeline(post.ScreenName);
         }
 
         private void SearchComboBox_KeyDown(object sender, KeyEventArgs e)
@@ -4240,7 +4241,8 @@ namespace OpenTween
         public bool RemoveSpecifiedTab(string TabName, bool confirm)
         {
             var tabInfo = _statuses.GetTabByName(TabName);
-            if (tabInfo.IsDefaultTabType || tabInfo.Protected) return false;
+            if (tabInfo == null || tabInfo.IsDefaultTabType || tabInfo.Protected)
+                return false;
 
             if (confirm)
             {
@@ -4552,11 +4554,11 @@ namespace OpenTween
                     {
                         e.Handled = true;
                         StatusText.Text = "";
-                        JumpUnreadMenuItem_Click(null, null);
+                        JumpUnreadMenuItem_Click(this.JumpUnreadMenuItem, EventArgs.Empty);
                     }
                 }
             }
-            this.StatusText_TextChanged(null, null);
+            this.StatusText_TextChanged(this.StatusText, EventArgs.Empty);
         }
 
         private void StatusText_TextChanged(object sender, EventArgs e)
@@ -4641,7 +4643,7 @@ namespace OpenTween
         /// <summary>
         /// attachment_url に指定可能な URL が含まれていれば除去
         /// </summary>
-        private string RemoveAttachmentUrl(string statusText, out string attachmentUrl)
+        private string RemoveAttachmentUrl(string statusText, out string? attachmentUrl)
         {
             attachmentUrl = null;
 
@@ -4668,7 +4670,7 @@ namespace OpenTween
         /// <summary>
         /// <see cref="FormatStatusText"/> に加えて、拡張モードで140字にカウントされない文字列の除去を行います
         /// </summary>
-        private string FormatStatusTextExtended(string statusText, out long[] autoPopulatedUserIds, out string attachmentUrl)
+        private string FormatStatusTextExtended(string statusText, out long[] autoPopulatedUserIds, out string? attachmentUrl)
         {
             statusText = this.RemoveAutoPopuratedMentions(statusText, out autoPopulatedUserIds);
 
@@ -4788,7 +4790,7 @@ namespace OpenTween
             return remainCount;
         }
 
-        private IMediaUploadService GetSelectedImageService()
+        private IMediaUploadService? GetSelectedImageService()
             => this.ImageSelector.Visible ? this.ImageSelector.SelectedService : null;
 
         private void MyList_CacheVirtualItems(object sender, CacheVirtualItemsEventArgs e)
@@ -5346,7 +5348,7 @@ namespace OpenTween
             }
             this.TopMost = SettingManager.Common.AlwaysTop;
 
-            var searchOptions = this.SearchDialog.ResultOptions;
+            var searchOptions = this.SearchDialog.ResultOptions!;
             if (searchOptions.Type == SearchWordDialog.SearchType.Timeline)
             {
                 if (searchOptions.NewTab)
@@ -5450,11 +5452,9 @@ namespace OpenTween
             if (ImageSelector.Enabled)
                 return;
 
-            TabModel foundTab = null;
+            TabModel? foundTab = null;
             var foundIndex = 0;
 
-            DetailsListView lst = null;
-
             //現在タブから最終タブまで探索
             foreach (var (tab, index) in this._statuses.Tabs.WithIndex().Skip(bgnIdx))
             {
@@ -5464,7 +5464,6 @@ namespace OpenTween
                     ListTab.SelectedIndex = index;
                     foundTab = tab;
                     foundIndex = unreadIndex;
-                    lst = (DetailsListView)this.ListTab.TabPages[index].Tag;
                     break;
                 }
             }
@@ -5480,12 +5479,13 @@ namespace OpenTween
                         ListTab.SelectedIndex = index;
                         foundTab = tab;
                         foundIndex = unreadIndex;
-                        lst = (DetailsListView)this.ListTab.TabPages[index].Tag;
                         break;
                     }
                 }
             }
 
+            DetailsListView lst;
+
             if (foundTab == null)
             {
                 //全部調べたが未読見つからず→先頭タブの最新発言へ
@@ -5503,6 +5503,11 @@ namespace OpenTween
 
                 lst = (DetailsListView)tabPage.Tag;
             }
+            else
+            {
+                var foundTabIndex = this._statuses.Tabs.IndexOf(foundTab);
+                lst = (DetailsListView)this.ListTab.TabPages[foundTabIndex].Tag;
+            }
 
             SelectListItem(lst, foundIndex);
 
@@ -5559,9 +5564,12 @@ namespace OpenTween
 
         public class VersionInfo
         {
-            public Version Version { get; set; }
-            public Uri DownloadUri { get; set; }
-            public string ReleaseNote { get; set; }
+            public Version Version { get; }
+            public Uri DownloadUri { get; }
+            public string ReleaseNote { get; }
+
+            public VersionInfo(Version version, Uri downloadUri, string releaseNote)
+                => (this.Version, this.DownloadUri, this.ReleaseNote) = (version, downloadUri, releaseNote);
         }
 
         /// <summary>
@@ -5583,12 +5591,11 @@ namespace OpenTween
 
             msgBody = Regex.Replace(msgBody, "(?<!\r)\n", "\r\n"); // LF -> CRLF
 
-            return new VersionInfo
-            {
-                Version = Version.Parse(msgHeader[0]),
-                DownloadUri = new Uri(msgHeader[1]),
-                ReleaseNote = msgBody,
-            };
+            return new VersionInfo(
+                version: Version.Parse(msgHeader[0]),
+                downloadUri: new Uri(msgHeader[1]),
+                releaseNote: msgBody
+            );
         }
 
         private async Task CheckNewVersion(bool startup = false)
@@ -5691,7 +5698,7 @@ namespace OpenTween
         /// <summary>
         /// サムネイル表示に使用する CancellationToken の生成元
         /// </summary>
-        private CancellationTokenSource thumbnailTokenSource = null;
+        private CancellationTokenSource? thumbnailTokenSource = null;
 
         private void DispSelectedPost(bool forceupdate)
         {
@@ -5717,7 +5724,7 @@ namespace OpenTween
                 var oldTokenSource = Interlocked.Exchange(ref this.thumbnailTokenSource, new CancellationTokenSource());
                 oldTokenSource?.Cancel();
 
-                var token = this.thumbnailTokenSource.Token;
+                var token = this.thumbnailTokenSource!.Token;
                 loadTasks.Add(this.tweetThumbnail1.ShowThumbnailAsync(currentPost, token));
             }
 
@@ -5794,7 +5801,7 @@ namespace OpenTween
                     .Do(() => this.OpenApplicationWebsite()),
 
                 ShortcutCommand.Create(Keys.F3)
-                    .Do(() => this.MenuItemSearchNext_Click(null, null)),
+                    .Do(() => this.MenuItemSearchNext_Click(this.MenuItemSearchNext, EventArgs.Empty)),
 
                 ShortcutCommand.Create(Keys.F5)
                     .Do(() => this.DoRefresh()),
@@ -5807,11 +5814,11 @@ namespace OpenTween
 
                 ShortcutCommand.Create(Keys.Space, Keys.ProcessKey)
                     .NotFocusedOn(FocusedControl.StatusText)
-                    .Do(() => { this._anchorFlag = false; this.JumpUnreadMenuItem_Click(null, null); }),
+                    .Do(() => { this._anchorFlag = false; this.JumpUnreadMenuItem_Click(this.JumpUnreadMenuItem, EventArgs.Empty); }),
 
                 ShortcutCommand.Create(Keys.G)
                     .NotFocusedOn(FocusedControl.StatusText)
-                    .Do(() => { this._anchorFlag = false; this.ShowRelatedStatusesMenuItem_Click(null, null); }),
+                    .Do(() => { this._anchorFlag = false; this.ShowRelatedStatusesMenuItem_Click(this.ShowRelatedStatusesMenuItem, EventArgs.Empty); }),
 
                 ShortcutCommand.Create(Keys.Right, Keys.N)
                     .FocusedOn(FocusedControl.ListTab)
@@ -5910,35 +5917,35 @@ namespace OpenTween
                     .Do(() => this.doQuoteOfficial()),
 
                 ShortcutCommand.Create(Keys.Control | Keys.B)
-                    .Do(() => this.ReadedStripMenuItem_Click(null, null)),
+                    .Do(() => this.ReadedStripMenuItem_Click(this.ReadedStripMenuItem, EventArgs.Empty)),
 
                 ShortcutCommand.Create(Keys.Control | Keys.T)
-                    .Do(() => this.HashManageMenuItem_Click(null, null)),
+                    .Do(() => this.HashManageMenuItem_Click(this.HashManageMenuItem, EventArgs.Empty)),
 
                 ShortcutCommand.Create(Keys.Control | Keys.L)
-                    .Do(() => this.UrlConvertAutoToolStripMenuItem_Click(null, null)),
+                    .Do(() => this.UrlConvertAutoToolStripMenuItem_Click(this.UrlConvertAutoToolStripMenuItem, EventArgs.Empty)),
 
                 ShortcutCommand.Create(Keys.Control | Keys.Y)
                     .NotFocusedOn(FocusedControl.PostBrowser)
-                    .Do(() => this.MultiLineMenuItem_Click(null, null)),
+                    .Do(() => this.MultiLineMenuItem_Click(this.MultiLineMenuItem, EventArgs.Empty)),
 
                 ShortcutCommand.Create(Keys.Control | Keys.F)
-                    .Do(() => this.MenuItemSubSearch_Click(null, null)),
+                    .Do(() => this.MenuItemSubSearch_Click(this.MenuItemSubSearch, EventArgs.Empty)),
 
                 ShortcutCommand.Create(Keys.Control | Keys.U)
                     .Do(() => this.ShowUserTimeline()),
 
                 ShortcutCommand.Create(Keys.Control | Keys.H)
-                    .Do(() => this.MoveToHomeToolStripMenuItem_Click(null, null)),
+                    .Do(() => this.MoveToHomeToolStripMenuItem_Click(this.MoveToHomeToolStripMenuItem, EventArgs.Empty)),
 
                 ShortcutCommand.Create(Keys.Control | Keys.G)
-                    .Do(() => this.MoveToFavToolStripMenuItem_Click(null, null)),
+                    .Do(() => this.MoveToFavToolStripMenuItem_Click(this.MoveToFavToolStripMenuItem, EventArgs.Empty)),
 
                 ShortcutCommand.Create(Keys.Control | Keys.O)
-                    .Do(() => this.StatusOpenMenuItem_Click(null, null)),
+                    .Do(() => this.StatusOpenMenuItem_Click(this.StatusOpenMenuItem, EventArgs.Empty)),
 
                 ShortcutCommand.Create(Keys.Control | Keys.E)
-                    .Do(() => this.OpenURLMenuItem_Click(null, null)),
+                    .Do(() => this.OpenURLMenuItem_Click(this.OpenURLMenuItem, EventArgs.Empty)),
 
                 ShortcutCommand.Create(Keys.Control | Keys.Home, Keys.Control | Keys.End)
                     .FocusedOn(FocusedControl.ListTab)
@@ -6055,7 +6062,7 @@ namespace OpenTween
                     }),
 
                 ShortcutCommand.Create(Keys.Shift | Keys.F3)
-                    .Do(() => this.MenuItemSearchPrev_Click(null, null)),
+                    .Do(() => this.MenuItemSearchPrev_Click(this.MenuItemSearchPrev, EventArgs.Empty)),
 
                 ShortcutCommand.Create(Keys.Shift | Keys.F5)
                     .Do(() => this.DoRefreshMore()),
@@ -6117,7 +6124,7 @@ namespace OpenTween
 
                 ShortcutCommand.Create(Keys.Alt | Keys.P)
                     .OnlyWhen(() => this.CurrentPost != null)
-                    .Do(() => this.doShowUserStatus(this.CurrentPost.ScreenName, ShowInputDialog: false)),
+                    .Do(() => this.doShowUserStatus(this.CurrentPost!.ScreenName, ShowInputDialog: false)),
 
                 ShortcutCommand.Create(Keys.Alt | Keys.Up)
                     .Do(() => this.tweetDetailsView.ScrollDownPostBrowser(forward: false)),
@@ -6154,13 +6161,13 @@ namespace OpenTween
                     .Do(() => this.FavoriteChange(FavAdd: false)),
 
                 ShortcutCommand.Create(Keys.Control | Keys.Shift | Keys.B)
-                    .Do(() => this.UnreadStripMenuItem_Click(null, null)),
+                    .Do(() => this.UnreadStripMenuItem_Click(this.UnreadStripMenuItem, EventArgs.Empty)),
 
                 ShortcutCommand.Create(Keys.Control | Keys.Shift | Keys.T)
-                    .Do(() => this.HashToggleMenuItem_Click(null, null)),
+                    .Do(() => this.HashToggleMenuItem_Click(this.HashToggleMenuItem, EventArgs.Empty)),
 
                 ShortcutCommand.Create(Keys.Control | Keys.Shift | Keys.P)
-                    .Do(() => this.ImageSelectMenuItem_Click(null, null)),
+                    .Do(() => this.ImageSelectMenuItem_Click(this.ImageSelectMenuItem, EventArgs.Empty)),
 
                 ShortcutCommand.Create(Keys.Control | Keys.Shift | Keys.H)
                     .Do(() => this.doMoveToRTHome()),
@@ -6304,7 +6311,7 @@ namespace OpenTween
             };
         }
 
-        internal bool CommonKeyDown(Keys keyData, FocusedControl focusedOn, out Task asyncTask)
+        internal bool CommonKeyDown(Keys keyData, FocusedControl focusedOn, out Task? asyncTask)
         {
             // Task を返す非同期処理があれば asyncTask に代入する
             asyncTask = null;
@@ -6547,7 +6554,7 @@ namespace OpenTween
             }
 
             string name;
-            if (currentPost.RetweetedId == null)
+            if (currentPost.RetweetedBy == null)
             {
                 name = currentPost.ScreenName;
             }
@@ -6962,7 +6969,7 @@ namespace OpenTween
             if (this.selectPostChains.Count > 1)
             {
                 var idx = -1;
-                TabModel foundTab = null;
+                TabModel? foundTab = null;
 
                 do
                 {
@@ -7037,7 +7044,7 @@ namespace OpenTween
         private void TrimPostChain()
         {
             if (this.selectPostChains.Count <= 2000) return;
-            var p = new Stack<(TabModel, PostClass)>(2000);
+            var p = new Stack<(TabModel, PostClass?)>(2000);
             for (var i = 0; i < 2000; i++)
             {
                 p.Push(this.selectPostChains.Pop());
@@ -7077,7 +7084,7 @@ namespace OpenTween
         {
             if (statusId == 0) return false;
 
-            var tab = this._statuses.GetTabByType<DirectMessagesTabModel>();
+            var tab = this._statuses.DirectMessageTab;
             var index = tab.IndexOf(statusId);
 
             if (index == -1)
@@ -7124,7 +7131,7 @@ namespace OpenTween
                 e.SuppressKeyPress = true;
             }
 
-            this.StatusText_TextChanged(null, null);
+            this.StatusText_TextChanged(this.StatusText, EventArgs.Empty);
 
             if (asyncTask != null)
                 await asyncTask;
@@ -7379,7 +7386,7 @@ namespace OpenTween
             this.TopMost = SettingManager.Common.AlwaysTop;
         }
 
-        public bool TabRename(string origTabName, out string newTabName)
+        public bool TabRename(string origTabName, [NotNullWhen(true)] out string? newTabName)
         {
             //タブ名変更
             newTabName = null;
@@ -7926,7 +7933,7 @@ namespace OpenTween
 
         private void TabMenuControl(string tabName)
         {
-            var tabInfo = _statuses.GetTabByName(tabName);
+            var tabInfo = _statuses.GetTabByName(tabName)!;
 
             this.FilterEditMenuItem.Enabled = true;
             this.EditRuleTbMenuItem.Enabled = true;
@@ -8048,7 +8055,7 @@ namespace OpenTween
 
         private void FilterEditMenuItem_Click(object sender, EventArgs e)
         {
-            if (string.IsNullOrEmpty(_rclickTabName)) _rclickTabName = _statuses.GetTabByType(MyCommon.TabUsageType.Home).TabName;
+            if (string.IsNullOrEmpty(_rclickTabName)) _rclickTabName = _statuses.HomeTab.TabName;
 
             using (var fltDialog = new FilterDialog())
             {
@@ -8064,7 +8071,7 @@ namespace OpenTween
 
         private async void AddTabMenuItem_Click(object sender, EventArgs e)
         {
-            string tabName = null;
+            string? tabName = null;
             MyCommon.TabUsageType tabUsage;
             using (var inputName = new InputTabName())
             {
@@ -8079,7 +8086,7 @@ namespace OpenTween
             if (!string.IsNullOrEmpty(tabName))
             {
                 //List対応
-                ListElement list = null;
+                ListElement? list = null;
                 if (tabUsage == MyCommon.TabUsageType.Lists)
                 {
                     using var listAvail = new ListAvailable();
@@ -8100,7 +8107,7 @@ namespace OpenTween
                         tab = new PublicSearchTabModel(tabName);
                         break;
                     case MyCommon.TabUsageType.Lists:
-                        tab = new ListTimelineTabModel(tabName, list);
+                        tab = new ListTimelineTabModel(tabName, list!);
                         break;
                     default:
                         return;
@@ -8146,7 +8153,7 @@ namespace OpenTween
 
                     fltDialog.SetCurrent(tabName);
 
-                    if (post.RetweetedId == null)
+                    if (post.RetweetedBy == null)
                     {
                         fltDialog.AddNewFilter(post.ScreenName, post.TextFromApi);
                     }
@@ -8231,7 +8238,7 @@ namespace OpenTween
                     }
                     else if (_Post)
                     {
-                        PostButton_Click(null, null);
+                        PostButton_Click(this.PostButton, EventArgs.Empty);
                         return true;
                     }
                 }
@@ -8244,7 +8251,7 @@ namespace OpenTween
                         if (tabPage.Controls["panelSearch"].Controls["comboSearch"].Focused ||
                             tabPage.Controls["panelSearch"].Controls["comboLang"].Focused)
                         {
-                            this.SearchButton_Click(tabPage.Controls["panelSearch"].Controls["comboSearch"], null);
+                            this.SearchButton_Click(tabPage.Controls["panelSearch"].Controls["comboSearch"], EventArgs.Empty);
                             return true;
                         }
                     }
@@ -8267,7 +8274,7 @@ namespace OpenTween
                 return;
 
             var screenNameArray = selectedPosts
-                .Select(x => x.RetweetedId != null ? x.RetweetedBy : x.ScreenName)
+                .Select(x => x.RetweetedBy ?? x.ScreenName)
                 .ToArray();
 
             this.AddFilterRuleByScreenName(screenNameArray);
@@ -8375,7 +8382,7 @@ namespace OpenTween
             this.SaveConfigsTabs();
         }
 
-        private bool SelectTab(out string tabName)
+        private bool SelectTab([NotNullWhen(true)] out string? tabName)
         {
             do
             {
@@ -8627,13 +8634,13 @@ namespace OpenTween
                         ttl.Append(_history[_history.Count - 2].status.Replace("\r\n", " "));
                     break;
                 case MyCommon.DispTitleEnum.UnreadRepCount:
-                    ttl.AppendFormat(Properties.Resources.SetMainWindowTitleText1, _statuses.GetTabByType(MyCommon.TabUsageType.Mentions).UnreadCount + _statuses.GetTabByType(MyCommon.TabUsageType.DirectMessage).UnreadCount);
+                    ttl.AppendFormat(Properties.Resources.SetMainWindowTitleText1, _statuses.MentionTab.UnreadCount + _statuses.DirectMessageTab.UnreadCount);
                     break;
                 case MyCommon.DispTitleEnum.UnreadAllCount:
                     ttl.AppendFormat(Properties.Resources.SetMainWindowTitleText2, ur);
                     break;
                 case MyCommon.DispTitleEnum.UnreadAllRepCount:
-                    ttl.AppendFormat(Properties.Resources.SetMainWindowTitleText3, ur, _statuses.GetTabByType(MyCommon.TabUsageType.Mentions).UnreadCount + _statuses.GetTabByType(MyCommon.TabUsageType.DirectMessage).UnreadCount);
+                    ttl.AppendFormat(Properties.Resources.SetMainWindowTitleText3, ur, _statuses.MentionTab.UnreadCount + _statuses.DirectMessageTab.UnreadCount);
                     break;
                 case MyCommon.DispTitleEnum.UnreadCountAllCount:
                     ttl.AppendFormat(Properties.Resources.SetMainWindowTitleText4, ur, al);
@@ -8659,8 +8666,8 @@ namespace OpenTween
             //ステータス欄にカウント表示
             //タブ未読数/タブ発言数 全未読数/総発言数 (未読@+未読DM数)
             if (_statuses == null) return "";
-            var tbRep = _statuses.GetTabByType(MyCommon.TabUsageType.Mentions);
-            var tbDm = _statuses.GetTabByType(MyCommon.TabUsageType.DirectMessage);
+            var tbRep = _statuses.MentionTab;
+            var tbDm = _statuses.DirectMessageTab;
             if (tbRep == null || tbDm == null) return "";
             var urat = tbRep.UnreadCount + tbDm.UnreadCount;
             var ur = 0;
@@ -8689,7 +8696,7 @@ namespace OpenTween
             UnreadCounter = ur;
             UnreadAtCounter = urat;
 
-            var homeTab = this._statuses.GetTabByType<HomeTabModel>();
+            var homeTab = this._statuses.HomeTab;
 
             slbl.AppendFormat(Properties.Resources.SetStatusLabelText1, tur, tal, ur, al, urat, _postTimestamps.Count, _favTimestamps.Count, homeTab.TweetsPerHour);
             if (SettingManager.Common.TimelinePeriod == 0)
@@ -8713,7 +8720,7 @@ namespace OpenTween
                 }
                 else
                 {
-                    var endpointName = (e as TwitterApiStatus.AccessLimitUpdatedEventArgs).EndpointName;
+                    var endpointName = ((TwitterApiStatus.AccessLimitUpdatedEventArgs)e).EndpointName;
                     SetApiStatusLabel(endpointName);
                 }
             }
@@ -8727,7 +8734,7 @@ namespace OpenTween
             }
         }
 
-        private void SetApiStatusLabel(string endpointName = null)
+        private void SetApiStatusLabel(string? endpointName = null)
         {
             var tabType = this.CurrentTab.TabType;
 
@@ -9023,16 +9030,15 @@ namespace OpenTween
         private async Task doRepliedStatusOpen()
         {
             var currentPost = this.CurrentPost;
-            if (this.ExistCurrentPost && currentPost.InReplyToUser != null && currentPost.InReplyToStatusId != null)
+            if (this.ExistCurrentPost && currentPost != null && currentPost.InReplyToUser != null && currentPost.InReplyToStatusId != null)
             {
                 if (MyCommon.IsKeyDown(Keys.Shift))
                 {
                     await this.OpenUriInBrowserAsync(MyCommon.GetStatusUrl(currentPost.InReplyToUser, currentPost.InReplyToStatusId.Value));
                     return;
                 }
-                if (_statuses.ContainsKey(currentPost.InReplyToStatusId.Value))
+                if (this._statuses.Posts.TryGetValue(currentPost.InReplyToStatusId.Value, out var repPost))
                 {
-                    var repPost = _statuses[currentPost.InReplyToStatusId.Value];
                     MessageBox.Show($"{repPost.ScreenName} / {repPost.Nickname}   ({repPost.CreatedAt.ToLocalTimeString()})" + Environment.NewLine + repPost.TextFromApi);
                 }
                 else
@@ -9040,7 +9046,7 @@ namespace OpenTween
                     foreach (var tb in _statuses.GetTabsByType(MyCommon.TabUsageType.Lists | MyCommon.TabUsageType.PublicSearch))
                     {
                         if (tb == null || !tb.Contains(currentPost.InReplyToStatusId.Value)) break;
-                        var repPost = _statuses[currentPost.InReplyToStatusId.Value];
+                        repPost = tb.Posts[currentPost.InReplyToStatusId.Value];
                         MessageBox.Show($"{repPost.ScreenName} / {repPost.Nickname}   ({repPost.CreatedAt.ToLocalTimeString()})" + Environment.NewLine + repPost.TextFromApi);
                         return;
                     }
@@ -9546,7 +9552,7 @@ namespace OpenTween
         /// </remarks>
         /// <exception cref="ArgumentException">不正なフォーマットが入力された場合</exception>
         /// <exception cref="NotSupportedException">サポートされていないデータが入力された場合</exception>
-        internal static (string Url, string Title) GetUrlFromDataObject(IDataObject data)
+        internal static (string Url, string? Title) GetUrlFromDataObject(IDataObject data)
         {
             if (data.GetDataPresent("text/x-moz-url"))
             {
@@ -9779,7 +9785,7 @@ namespace OpenTween
             if (flg) LView.Invalidate(bnd);
         }
 
-        private void SelectListItem(DetailsListView LView , int[] Index, int focusedIndex, int selectionMarkIndex)
+        private void SelectListItem(DetailsListView LView , int[]? Index, int focusedIndex, int selectionMarkIndex)
         {
             //複数
             var bnd = new Rectangle();
@@ -9894,7 +9900,7 @@ namespace OpenTween
                 if (MyCommon.TwitterApiInfo.AccessLevel == TwitterApiAccessLevel.ReadWrite)
                 {
                     MessageBox.Show(Properties.Resources.ReAuthorizeText);
-                    SettingStripMenuItem_Click(null, null);
+                    SettingStripMenuItem_Click(this.SettingStripMenuItem, EventArgs.Empty);
                 }
 
                 // 取得失敗の場合は再試行する
@@ -10007,7 +10013,7 @@ namespace OpenTween
         private async Task FavoritesRetweetUnofficial()
         {
             var post = this.CurrentPost;
-            if (this.ExistCurrentPost && !post.IsDm)
+            if (this.ExistCurrentPost && post != null && !post.IsDm)
             {
                 _DoFavRetweetFlags = true;
                 var favoriteTask = this.FavoriteChange(true);
@@ -10136,7 +10142,7 @@ namespace OpenTween
 
         private async void ApiUsageInfoMenuItem_Click(object sender, EventArgs e)
         {
-            TwitterApiStatus apiStatus;
+            TwitterApiStatus? apiStatus;
 
             using (var dialog = new WaitingDialog(Properties.Resources.ApiInfo6))
             {
@@ -10402,9 +10408,9 @@ namespace OpenTween
 
         private void doQuoteOfficial()
         {
-            if (this.ExistCurrentPost)
+            var post = this.CurrentPost;
+            if (this.ExistCurrentPost && post != null)
             {
-                var post = this.CurrentPost;
                 if (post.IsDm || !StatusText.Enabled)
                     return;
 
@@ -10428,9 +10434,9 @@ namespace OpenTween
         private void doReTweetUnofficial()
         {
             //RT @id:内容
-            if (this.ExistCurrentPost)
+            var post = this.CurrentPost;
+            if (this.ExistCurrentPost && post != null)
             {
-                var post = this.CurrentPost;
                 if (post.IsDm || !StatusText.Enabled)
                     return;
 
@@ -10547,8 +10553,9 @@ namespace OpenTween
             }
             else
             {
+                DetailsListView? listView;
+
                 var tb = _statuses.RemovedTab.Pop();
-                DetailsListView listView;
                 if (tb.TabType == MyCommon.TabUsageType.Related)
                 {
                     var relatedTab = _statuses.GetTabByType(MyCommon.TabUsageType.Related);
@@ -10710,7 +10717,7 @@ namespace OpenTween
             //    StatusText.Focus();
             //}
             this.MarkSettingCommonModified();
-            this.StatusText_TextChanged(null, null);
+            this.StatusText_TextChanged(this.StatusText, EventArgs.Empty);
         }
 
         private void HashToggleMenuItem_Click(object sender, EventArgs e)
@@ -10729,11 +10736,11 @@ namespace OpenTween
                 HashTogglePullDownMenuItem.Checked = false;
             }
             this.MarkSettingCommonModified();
-            this.StatusText_TextChanged(null, null);
+            this.StatusText_TextChanged(this.StatusText, EventArgs.Empty);
         }
 
         private void HashStripSplitButton_ButtonClick(object sender, EventArgs e)
-            => this.HashToggleMenuItem_Click(null, null);
+            => this.HashToggleMenuItem_Click(this.HashToggleMenuItem, EventArgs.Empty);
 
         public void SetPermanentHashtag(string hashtag)
         {
@@ -10780,7 +10787,7 @@ namespace OpenTween
 
             var tab = this.CurrentTab;
             var post = this.CurrentPost;
-            if (tab.TabType == MyCommon.TabUsageType.DirectMessage || !this.ExistCurrentPost || post.IsDm)
+            if (tab.TabType == MyCommon.TabUsageType.DirectMessage || !this.ExistCurrentPost || post == null || post.IsDm)
             {
                 this.FavOpMenuItem.Enabled = false;
                 this.UnFavOpMenuItem.Enabled = false;
@@ -10825,7 +10832,7 @@ namespace OpenTween
             {
                 this.RefreshPrevOpMenuItem.Enabled = false;
             }
-            if (!this.ExistCurrentPost || post.InReplyToStatusId == null)
+            if (!this.ExistCurrentPost || post == null || post.InReplyToStatusId == null)
             {
                 OpenRepSourceOpMenuItem.Enabled = false;
             }
@@ -10833,7 +10840,7 @@ namespace OpenTween
             {
                 OpenRepSourceOpMenuItem.Enabled = true;
             }
-            if (!this.ExistCurrentPost || string.IsNullOrEmpty(post.RetweetedBy))
+            if (!this.ExistCurrentPost || post == null || string.IsNullOrEmpty(post.RetweetedBy))
             {
                 OpenRterHomeMenuItem.Enabled = false;
             }
@@ -10842,14 +10849,14 @@ namespace OpenTween
                 OpenRterHomeMenuItem.Enabled = true;
             }
 
-            if (this.ExistCurrentPost)
+            if (this.ExistCurrentPost && post != null)
             {
                 this.DelOpMenuItem.Enabled = post.CanDeleteBy(this.tw.UserId);
             }
         }
 
         private void MenuItemTab_DropDownOpening(object sender, EventArgs e)
-            => this.ContextMenuTabProperty_Opening(sender, null);
+            => this.ContextMenuTabProperty_Opening(sender, null!);
 
         public Twitter TwitterInstance
             => this.tw;
@@ -10895,7 +10902,8 @@ namespace OpenTween
             else
                 PublicSearchQueryMenuItem.Enabled = false;
 
-            if (!this.ExistCurrentPost)
+            var post = this.CurrentPost;
+            if (!this.ExistCurrentPost || post == null)
             {
                 this.CopySTOTMenuItem.Enabled = false;
                 this.CopyURLMenuItem.Enabled = false;
@@ -10907,7 +10915,6 @@ namespace OpenTween
                 this.CopyURLMenuItem.Enabled = true;
                 this.CopyUserIdStripMenuItem.Enabled = true;
 
-                var post = this.CurrentPost;
                 if (post.IsDm) this.CopyURLMenuItem.Enabled = false;
                 if (post.IsProtect) this.CopySTOTMenuItem.Enabled = false;
             }
@@ -10921,7 +10928,7 @@ namespace OpenTween
 
         private async Task doShowUserStatus(string id, bool ShowInputDialog)
         {
-            TwitterUser user = null;
+            TwitterUser? user = null;
 
             if (ShowInputDialog)
             {
@@ -10991,10 +10998,10 @@ namespace OpenTween
 
         private async void RtCountMenuItem_Click(object sender, EventArgs e)
         {
-            if (!this.ExistCurrentPost)
+            var post = this.CurrentPost;
+            if (!this.ExistCurrentPost || post == null)
                 return;
 
-            var post = this.CurrentPost;
             var statusId = post.RetweetedId ?? post.StatusId;
             TwitterStatus status;
 
@@ -11126,12 +11133,12 @@ namespace OpenTween
             if (ImageSelector.Visible)
             {
                 this.MarkSettingCommonModified();
-                this.StatusText_TextChanged(null, null);
+                this.StatusText_TextChanged(this.StatusText, EventArgs.Empty);
             }
         }
 
         private void ImageSelector_VisibleChanged(object sender, EventArgs e)
-            => this.StatusText_TextChanged(null, null);
+            => this.StatusText_TextChanged(this.StatusText, EventArgs.Empty);
 
         /// <summary>
         /// StatusTextでCtrl+Vが押下された時の処理
@@ -11181,7 +11188,7 @@ namespace OpenTween
         private void MenuItemCommand_DropDownOpening(object sender, EventArgs e)
         {
             var post = this.CurrentPost;
-            if (this.ExistCurrentPost && !post.IsDm)
+            if (this.ExistCurrentPost && post != null && !post.IsDm)
                 RtCountMenuItem.Enabled = true;
             else
                 RtCountMenuItem.Enabled = false;
@@ -11213,7 +11220,7 @@ namespace OpenTween
         private async void ShowRelatedStatusesMenuItem_Click(object sender, EventArgs e)
         {
             var post = this.CurrentPost;
-            if (this.ExistCurrentPost && !post.IsDm)
+            if (this.ExistCurrentPost && post != null && !post.IsDm)
             {
                 try
                 {
@@ -11449,7 +11456,7 @@ namespace OpenTween
                 }
                 if (ev.Event == "unfavorite" && ev.Username.Equals(tw.Username, StringComparison.InvariantCultureIgnoreCase))
                 {
-                    var favTab = this._statuses.GetTabByType(MyCommon.TabUsageType.Favorites);
+                    var favTab = this._statuses.FavoriteTab;
                     favTab.EnqueueRemovePost(ev.Id, setIsDeleted: false);
                 }
             }
@@ -11800,7 +11807,7 @@ namespace OpenTween
         {
             if (e.KeyCode == Keys.Space)
             {
-                this.JumpUnreadMenuItem_Click(null, null);
+                this.JumpUnreadMenuItem_Click(this.JumpUnreadMenuItem, EventArgs.Empty);
 
                 e.SuppressKeyPress = true;
             }
index 119bebf..eb27e7b 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
index 7e2c241..8a384a9 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
@@ -45,16 +47,16 @@ namespace OpenTween
 {
     public partial class TweetDetailsView : UserControl
     {
-        public TweenMain Owner { get; set; }
+        public TweenMain Owner { get; set; } = null!;
 
         /// <summary>プロフィール画像のキャッシュ</summary>
-        public ImageCache IconCache { get; set; }
+        public ImageCache IconCache { get; set; } = null!;
 
         /// <summary><see cref="PostClass"/> のダンプを表示するか</summary>
         public bool DumpPostClass { get; set; }
 
         /// <summary>現在表示中の発言</summary>
-        public PostClass CurrentPost { get; private set; }
+        public PostClass? CurrentPost { get; private set; }
 
         [DefaultValue(false)]
         public new bool TabStop
@@ -404,7 +406,7 @@ namespace OpenTween
             }
         }
 
-        private string GetUserId()
+        private string? GetUserId()
         {
             var m = Regex.Match(this._postBrowserStatusText, @"^https?://twitter.com/(#!/)?(?<ScreenName>[a-zA-Z0-9_]+)(/status(es)?/[0-9]+)?$");
             if (m.Success && this.Owner.IsTwitterId(m.Result("${ScreenName}")))
@@ -443,7 +445,7 @@ namespace OpenTween
         {
             if (e.Url.AbsoluteUri != "about:blank")
             {
-                await this.ShowPostDetails(this.CurrentPost); // 現在の発言を表示し直す (Navigated の段階ではキャンセルできない)
+                await this.ShowPostDetails(this.CurrentPost!); // 現在の発言を表示し直す (Navigated の段階ではキャンセルできない)
                 await this.Owner.OpenUriInBrowserAsync(e.Url.OriginalString);
             }
         }
@@ -712,13 +714,17 @@ namespace OpenTween
             if (string.IsNullOrEmpty(imageUrl))
                 return;
 
+            var memoryImage = this.IconCache.TryGetFromCache(imageUrl);
+            if (memoryImage == null)
+                return;
+
             this.Owner.SaveFileDialog1.FileName = imageUrl.Substring(imageUrl.LastIndexOf('/') + 1);
 
             if (this.Owner.SaveFileDialog1.ShowDialog() == DialogResult.OK)
             {
                 try
                 {
-                    using var orgBmp = new Bitmap(IconCache.TryGetFromCache(imageUrl).Image);
+                    using var orgBmp = new Bitmap(memoryImage.Image);
                     using var bmp2 = new Bitmap(orgBmp.Size.Width, orgBmp.Size.Height);
 
                     using (var g = Graphics.FromImage(bmp2))
@@ -966,7 +972,7 @@ namespace OpenTween
         {
             var menuItem = (ToolStripMenuItem)sender;
 
-            string user;
+            string? user;
             if (menuItem.Owner == this.ContextMenuPostBrowser)
             {
                 user = GetUserId();
index c8c3f6a..737f26a 100644 (file)
@@ -20,6 +20,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -60,7 +62,7 @@ namespace OpenTween
                     if (Regex.IsMatch(before, Twitter.url_invalid_without_protocol_preceding_chars))
                         continue;
 
-                    string lasturl = null;
+                    string? lasturl = null;
 
                     var last_url_invalid_match = false;
                     var domainMatches = Regex.Matches(domain, Twitter.url_valid_ascii_domain, RegexOptions.IgnoreCase).Cast<Match>();
index aaf700d..91865cb 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Globalization;
@@ -35,7 +37,7 @@ namespace OpenTween
     /// </summary>
     public static class TweetFormatter
     {
-        public static string AutoLinkHtml(string text, IEnumerable<TwitterEntity> entities, bool keepTco = false)
+        public static string AutoLinkHtml(string text, IEnumerable<TwitterEntity>? entities, bool keepTco = false)
         {
             if (entities == null)
                 entities = Enumerable.Empty<TwitterEntity>();
index e4624c8..4f02655 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
@@ -49,7 +51,7 @@ namespace OpenTween
         public event EventHandler<ThumbnailImageSearchEventArgs> ThumbnailImageSearchClick;
 
         public ThumbnailInfo Thumbnail
-            => this.pictureBox[this.scrollBar.Value].Tag as ThumbnailInfo;
+            => (ThumbnailInfo)this.pictureBox[this.scrollBar.Value].Tag;
 
         public TweetThumbnail()
             => this.InitializeComponent();
index 326b8f3..22a8a57 100644 (file)
@@ -25,6 +25,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System.Diagnostics;
 using System.IO;
 using System.Linq;
@@ -164,7 +166,7 @@ namespace OpenTween
         //プロパティからアクセスされる共通情報
         private readonly List<string> _hashList = new List<string>();
 
-        private string nextCursorDirectMessage = null;
+        private string? nextCursorDirectMessage = null;
 
         private long previousStatusId = -1L;
 
@@ -267,7 +269,7 @@ namespace OpenTween
             return orgData;
         }
 
-        public async Task<PostClass> PostStatus(PostStatusParams param)
+        public async Task<PostClass?> PostStatus(PostStatusParams param)
         {
             this.CheckAccountState();
 
@@ -300,7 +302,7 @@ namespace OpenTween
             return post;
         }
 
-        public async Task<long> UploadMedia(IMediaItem item, string mediaCategory = null)
+        public async Task<long> UploadMedia(IMediaItem item, string? mediaCategory = null)
         {
             this.CheckAccountState();
 
@@ -390,7 +392,7 @@ namespace OpenTween
                 .ConfigureAwait(false);
         }
 
-        public async Task<PostClass> PostRetweet(long id, bool read)
+        public async Task<PostClass?> PostRetweet(long id, bool read)
         {
             this.CheckAccountState();
 
@@ -454,8 +456,8 @@ namespace OpenTween
             this.FollowersCount = self.FollowersCount;
             this.FriendsCount = self.FriendsCount;
             this.StatusesCount = self.StatusesCount;
-            this.Location = self.Location;
-            this.Bio = self.Description;
+            this.Location = self.Location ?? "";
+            this.Bio = self.Description ?? "";
         }
 
         /// <summary>
@@ -687,7 +689,7 @@ namespace OpenTween
                 else
                 {
                     //幻覚fav対策
-                    var tc = TabInformations.GetInstance().GetTabByType(MyCommon.TabUsageType.Favorites);
+                    var tc = TabInformations.GetInstance().FavoriteTab;
                     post.IsFav = tc.Contains(retweeted.Id);
                 }
 
@@ -742,8 +744,8 @@ namespace OpenTween
                 else
                 {
                     //幻覚fav対策
-                    var tc = TabInformations.GetInstance().GetTabByType(MyCommon.TabUsageType.Favorites);
-                    post.IsFav = tc.Contains(post.StatusId) && TabInformations.GetInstance()[post.StatusId].IsFav;
+                    var tc = TabInformations.GetInstance().FavoriteTab;
+                    post.IsFav = tc.Posts.TryGetValue(post.StatusId, out var tabinfoPost) && tabinfoPost.IsFav;
                 }
 
                 if (status.Coordinates != null)
@@ -830,8 +832,10 @@ namespace OpenTween
         /// <summary>
         /// ツイートに含まれる引用ツイートのURLからステータスIDを抽出
         /// </summary>
-        public static IEnumerable<long> GetQuoteTweetStatusIds(IEnumerable<TwitterEntity> entities, TwitterQuotedStatusPermalink quotedStatusLink)
+        public static IEnumerable<long> GetQuoteTweetStatusIds(IEnumerable<TwitterEntity>? entities, TwitterQuotedStatusPermalink? quotedStatusLink)
         {
+            entities ??= Enumerable.Empty<TwitterEntity>();
+
             var urls = entities.OfType<TwitterEntityUrl>().Select(x => x.ExpandedUrl);
 
             if (quotedStatusLink != null)
@@ -853,7 +857,7 @@ namespace OpenTween
             }
         }
 
-        private long? CreatePostsFromJson(TwitterStatus[] items, MyCommon.WORKERTYPE gType, TabModel tab, bool read)
+        private long? CreatePostsFromJson(TwitterStatus[] items, MyCommon.WORKERTYPE gType, TabModel? tab, bool read)
         {
             long? minimumId = null;
 
@@ -922,7 +926,7 @@ namespace OpenTween
 
         private long? CreateFavoritePostsFromJson(TwitterStatus[] items, bool read)
         {
-            var favTab = TabInformations.GetInstance().GetTabByType(MyCommon.TabUsageType.Favorites);
+            var favTab = TabInformations.GetInstance().FavoriteTab;
             long? minimumId = null;
 
             foreach (var status in items)
@@ -1009,7 +1013,7 @@ namespace OpenTween
             }
             relPosts.Add(targetPost.StatusId, targetPost);
 
-            Exception lastException = null;
+            Exception? lastException = null;
 
             // in_reply_to_status_id を使用してリプライチェインを辿る
             var nextPost = FindTopOfReplyChain(relPosts, targetPost.StatusId);
@@ -1122,7 +1126,7 @@ namespace OpenTween
                     //二重取得回避
                     lock (LockObj)
                     {
-                        if (TabInformations.GetInstance().GetTabByType(MyCommon.TabUsageType.DirectMessage).Contains(post.StatusId)) continue;
+                        if (TabInformations.GetInstance().DirectMessageTab.Contains(post.StatusId)) continue;
                     }
                     //sender_id
                     //recipient_id
@@ -1149,10 +1153,10 @@ namespace OpenTween
                         .ToArray();
 
                     //以下、ユーザー情報
-                    TwitterUser user;
+                    TwitterUser? user;
                     if (gType == MyCommon.WORKERTYPE.UserStream)
                     {
-                        if (this.Api.CurrentUserId == message.Recipient.Id)
+                        if (this.Api.CurrentUserId == message.Recipient?.Id)
                         {
                             user = message.Sender;
                             post.IsMe = false;
@@ -1181,11 +1185,21 @@ namespace OpenTween
                         }
                     }
 
-                    post.UserId = user.Id;
-                    post.ScreenName = user.ScreenName;
-                    post.Nickname = user.Name.Trim();
-                    post.ImageUrl = user.ProfileImageUrlHttps;
-                    post.IsProtect = user.Protected;
+                    if (user != null)
+                    {
+                        post.UserId = user.Id;
+                        post.ScreenName = user.ScreenName;
+                        post.Nickname = user.Name.Trim();
+                        post.ImageUrl = user.ProfileImageUrlHttps;
+                        post.IsProtect = user.Protected;
+                        post.IsMe = post.UserId == this.UserId;
+                    }
+                    else
+                    {
+                        post.UserId = 0L;
+                        post.ScreenName = "?????";
+                        post.Nickname = "Unknown User";
+                    }
 
                     // メモリ使用量削減 (同一のテキストであれば同一の string インスタンスを参照させる)
                     if (post.Text == post.TextFromApi)
@@ -1211,7 +1225,7 @@ namespace OpenTween
                 post.IsExcludeReply = false;
                 post.IsDm = true;
 
-                var dmTab = TabInformations.GetInstance().GetTabByType(MyCommon.TabUsageType.DirectMessage);
+                var dmTab = TabInformations.GetInstance().DirectMessageTab;
                 dmTab.AddPostQueue(post);
             }
         }
@@ -1367,7 +1381,7 @@ namespace OpenTween
                 post.IsExcludeReply = false;
                 post.IsDm = true;
 
-                var dmTab = TabInformations.GetInstance().GetTabByType<DirectMessagesTabModel>();
+                var dmTab = TabInformations.GetInstance().DirectMessageTab;
                 dmTab.AddPostQueue(post);
             }
         }
@@ -1396,7 +1410,7 @@ namespace OpenTween
                 tab.OldestId = minimumId.Value;
         }
 
-        private string ReplaceTextFromApi(string text, TwitterEntities entities, TwitterQuotedStatusPermalink quotedStatusLink)
+        private string ReplaceTextFromApi(string text, TwitterEntities? entities, TwitterQuotedStatusPermalink? quotedStatusLink)
         {
             if (entities != null)
             {
@@ -1422,7 +1436,7 @@ namespace OpenTween
             return text;
         }
 
-        internal static string CreateAccessibleText(string text, TwitterEntities entities, TwitterStatus quotedStatus, TwitterQuotedStatusPermalink quotedStatusLink)
+        internal static string CreateAccessibleText(string text, TwitterEntities? entities, TwitterStatus? quotedStatus, TwitterQuotedStatusPermalink? quotedStatusLink)
         {
             if (entities == null)
                 return text;
@@ -1462,7 +1476,7 @@ namespace OpenTween
                 }
             }
 
-            if (quotedStatusLink != null)
+            if (quotedStatus != null && quotedStatusLink != null)
             {
                 var quoteText = CreateAccessibleText(quotedStatus.FullText, quotedStatus.MergedEntities, quotedStatus: null, quotedStatusLink: null);
                 text += " " + string.Format(Properties.Resources.QuoteStatus_AccessibleText, quotedStatus.User.ScreenName, quoteText);
@@ -1604,13 +1618,13 @@ namespace OpenTween
                 return true;
             }
             catch (TwitterApiException ex)
-                when (ex.ErrorResponse.Errors.Any(x => x.Code == TwitterErrorCode.NotFound))
+                when (ex.Errors.Any(x => x.Code == TwitterErrorCode.NotFound))
             {
                 return false;
             }
         }
 
-        private void ExtractEntities(TwitterEntities entities, List<(long UserId, string ScreenName)> AtList, List<MediaInfo> media)
+        private void ExtractEntities(TwitterEntities? entities, List<(long UserId, string ScreenName)> AtList, List<MediaInfo> media)
         {
             if (entities != null)
             {
@@ -1654,7 +1668,7 @@ namespace OpenTween
             }
         }
 
-        internal static string CreateHtmlAnchor(string text, TwitterEntities entities, TwitterQuotedStatusPermalink quotedStatusLink)
+        internal static string CreateHtmlAnchor(string text, TwitterEntities? entities, TwitterQuotedStatusPermalink? quotedStatusLink)
         {
             var mergedEntities = entities.Concat(TweetExtractor.ExtractEmojiEntities(text));
 
@@ -1679,13 +1693,13 @@ namespace OpenTween
         /// <summary>
         /// Twitter APIから得たHTML形式のsource文字列を分析し、source名とURLに分離します
         /// </summary>
-        internal static (string SourceText, Uri SourceUri) ParseSource(string sourceHtml)
+        internal static (string SourceText, Uri? SourceUri) ParseSource(string? sourceHtml)
         {
             if (string.IsNullOrEmpty(sourceHtml))
                 return ("", null);
 
             string sourceText;
-            Uri sourceUri;
+            Uri? sourceUri;
 
             // sourceHtmlの例: <a href="http://twitter.com" rel="nofollow">Twitter Web Client</a>
 
@@ -1712,7 +1726,7 @@ namespace OpenTween
             return (sourceText, sourceUri);
         }
 
-        public async Task<TwitterApiStatus> GetInfoApi()
+        public async Task<TwitterApiStatus?> GetInfoApi()
         {
             if (Twitter.AccountState != MyCommon.ACCOUNT_STATE.Valid) return null;
 
@@ -1894,15 +1908,15 @@ namespace OpenTween
         public event EventHandler<PostDeletedEventArgs> PostDeleted;
         public event EventHandler<UserStreamEventReceivedEventArgs> UserStreamEventReceived;
         private DateTimeUtc _lastUserstreamDataReceived;
-        private StreamAutoConnector userStreamConnector;
+        private StreamAutoConnector? userStreamConnector;
 
         public class FormattedEvent
         {
             public MyCommon.EVENTTYPE Eventtype { get; set; }
             public DateTimeUtc CreatedAt { get; set; }
-            public string Event { get; set; }
-            public string Username { get; set; }
-            public string Target { get; set; }
+            public string Event { get; set; } = "";
+            public string Username { get; set; } = "";
+            public string Target { get; set; } = "";
             public long Id { get; set; }
             public bool IsMe { get; set; }
         }
@@ -2004,6 +2018,9 @@ namespace OpenTween
         /// </summary>
         private FormattedEvent CreateEventFromRetweet(TwitterStatus status)
         {
+            if (status.RetweetedStatus == null)
+                throw new InvalidOperationException();
+
             return new FormattedEvent
             {
                 Eventtype = MyCommon.EVENTTYPE.Retweet,
@@ -2081,7 +2098,7 @@ namespace OpenTween
 
                     if (eventData.Event == "favorite")
                     {
-                        var favTab = tabinfo.GetTabByType(MyCommon.TabUsageType.Favorites);
+                        var favTab = tabinfo.FavoriteTab;
                         favTab.AddPostQueue(post);
 
                         if (tweetEvent.Source.Id == this.UserId)
@@ -2215,11 +2232,11 @@ namespace OpenTween
             public bool IsStreamActive { get; private set; }
             public bool IsDisposed { get; private set; }
 
-            public event Action<ITwitterStreamMessage> MessageReceived;
-            public event Action Stopped;
-            public event Action Started;
+            public event Action<ITwitterStreamMessage>? MessageReceived;
+            public event Action? Stopped;
+            public event Action? Started;
 
-            private Task streamTask;
+            private Task? streamTask;
             private CancellationTokenSource streamCts = new CancellationTokenSource();
 
             public StreamAutoConnector(TwitterStreamObservable streamObservable)
index 3ecda20..53c49bd 100644 (file)
@@ -25,6 +25,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
index fd94626..f11781d 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Net;
 using OpenTween.Api.DataModel;
@@ -51,7 +53,7 @@ namespace OpenTween
             {
                 this.ImageUrl = null;
             }
-            this.Url = user.Url;
+            this.Url = user.Url ?? "";
             this.Protect = user.Protected;
             this.FriendsCount = user.FriendsCount;
             this.FollowersCount = user.FollowersCount;
@@ -70,7 +72,7 @@ namespace OpenTween
         public string ScreenName = "";
         public string Location = "";
         public string Description = "";
-        public Uri ImageUrl = null;
+        public Uri? ImageUrl = null;
         public string Url = "";
         public bool Protect = false;
         public int FriendsCount = 0;
index 47c4da7..24370be 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
@@ -47,8 +49,8 @@ namespace OpenTween
 {
     public partial class UserInfoDialog : OTBaseForm
     {
-        private TwitterUser _displayUser;
-        private CancellationTokenSource cancellationTokenSource = null;
+        private TwitterUser _displayUser = null!;
+        private CancellationTokenSource? cancellationTokenSource = null;
 
         private readonly TweenMain mainForm;
         private readonly TwitterApi twitterApi;
@@ -67,7 +69,7 @@ namespace OpenTween
         [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope")]
         private void CancelLoading()
         {
-            CancellationTokenSource oldTokenSource = null;
+            CancellationTokenSource? oldTokenSource = null;
             try
             {
                 var newTokenSource = new CancellationTokenSource();
@@ -93,7 +95,7 @@ namespace OpenTween
 
             this.CancelLoading();
 
-            var cancellationToken = this.cancellationTokenSource.Token;
+            var cancellationToken = this.cancellationTokenSource!.Token;
 
             this._displayUser = user;
 
@@ -152,23 +154,25 @@ namespace OpenTween
 
             await Task.WhenAll(new[]
             {
-                this.SetDescriptionAsync(user.Description, user.Entities.Description, cancellationToken),
+                this.SetDescriptionAsync(user.Description, user.Entities?.Description, cancellationToken),
                 this.SetRecentStatusAsync(user.Status, cancellationToken),
-                this.SetLinkLabelWebAsync(user.Url, user.Entities.Url, cancellationToken),
+                this.SetLinkLabelWebAsync(user.Url, user.Entities?.Url, cancellationToken),
                 this.SetUserImageAsync(user.ProfileImageUrlHttps, cancellationToken),
                 this.LoadFriendshipAsync(user.ScreenName, cancellationToken),
             });
         }
 
-        private async Task SetDescriptionAsync(string descriptionText, TwitterEntities entities, CancellationToken cancellationToken)
+        private async Task SetDescriptionAsync(string? descriptionText, TwitterEntities? entities, CancellationToken cancellationToken)
         {
             if (descriptionText != null)
             {
-                foreach (var entity in entities.Urls)
+                var urlEntities = entities?.Urls ?? Array.Empty<TwitterEntityUrl>();
+
+                foreach (var entity in urlEntities)
                     entity.ExpandedUrl = await ShortUrl.Instance.ExpandUrlAsync(entity.ExpandedUrl);
 
                 // user.entities には urls 以外のエンティティが含まれていないため、テキストをもとに生成する
-                var mergedEntities = entities.Urls.AsEnumerable<TwitterEntity>()
+                var mergedEntities = urlEntities.AsEnumerable<TwitterEntity>()
                     .Concat(TweetExtractor.ExtractHashtagEntities(descriptionText))
                     .Concat(TweetExtractor.ExtractMentionEntities(descriptionText))
                     .Concat(TweetExtractor.ExtractEmojiEntities(descriptionText));
@@ -218,11 +222,11 @@ namespace OpenTween
             });
         }
 
-        private async Task SetLinkLabelWebAsync(string uri, TwitterEntities entities, CancellationToken cancellationToken)
+        private async Task SetLinkLabelWebAsync(string? uri, TwitterEntities? entities, CancellationToken cancellationToken)
         {
             if (uri != null)
             {
-                var origUrl = entities?.Urls[0].ExpandedUrl ?? uri;
+                var origUrl = entities?.Urls?.FirstOrDefault()?.ExpandedUrl ?? uri;
                 var expandedUrl = await ShortUrl.Instance.ExpandUrlAsync(origUrl);
 
                 if (cancellationToken.IsCancellationRequested)
@@ -240,13 +244,14 @@ namespace OpenTween
             }
         }
 
-        private async Task SetRecentStatusAsync(TwitterStatus status, CancellationToken cancellationToken)
+        private async Task SetRecentStatusAsync(TwitterStatus? status, CancellationToken cancellationToken)
         {
             if (status != null)
             {
                 var entities = status.MergedEntities;
+                var urlEntities = entities.Urls ?? Array.Empty<TwitterEntityUrl>();
 
-                foreach (var entity in entities.Urls)
+                foreach (var entity in urlEntities)
                     entity.ExpandedUrl = await ShortUrl.Instance.ExpandUrlAsync(entity.ExpandedUrl);
 
                 var mergedEntities = entities.Concat(TweetExtractor.ExtractEmojiEntities(status.FullText));
@@ -504,7 +509,7 @@ namespace OpenTween
                 }
                 else
                 {
-                    Task showUserTask = null;
+                    Task? showUserTask = null;
 
                     if (TextBoxName.Modified ||
                         TextBoxLocation.Modified ||
@@ -732,8 +737,8 @@ namespace OpenTween
             if (disposing)
             {
                 var cts = this.cancellationTokenSource;
-                cts.Cancel();
-                cts.Dispose();
+                cts?.Cancel();
+                cts?.Dispose();
 
                 var oldImage = this.UserPicture.Image;
                 this.UserPicture.Image = null;
index fb14cd5..eb9561b 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
@@ -87,7 +89,7 @@ namespace OpenTween
         public Task WaitForAsync(Task task)
             => this.WaitForAsync(this.ConvertTaskWithValue(task));
 
-        public Task WaitForAsync(IWin32Window owner, Task task)
+        public Task WaitForAsync(IWin32Window? owner, Task task)
             => this.WaitForAsync(owner, this.ConvertTaskWithValue(task));
 
         public Task<T> WaitForAsync<T>(Task<T> task)
@@ -98,7 +100,7 @@ namespace OpenTween
         /// </summary>
         /// <param name="owner">ダイアログのオーナー</param>
         /// <param name="task">待機するタスク</param>
-        public Task<T> WaitForAsync<T>(IWin32Window owner, Task<T> task)
+        public Task<T> WaitForAsync<T>(IWin32Window? owner, Task<T> task)
         {
             return Task.Run(async () =>
             {
index 1e231aa..cbafa5d 100644 (file)
@@ -19,6 +19,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -33,7 +35,7 @@ namespace OpenTween
     [Serializable]
     public class WebApiException : Exception
     {
-        public string ResponseText { get; } = null;
+        public string? ResponseText { get; } = null;
 
         public WebApiException() { }
         public WebApiException(string message) : base(message) { }
index c447b69..1d66983 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -239,7 +241,7 @@ namespace OpenTween
             int SetSecuritySite([In] IInternetSecurityMgrSite pSite);
 
             [PreserveSig]
-            int GetSecuritySite(out IInternetSecurityMgrSite pSite);
+            int GetSecuritySite(out IInternetSecurityMgrSite? pSite);
 
             [PreserveSig]
             int MapUrlToZone([In, MarshalAs(UnmanagedType.LPWStr)] string pwszUrl, out int pdwZone, int dwFlags);
@@ -257,7 +259,7 @@ namespace OpenTween
             int SetZoneMapping(int dwZone, [In, MarshalAs(UnmanagedType.LPWStr)] string lpszPattern, int dwFlags);
 
             [PreserveSig]
-            int GetZoneMappings(int dwZone, ref IEnumString ppenumstring, int dwFlags);
+            int GetZoneMappings(int dwZone, ref IEnumString? ppenumstring, int dwFlags);
         }
     }
     #endregion
@@ -283,7 +285,7 @@ namespace OpenTween
         private readonly object ocx = new object();
         private readonly WebBrowserAPI.IServiceProvider ocxServiceProvider;
         private readonly IntPtr profferServicePtr = new IntPtr();
-        private readonly WebBrowserAPI.IProfferService profferService;
+        private readonly WebBrowserAPI.IProfferService profferService = null!;
 
         public POLICY SecurityPolicy { get; set; } = 0;
 
@@ -361,13 +363,13 @@ namespace OpenTween
         int WebBrowserAPI.IInternetSecurityManager.GetSecurityId(string pwszUrl, byte[] pbSecurityId, ref uint pcbSecurityId, uint dwReserved)
             => WebBrowserAPI.INET_E_DEFAULT_ACTION;
 
-        int WebBrowserAPI.IInternetSecurityManager.GetSecuritySite(out WebBrowserAPI.IInternetSecurityMgrSite pSite)
+        int WebBrowserAPI.IInternetSecurityManager.GetSecuritySite(out WebBrowserAPI.IInternetSecurityMgrSite? pSite)
         {
             pSite = null;
             return WebBrowserAPI.INET_E_DEFAULT_ACTION;
         }
 
-        int WebBrowserAPI.IInternetSecurityManager.GetZoneMappings(int dwZone, ref IEnumString ppenumstring, int dwFlags)
+        int WebBrowserAPI.IInternetSecurityManager.GetZoneMappings(int dwZone, ref IEnumString? ppenumstring, int dwFlags)
         {
             ppenumstring = null;
             return WebBrowserAPI.INET_E_DEFAULT_ACTION;
index 55b60a2..6a23a2a 100644 (file)
@@ -24,6 +24,8 @@
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 
 namespace OpenTween