Nullability annotations for System.Console (dotnet/corefx#41161)
authorMaryam Ariyan <maryam.ariyan@microsoft.com>
Thu, 19 Sep 2019 02:50:18 +0000 (19:50 -0700)
committerGitHub <noreply@github.com>
Thu, 19 Sep 2019 02:50:18 +0000 (19:50 -0700)
Contributes to: dotnet/corefx#40623

Commit migrated from https://github.com/dotnet/corefx/commit/19b304f7815894b13cb61e87e1c9eac49a474c7e

13 files changed:
src/libraries/Common/src/System/Text/EncodingHelper.Unix.cs
src/libraries/Common/src/System/Text/OSEncoding.Windows.cs
src/libraries/Common/src/System/Text/StringOrCharArray.cs
src/libraries/System.Console/ref/System.Console.cs
src/libraries/System.Console/ref/System.Console.csproj
src/libraries/System.Console/src/System.Console.csproj
src/libraries/System.Console/src/System/Console.cs
src/libraries/System.Console/src/System/ConsoleCancelEventArgs.cs
src/libraries/System.Console/src/System/ConsoleKeyInfo.cs
src/libraries/System.Console/src/System/ConsolePal.Unix.cs
src/libraries/System.Console/src/System/IO/StdInReader.cs
src/libraries/System.Console/src/System/IO/SyncTextReader.cs
src/libraries/System.Console/src/System/TermInfo.cs

index 0fb91e6..111f161 100644 (file)
@@ -8,9 +8,9 @@ namespace System.Text
     {
         /// <summary>Creates an encoding from the current environment.</summary>
         /// <returns>The encoding, or null if it could not be determined.</returns>
-        internal static Encoding GetEncodingFromCharset()
+        internal static Encoding? GetEncodingFromCharset()
         {
-            string charset = GetCharset();
+            string? charset = GetCharset();
             if (charset != null)
             {
                 try { return Encoding.GetEncoding(charset); }
@@ -31,10 +31,10 @@ namespace System.Text
 
         /// <summary>Gets the current charset name from the environment.</summary>
         /// <returns>The charset name if found; otherwise, null.</returns>
-        private static string GetCharset()
+        private static string? GetCharset()
         {
             // Find the first of the locale environment variables that's set.
-            string locale = null;
+            string? locale = null;
             foreach (string envVar in s_localeEnvVars)
             {
                 locale = Environment.GetEnvironmentVariable(envVar);
index c7815f6..82ad53b 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
 using System;
 using System.Text;
 using System.Collections.Generic;
@@ -11,7 +12,7 @@ namespace System.Text
     internal sealed class OSEncoding : Encoding
     {
         private readonly int _codePage;
-        private string _encodingName;
+        private string? _encodingName;
 
         internal OSEncoding(int codePage) : base(codePage)
         {
index 2da29e3..c9d54e2 100644 (file)
@@ -14,9 +14,9 @@ namespace System.Text
     /// </summary>
     internal readonly struct StringOrCharArray : IEquatable<StringOrCharArray>
     {
-        public readonly string String;
+        public readonly string? String;
 
-        public readonly char[] CharArray;
+        public readonly char[]? CharArray;
         public readonly int CharArrayOffset;
         public readonly int CharArrayCount;
 
@@ -56,7 +56,7 @@ namespace System.Text
             }
         }
 
-        public override bool Equals(object obj)
+        public override bool Equals(object? obj)
         {
             return
                 obj is StringOrCharArray &&
@@ -75,6 +75,7 @@ namespace System.Text
                 {
                     return StringComparer.Ordinal.Equals(this.String, other.String);
                 }
+                Debug.Assert(other.CharArray != null);
 
                 // String vs CharArray
                 if (this.String.Length != other.CharArrayCount)
@@ -88,6 +89,7 @@ namespace System.Text
 
                 return true;
             }
+            Debug.Assert(CharArray != null);
 
             // CharArray vs CharArray
             if (other.CharArray != null)
@@ -103,6 +105,7 @@ namespace System.Text
 
                 return true;
             }
+            Debug.Assert(other.String != null);
 
             // CharArray vs String
             if (this.CharArrayCount != other.String.Length)
index ab32dca..ce7fdaa 100644 (file)
@@ -36,7 +36,7 @@ namespace System
         public static int WindowLeft { get { throw null; } set { } }
         public static int WindowTop { get { throw null; } set { } }
         public static int WindowWidth { get { throw null; } set { } }
-        public static event System.ConsoleCancelEventHandler CancelKeyPress { add { } remove { } }
+        public static event System.ConsoleCancelEventHandler? CancelKeyPress { add { } remove { } }
         public static void Beep() { }
         public static void Beep(int frequency, int duration) { }
         public static void Clear() { }
@@ -51,7 +51,7 @@ namespace System
         public static int Read() { throw null; }
         public static System.ConsoleKeyInfo ReadKey() { throw null; }
         public static System.ConsoleKeyInfo ReadKey(bool intercept) { throw null; }
-        public static string ReadLine() { throw null; }
+        public static string? ReadLine() { throw null; }
         public static void ResetColor() { }
         public static void SetBufferSize(int width, int height) { }
         public static void SetCursorPosition(int left, int top) { }
@@ -62,19 +62,19 @@ namespace System
         public static void SetWindowSize(int width, int height) { }
         public static void Write(bool value) { }
         public static void Write(char value) { }
-        public static void Write(char[] buffer) { }
+        public static void Write(char[]? buffer) { }
         public static void Write(char[] buffer, int index, int count) { }
         public static void Write(decimal value) { }
         public static void Write(double value) { }
         public static void Write(int value) { }
         public static void Write(long value) { }
-        public static void Write(object value) { }
+        public static void Write(object? value) { }
         public static void Write(float value) { }
-        public static void Write(string value) { }
-        public static void Write(string format, object arg0) { }
-        public static void Write(string format, object arg0, object arg1) { }
-        public static void Write(string format, object arg0, object arg1, object arg2) { }
-        public static void Write(string format, params object[] arg) { }
+        public static void Write(string? value) { }
+        public static void Write(string format, object? arg0) { }
+        public static void Write(string format, object? arg0, object? arg1) { }
+        public static void Write(string format, object? arg0, object? arg1, object? arg2) { }
+        public static void Write(string format, params object?[]? arg) { }
         [System.CLSCompliantAttribute(false)]
         public static void Write(uint value) { }
         [System.CLSCompliantAttribute(false)]
@@ -82,19 +82,19 @@ namespace System
         public static void WriteLine() { }
         public static void WriteLine(bool value) { }
         public static void WriteLine(char value) { }
-        public static void WriteLine(char[] buffer) { }
+        public static void WriteLine(char[]? buffer) { }
         public static void WriteLine(char[] buffer, int index, int count) { }
         public static void WriteLine(decimal value) { }
         public static void WriteLine(double value) { }
         public static void WriteLine(int value) { }
         public static void WriteLine(long value) { }
-        public static void WriteLine(object value) { }
+        public static void WriteLine(object? value) { }
         public static void WriteLine(float value) { }
-        public static void WriteLine(string value) { }
-        public static void WriteLine(string format, object arg0) { }
-        public static void WriteLine(string format, object arg0, object arg1) { }
-        public static void WriteLine(string format, object arg0, object arg1, object arg2) { }
-        public static void WriteLine(string format, params object[] arg) { }
+        public static void WriteLine(string? value) { }
+        public static void WriteLine(string format, object? arg0) { }
+        public static void WriteLine(string format, object? arg0, object? arg1) { }
+        public static void WriteLine(string format, object? arg0, object? arg1, object? arg2) { }
+        public static void WriteLine(string format, params object?[]? arg) { }
         [System.CLSCompliantAttribute(false)]
         public static void WriteLine(uint value) { }
         [System.CLSCompliantAttribute(false)]
@@ -106,7 +106,7 @@ namespace System
         public bool Cancel { get { throw null; } set { } }
         public System.ConsoleSpecialKey SpecialKey { get { throw null; } }
     }
-    public delegate void ConsoleCancelEventHandler(object sender, System.ConsoleCancelEventArgs e);
+    public delegate void ConsoleCancelEventHandler(object? sender, System.ConsoleCancelEventArgs e);
     public enum ConsoleColor
     {
         Black = 0,
@@ -281,7 +281,7 @@ namespace System
         public char KeyChar { get { throw null; } }
         public System.ConsoleModifiers Modifiers { get { throw null; } }
         public bool Equals(System.ConsoleKeyInfo obj) { throw null; }
-        public override bool Equals(object value) { throw null; }
+        public override bool Equals(object? value) { throw null; }
         public override int GetHashCode() { throw null; }
         public static bool operator ==(System.ConsoleKeyInfo a, System.ConsoleKeyInfo b) { throw null; }
         public static bool operator !=(System.ConsoleKeyInfo a, System.ConsoleKeyInfo b) { throw null; }
index 93ffdc8..4a14acc 100644 (file)
@@ -1,6 +1,7 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <Configurations>netcoreapp-Debug;netcoreapp-Release;uap-Debug;uap-Release</Configurations>
+    <Nullable>enable</Nullable>
   </PropertyGroup>
   <ItemGroup>
     <Compile Include="System.Console.cs" />
index 37f552e..93bc6bb 100644 (file)
@@ -1,9 +1,10 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <RootNamespace>System.Console</RootNamespace>
     <AssemblyName>System.Console</AssemblyName>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
     <Configurations>netcoreapp-Unix-Debug;netcoreapp-Unix-Release;netcoreapp-Windows_NT-Debug;netcoreapp-Windows_NT-Release;uap-Windows_NT-Debug;uap-Windows_NT-Release</Configurations>
+    <Nullable>enable</Nullable>
   </PropertyGroup>
   <ItemGroup>
     <Compile Include="FxCopBaseline.cs" />
index 365f03e..b2e6986 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+using System.Diagnostics.CodeAnalysis;
 using System.IO;
 using System.Runtime.CompilerServices;
 using System.Text;
@@ -22,17 +23,17 @@ namespace System
         private const int WriteBufferSize = 256;
 
         private static object InternalSyncObject = new object(); // for synchronizing changing of Console's static fields
-        private static TextReader s_in;
-        private static TextWriter s_out, s_error;
-        private static Encoding s_inputEncoding;
-        private static Encoding s_outputEncoding;
+        private static TextReader? s_in;
+        private static TextWriter? s_out, s_error;
+        private static Encoding? s_inputEncoding;
+        private static Encoding? s_outputEncoding;
         private static bool s_isOutTextWriterRedirected = false;
         private static bool s_isErrorTextWriterRedirected = false;
 
-        private static ConsoleCancelEventHandler s_cancelCallbacks;
-        private static ConsolePal.ControlCHandlerRegistrar s_registrar;
+        private static ConsoleCancelEventHandler? s_cancelCallbacks;
+        private static ConsolePal.ControlCHandlerRegistrar? s_registrar;
 
-        internal static T EnsureInitialized<T>(ref T field, Func<T> initializer) where T : class =>
+        internal static T EnsureInitialized<T>([NotNull] ref T? field, Func<T> initializer) where T : class =>
             LazyInitializer.EnsureInitialized(ref field, ref InternalSyncObject, initializer);
 
         public static TextReader In => EnsureInitialized(ref s_in, () => ConsolePal.GetOrCreateReader());
@@ -81,12 +82,12 @@ namespace System
                     // s_out reinitialize the console code page.
                     if (Volatile.Read(ref s_out) != null && !s_isOutTextWriterRedirected)
                     {
-                        s_out.Flush();
+                        s_out!.Flush();
                         Volatile.Write(ref s_out, null);
                     }
                     if (Volatile.Read(ref s_error) != null && !s_isErrorTextWriterRedirected)
                     {
-                        s_error.Flush();
+                        s_error!.Flush();
                         Volatile.Write(ref s_error, null);
                     }
 
@@ -136,9 +137,9 @@ namespace System
                 });
         }
 
-        private static StrongBox<bool> _isStdInRedirected;
-        private static StrongBox<bool> _isStdOutRedirected;
-        private static StrongBox<bool> _isStdErrRedirected;
+        private static StrongBox<bool>? _isStdInRedirected;
+        private static StrongBox<bool>? _isStdOutRedirected;
+        private static StrongBox<bool>? _isStdErrRedirected;
 
         public static bool IsInputRedirected
         {
@@ -326,7 +327,7 @@ namespace System
             ConsolePal.SetCursorPosition(left, top);
         }
 
-        public static event ConsoleCancelEventHandler CancelKeyPress
+        public static event ConsoleCancelEventHandler? CancelKeyPress
         {
             add
             {
@@ -461,7 +462,7 @@ namespace System
         }
 
         [MethodImplAttribute(MethodImplOptions.NoInlining)]
-        public static string ReadLine()
+        public static string? ReadLine()
         {
             return In.ReadLine();
         }
@@ -485,7 +486,7 @@ namespace System
         }
 
         [MethodImplAttribute(MethodImplOptions.NoInlining)]
-        public static void WriteLine(char[] buffer)
+        public static void WriteLine(char[]? buffer)
         {
             Out.WriteLine(buffer);
         }
@@ -541,37 +542,37 @@ namespace System
         }
 
         [MethodImplAttribute(MethodImplOptions.NoInlining)]
-        public static void WriteLine(object value)
+        public static void WriteLine(object? value)
         {
             Out.WriteLine(value);
         }
 
         [MethodImplAttribute(MethodImplOptions.NoInlining)]
-        public static void WriteLine(string value)
+        public static void WriteLine(string? value)
         {
             Out.WriteLine(value);
         }
 
         [MethodImplAttribute(MethodImplOptions.NoInlining)]
-        public static void WriteLine(string format, object arg0)
+        public static void WriteLine(string format, object? arg0)
         {
             Out.WriteLine(format, arg0);
         }
 
         [MethodImplAttribute(MethodImplOptions.NoInlining)]
-        public static void WriteLine(string format, object arg0, object arg1)
+        public static void WriteLine(string format, object? arg0, object? arg1)
         {
             Out.WriteLine(format, arg0, arg1);
         }
 
         [MethodImplAttribute(MethodImplOptions.NoInlining)]
-        public static void WriteLine(string format, object arg0, object arg1, object arg2)
+        public static void WriteLine(string format, object? arg0, object? arg1, object? arg2)
         {
             Out.WriteLine(format, arg0, arg1, arg2);
         }
 
         [MethodImplAttribute(MethodImplOptions.NoInlining)]
-        public static void WriteLine(string format, params object[] arg)
+        public static void WriteLine(string format, params object?[]? arg)
         {
             if (arg == null)                       // avoid ArgumentNullException from String.Format
                 Out.WriteLine(format, null, null); // faster than Out.WriteLine(format, (Object)arg);
@@ -580,25 +581,25 @@ namespace System
         }
 
         [MethodImplAttribute(MethodImplOptions.NoInlining)]
-        public static void Write(string format, object arg0)
+        public static void Write(string format, object? arg0)
         {
             Out.Write(format, arg0);
         }
 
         [MethodImplAttribute(MethodImplOptions.NoInlining)]
-        public static void Write(string format, object arg0, object arg1)
+        public static void Write(string format, object? arg0, object? arg1)
         {
             Out.Write(format, arg0, arg1);
         }
 
         [MethodImplAttribute(MethodImplOptions.NoInlining)]
-        public static void Write(string format, object arg0, object arg1, object arg2)
+        public static void Write(string format, object? arg0, object? arg1, object? arg2)
         {
             Out.Write(format, arg0, arg1, arg2);
         }
 
         [MethodImplAttribute(MethodImplOptions.NoInlining)]
-        public static void Write(string format, params object[] arg)
+        public static void Write(string format, params object?[]? arg)
         {
             if (arg == null)                   // avoid ArgumentNullException from String.Format
                 Out.Write(format, null, null); // faster than Out.Write(format, (Object)arg);
@@ -619,7 +620,7 @@ namespace System
         }
 
         [MethodImplAttribute(MethodImplOptions.NoInlining)]
-        public static void Write(char[] buffer)
+        public static void Write(char[]? buffer)
         {
             Out.Write(buffer);
         }
@@ -675,20 +676,20 @@ namespace System
         }
 
         [MethodImplAttribute(MethodImplOptions.NoInlining)]
-        public static void Write(object value)
+        public static void Write(object? value)
         {
             Out.Write(value);
         }
 
         [MethodImplAttribute(MethodImplOptions.NoInlining)]
-        public static void Write(string value)
+        public static void Write(string? value)
         {
             Out.Write(value);
         }
 
         internal static bool HandleBreakEvent(ConsoleSpecialKey controlKey)
         {
-            ConsoleCancelEventHandler handler = s_cancelCallbacks;
+            ConsoleCancelEventHandler? handler = s_cancelCallbacks;
             if (handler == null)
             {
                 return false;
index 7638136..ac55456 100644 (file)
@@ -5,7 +5,7 @@
 namespace System
 {
 
-    public delegate void ConsoleCancelEventHandler(object sender, ConsoleCancelEventArgs e);
+    public delegate void ConsoleCancelEventHandler(object? sender, ConsoleCancelEventArgs e);
 
     public sealed class ConsoleCancelEventArgs : EventArgs
     {
index 1e40ff0..2ac7fe5 100644 (file)
@@ -47,7 +47,7 @@ namespace System
             get { return _mods; }
         }
 
-        public override bool Equals(object value)
+        public override bool Equals(object? value)
         {
             return value is ConsoleKeyInfo && Equals((ConsoleKeyInfo)value);
         }
index 4e82044..4718bdf 100644 (file)
@@ -67,7 +67,7 @@ namespace System
             get { return GetConsoleEncoding(); }
         }
 
-        private static SyncTextReader s_stdInReader;
+        private static SyncTextReader? s_stdInReader;
 
         private static SyncTextReader StdInReader
         {
@@ -200,7 +200,7 @@ namespace System
                 if (Console.IsOutputRedirected)
                     return;
 
-                string titleFormat = TerminalFormatStrings.Instance.Title;
+                string? titleFormat = TerminalFormatStrings.Instance.Title;
                 if (!string.IsNullOrEmpty(titleFormat))
                 {
                     string ansiStr = TermInfo.ParameterizedStrings.Evaluate(titleFormat, value);
@@ -244,7 +244,7 @@ namespace System
                     return;
                 }
 
-                string cursorAddressFormat = TerminalFormatStrings.Instance.CursorAddress;
+                string? cursorAddressFormat = TerminalFormatStrings.Instance.CursorAddress;
                 if (!string.IsNullOrEmpty(cursorAddressFormat))
                 {
                     string ansiStr = TermInfo.ParameterizedStrings.Evaluate(cursorAddressFormat, top, left);
@@ -731,7 +731,7 @@ namespace System
         /// <returns>The encoding.</returns>
         private static Encoding GetConsoleEncoding()
         {
-            Encoding enc = EncodingHelper.GetEncodingFromCharset();
+            Encoding? enc = EncodingHelper.GetEncodingFromCharset();
             return enc != null ?
                 enc.RemovePreamble() :
                 new UTF8Encoding(encoderShouldEmitUTF8Identifier: false);
@@ -803,7 +803,7 @@ namespace System
             }
 
             // We haven't yet computed a format string.  Compute it, use it, then cache it.
-            string formatString = foreground ? TerminalFormatStrings.Instance.Foreground : TerminalFormatStrings.Instance.Background;
+            string? formatString = foreground ? TerminalFormatStrings.Instance.Foreground : TerminalFormatStrings.Instance.Background;
             if (!string.IsNullOrEmpty(formatString))
             {
                 int maxColors = TerminalFormatStrings.Instance.MaxColors; // often 8 or 16; 0 is invalid
@@ -946,7 +946,7 @@ namespace System
                     // the native lib later to handle signals that require re-entering the mode.
                     if (!Console.IsOutputRedirected)
                     {
-                        string keypadXmit = TerminalFormatStrings.Instance.KeypadXmit;
+                        string? keypadXmit = TerminalFormatStrings.Instance.KeypadXmit;
                         if (keypadXmit != null)
                         {
                             Interop.Sys.SetKeypadXmit(keypadXmit);
@@ -982,11 +982,11 @@ namespace System
             private static readonly Lazy<TerminalFormatStrings> s_instance = new Lazy<TerminalFormatStrings>(() => new TerminalFormatStrings(TermInfo.Database.ReadActiveDatabase()));
 
             /// <summary>The format string to use to change the foreground color.</summary>
-            public readonly string Foreground;
+            public readonly string? Foreground;
             /// <summary>The format string to use to change the background color.</summary>
-            public readonly string Background;
+            public readonly string? Background;
             /// <summary>The format string to use to reset the foreground and background colors.</summary>
-            public readonly string Reset;
+            public readonly string? Reset;
             /// <summary>The maximum number of colors supported by the terminal.</summary>
             public readonly int MaxColors;
             /// <summary>The number of columns in a format.</summary>
@@ -994,21 +994,21 @@ namespace System
             /// <summary>The number of lines in a format.</summary>
             public readonly int Lines;
             /// <summary>The format string to use to make cursor visible.</summary>
-            public readonly string CursorVisible;
+            public readonly string? CursorVisible;
             /// <summary>The format string to use to make cursor invisible</summary>
-            public readonly string CursorInvisible;
+            public readonly string? CursorInvisible;
             /// <summary>The format string to use to set the window title.</summary>
-            public readonly string Title;
+            public readonly string? Title;
             /// <summary>The format string to use for an audible bell.</summary>
-            public readonly string Bell;
+            public readonly string? Bell;
             /// <summary>The format string to use to clear the terminal.</summary>
-            public readonly string Clear;
+            public readonly string? Clear;
             /// <summary>The format string to use to set the position of the cursor.</summary>
-            public readonly string CursorAddress;
+            public readonly string? CursorAddress;
             /// <summary>The format string to use to move the cursor to the left.</summary>
-            public readonly string CursorLeft;
+            public readonly string? CursorLeft;
             /// <summary>The format string to use to clear to the end of line.</summary>
-            public readonly string ClrEol;
+            public readonly string? ClrEol;
             /// <summary>The ANSI-compatible string for the Cursor Position report request.</summary>
             /// <remarks>
             /// This should really be in user string 7 in the terminfo file, but some terminfo databases
@@ -1028,9 +1028,9 @@ namespace System
             /// <summary> Min key length </summary>
             public readonly int MinKeyFormatLength;
             /// <summary>The ANSI string used to enter "application" / "keypad transmit" mode.</summary>
-            public readonly string KeypadXmit;
+            public readonly string? KeypadXmit;
 
-            public TerminalFormatStrings(TermInfo.Database db)
+            public TerminalFormatStrings(TermInfo.Database? db)
             {
                 if (db == null)
                     return;
@@ -1143,8 +1143,8 @@ namespace System
             private static string GetTitle(TermInfo.Database db)
             {
                 // Try to get the format string from tsl/fsl and use it if they're available
-                string tsl = db.GetString(TermInfo.WellKnownStrings.ToStatusLine);
-                string fsl = db.GetString(TermInfo.WellKnownStrings.FromStatusLine);
+                string? tsl = db.GetString(TermInfo.WellKnownStrings.ToStatusLine);
+                string? fsl = db.GetString(TermInfo.WellKnownStrings.FromStatusLine);
                 if (tsl != null && fsl != null)
                 {
                     return tsl + "%p1%s" + fsl;
@@ -1187,7 +1187,7 @@ namespace System
 
             private void AddKey(TermInfo.Database db, TermInfo.WellKnownStrings keyId, ConsoleKey key, bool shift, bool alt, bool control)
             {
-                string keyFormat = db.GetString(keyId);
+                string? keyFormat = db.GetString(keyId);
                 if (!string.IsNullOrEmpty(keyFormat))
                     KeyFormatToConsoleKey[keyFormat] = new ConsoleKeyInfo('\0', key, shift, alt, control);
             }
@@ -1203,7 +1203,7 @@ namespace System
 
             private void AddKey(TermInfo.Database db, string extendedName, ConsoleKey key, bool shift, bool alt, bool control)
             {
-                string keyFormat = db.GetExtendedString(extendedName);
+                string? keyFormat = db.GetExtendedString(extendedName);
                 if (!string.IsNullOrEmpty(keyFormat))
                     KeyFormatToConsoleKey[keyFormat] = new ConsoleKeyInfo('\0', key, shift, alt, control);
             }
@@ -1372,7 +1372,7 @@ namespace System
         /// <summary>Writes a terminfo-based ANSI escape string to stdout.</summary>
         /// <param name="value">The string to write.</param>
         /// <param name="mayChangeCursorPosition">Writing this value may change the cursor position.</param>
-        internal static unsafe void WriteStdoutAnsiString(string value, bool mayChangeCursorPosition = true)
+        internal static unsafe void WriteStdoutAnsiString(string? value, bool mayChangeCursorPosition = true)
         {
             if (string.IsNullOrEmpty(value))
                 return;
@@ -1494,8 +1494,9 @@ namespace System
                 handlerThread.Start(ctrlCode);
             }
 
-            private static void HandleBreakEvent(object state)
+            private static void HandleBreakEvent(object? state)
             {
+                Debug.Assert(state != null);
                 var ctrlCode = (Interop.Sys.CtrlCode)state;
                 ConsoleSpecialKey controlKey = (ctrlCode == Interop.Sys.CtrlCode.Break ? ConsoleSpecialKey.ControlBreak : ConsoleSpecialKey.ControlC);
                 bool cancel = Console.HandleBreakEvent(controlKey);
index b323b86..f2a14c2 100644 (file)
@@ -16,8 +16,8 @@ namespace System.IO
      */
     internal sealed class StdInReader : TextReader
     {
-        private static string s_moveLeftString; // string written to move the cursor to the left
-        private static string s_clearToEol;     // string written to clear from cursor to end of line
+        private static string? s_moveLeftString; // string written to move the cursor to the left
+        private static string? s_clearToEol;     // string written to clear from cursor to end of line
 
         private readonly StringBuilder _readLineSB; // SB that holds readLine output.  This is a field simply to enable reuse; it's only used in ReadLine.
         private readonly Stack<ConsoleKeyInfo> _tmpKeys = new Stack<ConsoleKeyInfo>(); // temporary working stack; should be empty outside of ReadLine
@@ -78,15 +78,15 @@ namespace System.IO
             return result;
         }
 
-        public override string ReadLine()
+        public override string? ReadLine()
         {
             return ReadLine(consumeKeys: true);
         }
 
-        private string ReadLine(bool consumeKeys)
+        private string? ReadLine(bool consumeKeys)
         {
             Debug.Assert(_tmpKeys.Count == 0);
-            string readLineStr = null;
+            string? readLineStr = null;
 
             Interop.Sys.InitializeConsoleBeforeRead();
             try
@@ -156,7 +156,7 @@ namespace System.IO
                                 {
                                     if (s_moveLeftString == null)
                                     {
-                                        string moveLeft = ConsolePal.TerminalFormatStrings.Instance.CursorLeft;
+                                        string? moveLeft = ConsolePal.TerminalFormatStrings.Instance.CursorLeft;
                                         s_moveLeftString = !string.IsNullOrEmpty(moveLeft) ? moveLeft + " " + moveLeft : string.Empty;
                                     }
 
index b2d53c4..bc59b40 100644 (file)
@@ -70,7 +70,7 @@ namespace System.IO
             }
         }
 
-        public override string ReadLine()
+        public override string? ReadLine()
         {
             lock (this)
             {
@@ -91,7 +91,7 @@ namespace System.IO
         // No explicit locking is needed, as they all just delegate
         //
 
-        public override Task<string> ReadLineAsync()
+        public override Task<string?> ReadLineAsync()
         {
             return Task.FromResult(ReadLine());
         }
index 56bff4e..b35d8b5 100644 (file)
@@ -4,6 +4,7 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.IO;
 using System.Text;
 using Microsoft.Win32.SafeHandles;
@@ -163,9 +164,9 @@ namespace System
 
             /// <summary>Read the database for the current terminal as specified by the "TERM" environment variable.</summary>
             /// <returns>The database, or null if it could not be found.</returns>
-            internal static Database ReadActiveDatabase()
+            internal static Database? ReadActiveDatabase()
             {
-                string term = Environment.GetEnvironmentVariable("TERM");
+                string? term = Environment.GetEnvironmentVariable("TERM");
                 return !string.IsNullOrEmpty(term) ? ReadDatabase(term) : null;
             }
 
@@ -183,20 +184,20 @@ namespace System
             /// <summary>Read the database for the specified terminal.</summary>
             /// <param name="term">The identifier for the terminal.</param>
             /// <returns>The database, or null if it could not be found.</returns>
-            private static Database ReadDatabase(string term)
+            private static Database? ReadDatabase(string term)
             {
                 // This follows the same search order as prescribed by ncurses.
-                Database db;
+                Database? db;
 
                 // First try a location specified in the TERMINFO environment variable.
-                string terminfo = Environment.GetEnvironmentVariable("TERMINFO");
+                string? terminfo = Environment.GetEnvironmentVariable("TERMINFO");
                 if (!string.IsNullOrWhiteSpace(terminfo) && (db = ReadDatabase(term, terminfo)) != null)
                 {
                     return db;
                 }
 
                 // Then try in the user's home directory.
-                string home = PersistedFiles.GetHomeDirectory();
+                string? home = PersistedFiles.GetHomeDirectory();
                 if (!string.IsNullOrWhiteSpace(home) && (db = ReadDatabase(term, home + "/.terminfo")) != null)
                 {
                     return db;
@@ -219,7 +220,7 @@ namespace System
             /// <param name="filePath">The path to the file to open.</param>
             /// <param name="fd">If successful, the opened file descriptor; otherwise, -1.</param>
             /// <returns>true if the file was successfully opened; otherwise, false.</returns>
-            private static bool TryOpen(string filePath, out SafeFileHandle fd)
+            private static bool TryOpen(string filePath, [NotNullWhen(true)] out SafeFileHandle? fd)
             {
                 fd = Interop.Sys.Open(filePath, Interop.Sys.OpenFlags.O_RDONLY | Interop.Sys.OpenFlags.O_CLOEXEC, 0);
                 if (fd.IsInvalid)
@@ -236,14 +237,14 @@ namespace System
             /// <param name="term">The identifier for the terminal.</param>
             /// <param name="directoryPath">The path to the directory containing terminfo database files.</param>
             /// <returns>The database, or null if it could not be found.</returns>
-            private static Database ReadDatabase(string term, string directoryPath)
+            private static Database? ReadDatabase(string? term, string? directoryPath)
             {
                 if (string.IsNullOrEmpty(term) || string.IsNullOrEmpty(directoryPath))
                 {
                     return null;
                 }
 
-                SafeFileHandle fd;
+                SafeFileHandle? fd;
                 if (!TryOpen(directoryPath + "/" + term[0].ToString() + "/" + term, out fd) &&          // /directory/termFirstLetter/term      (Linux)
                     !TryOpen(directoryPath + "/" + ((int)term[0]).ToString("X") + "/" + term, out fd))  // /directory/termFirstLetterAsHex/term (Mac)
                 {
@@ -295,7 +296,7 @@ namespace System
             /// <summary>Gets a string from the strings section by the string's well-known index.</summary>
             /// <param name="stringTableIndex">The index of the string to find.</param>
             /// <returns>The string if it's in the database; otherwise, null.</returns>
-            public string GetString(WellKnownStrings stringTableIndex)
+            public string? GetString(WellKnownStrings stringTableIndex)
             {
                 int index = (int)stringTableIndex;
                 Debug.Assert(index >= 0);
@@ -321,11 +322,11 @@ namespace System
             /// <summary>Gets a string from the extended strings section.</summary>
             /// <param name="name">The name of the string as contained in the extended names section.</param>
             /// <returns>The string if it's in the database; otherwise, null.</returns>
-            public string GetExtendedString(string name)
+            public string? GetExtendedString(string name)
             {
                 Debug.Assert(name != null);
 
-                string value;
+                string? value;
                 return _extendedStrings.TryGetValue(name, out value) ?
                     value :
                     null;
@@ -355,7 +356,7 @@ namespace System
             /// defined as the earlier portions, and may not even exist, the parsing is more lenient about
             /// errors, returning an empty collection rather than throwing.
             /// </returns>
-            private static Dictionary<string, string> ParseExtendedStrings(byte[] data, int extendedBeginning, bool readAs32Bit)
+            private static Dictionary<string, string>? ParseExtendedStrings(byte[] data, int extendedBeginning, bool readAs32Bit)
             {
                 const int ExtendedHeaderSize = 10;
                 int sizeOfIntValuesInBytes = (readAs32Bit) ? 4 : 2;
@@ -512,15 +513,15 @@ namespace System
         {
             /// <summary>A cached stack to use to avoid allocating a new stack object for every evaluation.</summary>
             [ThreadStatic]
-            private static Stack<FormatParam> t_cachedStack;
+            private static Stack<FormatParam>? t_cachedStack;
 
             /// <summary>A cached array of arguments to use to avoid allocating a new array object for every evaluation.</summary>
             [ThreadStatic]
-            private static FormatParam[] t_cachedOneElementArgsArray;
+            private static FormatParam[]? t_cachedOneElementArgsArray;
 
             /// <summary>A cached array of arguments to use to avoid allocating a new array object for every evaluation.</summary>
             [ThreadStatic]
-            private static FormatParam[] t_cachedTwoElementArgsArray;
+            private static FormatParam[]? t_cachedTwoElementArgsArray;
 
             /// <summary>Evaluates a terminfo formatting string, using the supplied argument.</summary>
             /// <param name="format">The format string.</param>
@@ -528,7 +529,7 @@ namespace System
             /// <returns>The formatted string.</returns>
             public static string Evaluate(string format, FormatParam arg)
             {
-                FormatParam[] args = t_cachedOneElementArgsArray;
+                FormatParam[]? args = t_cachedOneElementArgsArray;
                 if (args == null)
                 {
                     t_cachedOneElementArgsArray = args = new FormatParam[1];
@@ -546,7 +547,7 @@ namespace System
             /// <returns>The formatted string.</returns>
             public static string Evaluate(string format, FormatParam arg1, FormatParam arg2)
             {
-                FormatParam[] args = t_cachedTwoElementArgsArray;
+                FormatParam[]? args = t_cachedTwoElementArgsArray;
                 if (args == null)
                 {
                     t_cachedTwoElementArgsArray = args = new FormatParam[2];
@@ -574,7 +575,7 @@ namespace System
                 }
 
                 // Initialize the stack to use for processing.
-                Stack<FormatParam> stack = t_cachedStack;
+                Stack<FormatParam>? stack = t_cachedStack;
                 if (stack == null)
                 {
                     t_cachedStack = stack = new Stack<FormatParam>();
@@ -587,7 +588,7 @@ namespace System
                 // "dynamic" and "static" variables are much less often used (the "dynamic" and "static"
                 // terminology appears to just refer to two different collections rather than to any semantic
                 // meaning).  As such, we'll only initialize them if we really need them.
-                FormatParam[] dynamicVars = null, staticVars = null;
+                FormatParam[]? dynamicVars = null, staticVars = null;
 
                 int pos = 0;
                 return EvaluateInternal(format, ref pos, args, stack, ref dynamicVars, ref staticVars);
@@ -610,7 +611,7 @@ namespace System
             /// </returns>
             private static string EvaluateInternal(
                 string format, ref int pos, FormatParam[] args, Stack<FormatParam> stack,
-                ref FormatParam[] dynamicVars, ref FormatParam[] staticVars)
+                ref FormatParam[]? dynamicVars, ref FormatParam[]? staticVars)
             {
                 // Create a StringBuilder to store the output of this processing.  We use the format's length as an
                 // approximation of an upper-bound for how large the output will be, though with parameter processing,
@@ -872,7 +873,7 @@ namespace System
                 Debug.Assert(arg is string || arg is int);
 
                 // Determine how much space is needed to store the formatted string.
-                string stringArg = arg as string;
+                string? stringArg = arg as string;
                 int neededLength = stringArg != null ?
                     Interop.Sys.SNPrintF(null, 0, format, stringArg) :
                     Interop.Sys.SNPrintF(null, 0, format, (int)arg);
@@ -907,7 +908,7 @@ namespace System
             /// <param name="index">The index to use to index into the variables.</param>
             /// <returns>The variables collection.</returns>
             private static FormatParam[] GetDynamicOrStaticVariables(
-                char c, ref FormatParam[] dynamicVars, ref FormatParam[] staticVars, out int index)
+                char c, ref FormatParam[]? dynamicVars, ref FormatParam[]? staticVars, out int index)
             {
                 if (c >= 'A' && c <= 'Z')
                 {
@@ -932,7 +933,7 @@ namespace System
                 /// <summary>The integer stored in the parameter.</summary>
                 private readonly int _int32;
                 /// <summary>The string stored in the parameter.</summary>
-                private readonly string _string; // null means an Int32 is stored
+                private readonly string? _string; // null means an Int32 is stored
 
                 /// <summary>Initializes the parameter with an integer value.</summary>
                 /// <param name="value">The value to be stored in the parameter.</param>
@@ -940,12 +941,12 @@ namespace System
 
                 /// <summary>Initializes the parameter with a string value.</summary>
                 /// <param name="value">The value to be stored in the parameter.</param>
-                public FormatParam(string value) : this(0, value ?? string.Empty) { }
+                public FormatParam(string? value) : this(0, value ?? string.Empty) { }
 
                 /// <summary>Initializes the parameter.</summary>
                 /// <param name="intValue">The integer value.</param>
                 /// <param name="stringValue">The string value.</param>
-                private FormatParam(int intValue, string stringValue)
+                private FormatParam(int intValue, string? stringValue)
                 {
                     _int32 = intValue;
                     _string = stringValue;
@@ -958,7 +959,7 @@ namespace System
                 }
 
                 /// <summary>Implicit converts a string into a parameter.</summary>
-                public static implicit operator FormatParam(string value)
+                public static implicit operator FormatParam(string? value)
                 {
                     return new FormatParam(value);
                 }