From b915b4026bf6a424be2f54584423423772668939 Mon Sep 17 00:00:00 2001 From: Maryam Ariyan Date: Tue, 17 Sep 2019 14:23:35 -0700 Subject: [PATCH 01/12] Nullability annotations for System.Console Contributes to: #40623 --- .../src/System/Text/OSEncoding.Windows.cs | 7 +-- src/System.Console/ref/System.Console.cs | 34 +++++------ src/System.Console/src/System.Console.csproj | 3 +- src/System.Console/src/System/Console.cs | 59 ++++++++++--------- .../src/System/ConsoleCancelEventArgs.cs | 2 +- .../src/System/ConsoleKeyInfo.cs | 2 +- .../src/System/IO/SyncTextReader.cs | 4 +- 7 files changed, 55 insertions(+), 56 deletions(-) diff --git a/src/Common/src/System/Text/OSEncoding.Windows.cs b/src/Common/src/System/Text/OSEncoding.Windows.cs index c7815f68bbf4..721681cbbbc2 100644 --- a/src/Common/src/System/Text/OSEncoding.Windows.cs +++ b/src/Common/src/System/Text/OSEncoding.Windows.cs @@ -11,11 +11,12 @@ namespace System.Text internal sealed class OSEncoding : Encoding { private readonly int _codePage; - private string _encodingName; + private readonly string _encodingName; internal OSEncoding(int codePage) : base(codePage) { _codePage = codePage; + _encodingName = "Codepage - " + _codePage.ToString(); } public override unsafe int GetByteCount(char[] chars, int index, int count) @@ -187,10 +188,6 @@ public override string EncodingName { get { - if (_encodingName == null) - { - _encodingName = "Codepage - " + _codePage.ToString(); - } return _encodingName; } } diff --git a/src/System.Console/ref/System.Console.cs b/src/System.Console/ref/System.Console.cs index ab32dcaf4da8..972155b0c6bc 100644 --- a/src/System.Console/ref/System.Console.cs +++ b/src/System.Console/ref/System.Console.cs @@ -51,7 +51,7 @@ public static void MoveBufferArea(int sourceLeft, int sourceTop, int sourceWidth 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 @@ public static void SetWindowPosition(int left, int top) { } 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 @@ public static void Write(ulong value) { } 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 @@ internal ConsoleCancelEventArgs() { } 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 @@ public readonly partial struct ConsoleKeyInfo 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; } diff --git a/src/System.Console/src/System.Console.csproj b/src/System.Console/src/System.Console.csproj index 37f552e45554..93bc6bb752b7 100644 --- a/src/System.Console/src/System.Console.csproj +++ b/src/System.Console/src/System.Console.csproj @@ -1,9 +1,10 @@ - + System.Console System.Console true netcoreapp-Unix-Debug;netcoreapp-Unix-Release;netcoreapp-Windows_NT-Debug;netcoreapp-Windows_NT-Release;uap-Windows_NT-Debug;uap-Windows_NT-Release + enable diff --git a/src/System.Console/src/System/Console.cs b/src/System.Console/src/System/Console.cs index 365f03ecff0c..6d0b03ad79d8 100644 --- a/src/System.Console/src/System/Console.cs +++ b/src/System.Console/src/System/Console.cs @@ -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 @@ public static class Console 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(ref T field, Func initializer) where T : class => + internal static T EnsureInitialized([NotNull] ref T? field, Func 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 @@ public static Encoding OutputEncoding // 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 @@ private static TextWriter CreateOutputWriter(Stream outputStream) }); } - private static StrongBox _isStdInRedirected; - private static StrongBox _isStdOutRedirected; - private static StrongBox _isStdErrRedirected; + private static StrongBox? _isStdInRedirected; + private static StrongBox? _isStdOutRedirected; + private static StrongBox? _isStdErrRedirected; public static bool IsInputRedirected { @@ -326,7 +327,7 @@ public static void SetCursorPosition(int left, int top) ConsolePal.SetCursorPosition(left, top); } - public static event ConsoleCancelEventHandler CancelKeyPress + public static event ConsoleCancelEventHandler CancelKeyPress // TODO: Ask for review { add { @@ -461,7 +462,7 @@ public static int Read() } [MethodImplAttribute(MethodImplOptions.NoInlining)] - public static string ReadLine() + public static string? ReadLine() { return In.ReadLine(); } @@ -485,7 +486,7 @@ public static void WriteLine(char value) } [MethodImplAttribute(MethodImplOptions.NoInlining)] - public static void WriteLine(char[] buffer) + public static void WriteLine(char[]? buffer) { Out.WriteLine(buffer); } @@ -541,37 +542,37 @@ public static void WriteLine(ulong value) } [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 @@ public static void WriteLine(string format, params object[] arg) } [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 @@ public static void Write(char value) } [MethodImplAttribute(MethodImplOptions.NoInlining)] - public static void Write(char[] buffer) + public static void Write(char[]? buffer) { Out.Write(buffer); } @@ -675,20 +676,20 @@ public static void Write(ulong value) } [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; diff --git a/src/System.Console/src/System/ConsoleCancelEventArgs.cs b/src/System.Console/src/System/ConsoleCancelEventArgs.cs index 763813672737..ac55456554fa 100644 --- a/src/System.Console/src/System/ConsoleCancelEventArgs.cs +++ b/src/System.Console/src/System/ConsoleCancelEventArgs.cs @@ -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 { diff --git a/src/System.Console/src/System/ConsoleKeyInfo.cs b/src/System.Console/src/System/ConsoleKeyInfo.cs index 1e40ff0dd95f..2ac7fe52ea26 100644 --- a/src/System.Console/src/System/ConsoleKeyInfo.cs +++ b/src/System.Console/src/System/ConsoleKeyInfo.cs @@ -47,7 +47,7 @@ public ConsoleModifiers Modifiers get { return _mods; } } - public override bool Equals(object value) + public override bool Equals(object? value) { return value is ConsoleKeyInfo && Equals((ConsoleKeyInfo)value); } diff --git a/src/System.Console/src/System/IO/SyncTextReader.cs b/src/System.Console/src/System/IO/SyncTextReader.cs index b2d53c44c98d..bc59b4038b72 100644 --- a/src/System.Console/src/System/IO/SyncTextReader.cs +++ b/src/System.Console/src/System/IO/SyncTextReader.cs @@ -70,7 +70,7 @@ public override int ReadBlock(char[] buffer, int index, int count) } } - public override string ReadLine() + public override string? ReadLine() { lock (this) { @@ -91,7 +91,7 @@ public override string ReadToEnd() // No explicit locking is needed, as they all just delegate // - public override Task ReadLineAsync() + public override Task ReadLineAsync() { return Task.FromResult(ReadLine()); } From a3827450abffd8b7aa8f1fbcf0949b85499e976e Mon Sep 17 00:00:00 2001 From: Maryam Ariyan Date: Tue, 17 Sep 2019 15:06:45 -0700 Subject: [PATCH 02/12] enable annotation on ref project --- src/System.Console/ref/System.Console.csproj | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/System.Console/ref/System.Console.csproj b/src/System.Console/ref/System.Console.csproj index 93ffdc8eb731..4a14acc08dd7 100644 --- a/src/System.Console/ref/System.Console.csproj +++ b/src/System.Console/ref/System.Console.csproj @@ -1,6 +1,7 @@ - + netcoreapp-Debug;netcoreapp-Release;uap-Debug;uap-Release + enable From 08a16485c4ae072985d1c77067aaa06907f4d145 Mon Sep 17 00:00:00 2001 From: Maryam Ariyan Date: Tue, 17 Sep 2019 15:12:35 -0700 Subject: [PATCH 03/12] For OSEncoding, make private field nullable and have it lazy initialized --- src/Common/src/System/Text/OSEncoding.Windows.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Common/src/System/Text/OSEncoding.Windows.cs b/src/Common/src/System/Text/OSEncoding.Windows.cs index 721681cbbbc2..e23db3ca1701 100644 --- a/src/Common/src/System/Text/OSEncoding.Windows.cs +++ b/src/Common/src/System/Text/OSEncoding.Windows.cs @@ -11,12 +11,11 @@ namespace System.Text internal sealed class OSEncoding : Encoding { private readonly int _codePage; - private readonly string _encodingName; + private string? _encodingName; internal OSEncoding(int codePage) : base(codePage) { _codePage = codePage; - _encodingName = "Codepage - " + _codePage.ToString(); } public override unsafe int GetByteCount(char[] chars, int index, int count) @@ -188,6 +187,10 @@ public override string EncodingName { get { + if (_encodingName == null) + { + _encodingName = "Codepage - " + _codePage.ToString(); + } return _encodingName; } } From e91b1a2d4ba69101f9933a7c5ab95affbe6d5efe Mon Sep 17 00:00:00 2001 From: Maryam Ariyan Date: Tue, 17 Sep 2019 15:23:40 -0700 Subject: [PATCH 04/12] Making event nullable --- src/System.Console/ref/System.Console.cs | 2 +- src/System.Console/src/System/Console.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/System.Console/ref/System.Console.cs b/src/System.Console/ref/System.Console.cs index 972155b0c6bc..ce7fdaa1e5cd 100644 --- a/src/System.Console/ref/System.Console.cs +++ b/src/System.Console/ref/System.Console.cs @@ -36,7 +36,7 @@ public static partial class Console 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() { } diff --git a/src/System.Console/src/System/Console.cs b/src/System.Console/src/System/Console.cs index 6d0b03ad79d8..b2e698648d94 100644 --- a/src/System.Console/src/System/Console.cs +++ b/src/System.Console/src/System/Console.cs @@ -327,7 +327,7 @@ public static void SetCursorPosition(int left, int top) ConsolePal.SetCursorPosition(left, top); } - public static event ConsoleCancelEventHandler CancelKeyPress // TODO: Ask for review + public static event ConsoleCancelEventHandler? CancelKeyPress { add { From 74895a41f7d45bff418f870517ed365b603606fb Mon Sep 17 00:00:00 2001 From: Maryam Ariyan Date: Tue, 17 Sep 2019 16:17:39 -0700 Subject: [PATCH 05/12] Enable nullable for OSEncoding.Windows.cs - Also used for System.Diagnostics.Process --- src/Common/src/System/Text/OSEncoding.Windows.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Common/src/System/Text/OSEncoding.Windows.cs b/src/Common/src/System/Text/OSEncoding.Windows.cs index e23db3ca1701..9107f461b452 100644 --- a/src/Common/src/System/Text/OSEncoding.Windows.cs +++ b/src/Common/src/System/Text/OSEncoding.Windows.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // 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; From b384e3c54839d711a7fdf5bf4e914e6fd071fbb3 Mon Sep 17 00:00:00 2001 From: Maryam Ariyan Date: Tue, 17 Sep 2019 16:34:15 -0700 Subject: [PATCH 06/12] nit fix --- src/Common/src/System/Text/OSEncoding.Windows.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Common/src/System/Text/OSEncoding.Windows.cs b/src/Common/src/System/Text/OSEncoding.Windows.cs index 9107f461b452..82ad53b1dcb6 100644 --- a/src/Common/src/System/Text/OSEncoding.Windows.cs +++ b/src/Common/src/System/Text/OSEncoding.Windows.cs @@ -1,8 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // 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 +#nullable enable using System; using System.Text; using System.Collections.Generic; From 73ec65c90ccb78fe034950795c9aaee1f8e7d94f Mon Sep 17 00:00:00 2001 From: Maryam Ariyan Date: Wed, 18 Sep 2019 12:38:07 -0700 Subject: [PATCH 07/12] Fixes on mac side --- .../src/System/Text/EncodingHelper.Unix.cs | 8 +-- .../src/System/Text/StringOrCharArray.cs | 10 +++- .../src/System/ConsolePal.Unix.cs | 51 +++++++++-------- .../src/System/IO/StdInReader.cs | 12 ++-- src/System.Console/src/System/TermInfo.cs | 57 ++++++++++--------- 5 files changed, 72 insertions(+), 66 deletions(-) diff --git a/src/Common/src/System/Text/EncodingHelper.Unix.cs b/src/Common/src/System/Text/EncodingHelper.Unix.cs index 0fb91e63f58a..111f1610bded 100644 --- a/src/Common/src/System/Text/EncodingHelper.Unix.cs +++ b/src/Common/src/System/Text/EncodingHelper.Unix.cs @@ -8,9 +8,9 @@ internal static partial class EncodingHelper { /// Creates an encoding from the current environment. /// The encoding, or null if it could not be determined. - 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 @@ internal static Encoding GetEncodingFromCharset() /// Gets the current charset name from the environment. /// The charset name if found; otherwise, null. - 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); diff --git a/src/Common/src/System/Text/StringOrCharArray.cs b/src/Common/src/System/Text/StringOrCharArray.cs index 2da29e3c9712..c6cd09bece33 100644 --- a/src/Common/src/System/Text/StringOrCharArray.cs +++ b/src/Common/src/System/Text/StringOrCharArray.cs @@ -14,9 +14,9 @@ namespace System.Text /// internal readonly struct StringOrCharArray : IEquatable { - 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 @@ public int Length } } - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is StringOrCharArray && @@ -71,12 +71,14 @@ public unsafe bool Equals(StringOrCharArray other) if (this.String != null) { // String vs String + Debug.Assert(String != null && other.String != null); if (other.String != null) { return StringComparer.Ordinal.Equals(this.String, other.String); } // String vs CharArray + Debug.Assert(String != null && other.CharArray != null); if (this.String.Length != other.CharArrayCount) return false; @@ -90,6 +92,7 @@ public unsafe bool Equals(StringOrCharArray other) } // CharArray vs CharArray + Debug.Assert(CharArray != null && other.CharArray != null); if (other.CharArray != null) { if (this.CharArrayCount != other.CharArrayCount) @@ -105,6 +108,7 @@ public unsafe bool Equals(StringOrCharArray other) } // CharArray vs String + Debug.Assert(CharArray != null && other.String != null); if (this.CharArrayCount != other.String.Length) return false; diff --git a/src/System.Console/src/System/ConsolePal.Unix.cs b/src/System.Console/src/System/ConsolePal.Unix.cs index 4e8204406d96..4718bdf0a6c4 100644 --- a/src/System.Console/src/System/ConsolePal.Unix.cs +++ b/src/System.Console/src/System/ConsolePal.Unix.cs @@ -67,7 +67,7 @@ public static Encoding OutputEncoding get { return GetConsoleEncoding(); } } - private static SyncTextReader s_stdInReader; + private static SyncTextReader? s_stdInReader; private static SyncTextReader StdInReader { @@ -200,7 +200,7 @@ public static string Title 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 @@ public static void SetCursorPosition(int left, int top) 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 @@ public static bool IsErrorRedirectedCore() /// The encoding. 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 @@ private static void WriteSetColorString(bool foreground, ConsoleColor color) } // 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 @@ private static void EnsureInitializedCore() // 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 @@ internal class TerminalFormatStrings private static readonly Lazy s_instance = new Lazy(() => new TerminalFormatStrings(TermInfo.Database.ReadActiveDatabase())); /// The format string to use to change the foreground color. - public readonly string Foreground; + public readonly string? Foreground; /// The format string to use to change the background color. - public readonly string Background; + public readonly string? Background; /// The format string to use to reset the foreground and background colors. - public readonly string Reset; + public readonly string? Reset; /// The maximum number of colors supported by the terminal. public readonly int MaxColors; /// The number of columns in a format. @@ -994,21 +994,21 @@ internal class TerminalFormatStrings /// The number of lines in a format. public readonly int Lines; /// The format string to use to make cursor visible. - public readonly string CursorVisible; + public readonly string? CursorVisible; /// The format string to use to make cursor invisible - public readonly string CursorInvisible; + public readonly string? CursorInvisible; /// The format string to use to set the window title. - public readonly string Title; + public readonly string? Title; /// The format string to use for an audible bell. - public readonly string Bell; + public readonly string? Bell; /// The format string to use to clear the terminal. - public readonly string Clear; + public readonly string? Clear; /// The format string to use to set the position of the cursor. - public readonly string CursorAddress; + public readonly string? CursorAddress; /// The format string to use to move the cursor to the left. - public readonly string CursorLeft; + public readonly string? CursorLeft; /// The format string to use to clear to the end of line. - public readonly string ClrEol; + public readonly string? ClrEol; /// The ANSI-compatible string for the Cursor Position report request. /// /// This should really be in user string 7 in the terminfo file, but some terminfo databases @@ -1028,9 +1028,9 @@ internal class TerminalFormatStrings /// Min key length public readonly int MinKeyFormatLength; /// The ANSI string used to enter "application" / "keypad transmit" mode. - 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 @@ public TerminalFormatStrings(TermInfo.Database db) 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 @@ private void AddKey(TermInfo.Database db, TermInfo.WellKnownStrings keyId, Conso 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 @@ private void AddPrefixKey(TermInfo.Database db, string extendedNamePrefix, Conso 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 @@ private static void InvalidateTerminalSettings() /// Writes a terminfo-based ANSI escape string to stdout. /// The string to write. /// Writing this value may change the cursor position. - 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 @@ private static void OnBreakEvent(Interop.Sys.CtrlCode ctrlCode) 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); diff --git a/src/System.Console/src/System/IO/StdInReader.cs b/src/System.Console/src/System/IO/StdInReader.cs index b323b86b5b11..f2a14c20631e 100644 --- a/src/System.Console/src/System/IO/StdInReader.cs +++ b/src/System.Console/src/System/IO/StdInReader.cs @@ -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 _tmpKeys = new Stack(); // temporary working stack; should be empty outside of ReadLine @@ -78,15 +78,15 @@ internal unsafe int ReadStdin(byte* buffer, int bufferSize) 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 @@ private string ReadLine(bool consumeKeys) { 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; } diff --git a/src/System.Console/src/System/TermInfo.cs b/src/System.Console/src/System/TermInfo.cs index 56bff4e1aa13..35a1cdd170fc 100644 --- a/src/System.Console/src/System/TermInfo.cs +++ b/src/System.Console/src/System/TermInfo.cs @@ -163,9 +163,9 @@ private Database(string term, byte[] data) /// Read the database for the current terminal as specified by the "TERM" environment variable. /// The database, or null if it could not be found. - 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 +183,20 @@ internal static Database ReadActiveDatabase() /// Read the database for the specified terminal. /// The identifier for the terminal. /// The database, or null if it could not be found. - 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 +219,7 @@ private static Database ReadDatabase(string term) /// The path to the file to open. /// If successful, the opened file descriptor; otherwise, -1. /// true if the file was successfully opened; otherwise, false. - private static bool TryOpen(string filePath, out SafeFileHandle fd) + private static bool TryOpen(string filePath, out SafeFileHandle? fd) { fd = Interop.Sys.Open(filePath, Interop.Sys.OpenFlags.O_RDONLY | Interop.Sys.OpenFlags.O_CLOEXEC, 0); if (fd.IsInvalid) @@ -236,20 +236,21 @@ private static bool TryOpen(string filePath, out SafeFileHandle fd) /// The identifier for the terminal. /// The path to the directory containing terminfo database files. /// The database, or null if it could not be found. - 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) { return null; } + Debug.Assert(fd != null); using (fd) { // Read in all of the terminfo data @@ -295,7 +296,7 @@ private static Database ReadDatabase(string term, string directoryPath) /// Gets a string from the strings section by the string's well-known index. /// The index of the string to find. /// The string if it's in the database; otherwise, null. - public string GetString(WellKnownStrings stringTableIndex) + public string? GetString(WellKnownStrings stringTableIndex) { int index = (int)stringTableIndex; Debug.Assert(index >= 0); @@ -321,11 +322,11 @@ public string GetString(WellKnownStrings stringTableIndex) /// Gets a string from the extended strings section. /// The name of the string as contained in the extended names section. /// The string if it's in the database; otherwise, null. - 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 @@ public int GetNumber(WellKnownNumbers numberIndex) /// defined as the earlier portions, and may not even exist, the parsing is more lenient about /// errors, returning an empty collection rather than throwing. /// - private static Dictionary ParseExtendedStrings(byte[] data, int extendedBeginning, bool readAs32Bit) + private static Dictionary? ParseExtendedStrings(byte[] data, int extendedBeginning, bool readAs32Bit) { const int ExtendedHeaderSize = 10; int sizeOfIntValuesInBytes = (readAs32Bit) ? 4 : 2; @@ -512,15 +513,15 @@ internal static class ParameterizedStrings { /// A cached stack to use to avoid allocating a new stack object for every evaluation. [ThreadStatic] - private static Stack t_cachedStack; + private static Stack? t_cachedStack; /// A cached array of arguments to use to avoid allocating a new array object for every evaluation. [ThreadStatic] - private static FormatParam[] t_cachedOneElementArgsArray; + private static FormatParam[]? t_cachedOneElementArgsArray; /// A cached array of arguments to use to avoid allocating a new array object for every evaluation. [ThreadStatic] - private static FormatParam[] t_cachedTwoElementArgsArray; + private static FormatParam[]? t_cachedTwoElementArgsArray; /// Evaluates a terminfo formatting string, using the supplied argument. /// The format string. @@ -528,7 +529,7 @@ internal static class ParameterizedStrings /// The formatted string. 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 @@ public static string Evaluate(string format, FormatParam arg) /// The formatted string. 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]; @@ -562,7 +563,7 @@ public static string Evaluate(string format, FormatParam arg1, FormatParam arg2) /// The format string. /// The arguments to the format string. /// The formatted string. - public static string Evaluate(string format, params FormatParam[] args) + public static string Evaluate(string? format, params FormatParam[]? args) { if (format == null) { @@ -574,7 +575,7 @@ public static string Evaluate(string format, params FormatParam[] args) } // Initialize the stack to use for processing. - Stack stack = t_cachedStack; + Stack? stack = t_cachedStack; if (stack == null) { t_cachedStack = stack = new Stack(); @@ -587,7 +588,7 @@ public static string Evaluate(string format, params FormatParam[] args) // "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 @@ public static string Evaluate(string format, params FormatParam[] args) /// private static string EvaluateInternal( string format, ref int pos, FormatParam[] args, Stack 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 @@ private static unsafe string FormatPrintF(string format, object arg) 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 @@ private static unsafe string FormatPrintF(string format, object arg) /// The index to use to index into the variables. /// The variables collection. 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 @@ public readonly struct FormatParam /// The integer stored in the parameter. private readonly int _int32; /// The string stored in the parameter. - private readonly string _string; // null means an Int32 is stored + private readonly string? _string; // null means an Int32 is stored /// Initializes the parameter with an integer value. /// The value to be stored in the parameter. @@ -940,12 +941,12 @@ public FormatParam(int value) : this(value, null) { } /// Initializes the parameter with a string value. /// The value to be stored in the parameter. - public FormatParam(string value) : this(0, value ?? string.Empty) { } + public FormatParam(string? value) : this(0, value ?? string.Empty) { } /// Initializes the parameter. /// The integer value. /// The string value. - private FormatParam(int intValue, string stringValue) + private FormatParam(int intValue, string? stringValue) { _int32 = intValue; _string = stringValue; @@ -958,7 +959,7 @@ public static implicit operator FormatParam(int value) } /// Implicit converts a string into a parameter. - public static implicit operator FormatParam(string value) + public static implicit operator FormatParam(string? value) { return new FormatParam(value); } From 20abf3b81a5a122e7dc9189218eaca0df91e657c Mon Sep 17 00:00:00 2001 From: Maryam Ariyan Date: Wed, 18 Sep 2019 14:38:46 -0700 Subject: [PATCH 08/12] Simplify asserts --- src/Common/src/System/Text/StringOrCharArray.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Common/src/System/Text/StringOrCharArray.cs b/src/Common/src/System/Text/StringOrCharArray.cs index c6cd09bece33..c9d54e29703f 100644 --- a/src/Common/src/System/Text/StringOrCharArray.cs +++ b/src/Common/src/System/Text/StringOrCharArray.cs @@ -71,14 +71,13 @@ public unsafe bool Equals(StringOrCharArray other) if (this.String != null) { // String vs String - Debug.Assert(String != null && other.String != null); if (other.String != null) { return StringComparer.Ordinal.Equals(this.String, other.String); } + Debug.Assert(other.CharArray != null); // String vs CharArray - Debug.Assert(String != null && other.CharArray != null); if (this.String.Length != other.CharArrayCount) return false; @@ -90,9 +89,9 @@ public unsafe bool Equals(StringOrCharArray other) return true; } + Debug.Assert(CharArray != null); // CharArray vs CharArray - Debug.Assert(CharArray != null && other.CharArray != null); if (other.CharArray != null) { if (this.CharArrayCount != other.CharArrayCount) @@ -106,9 +105,9 @@ public unsafe bool Equals(StringOrCharArray other) return true; } + Debug.Assert(other.String != null); // CharArray vs String - Debug.Assert(CharArray != null && other.String != null); if (this.CharArrayCount != other.String.Length) return false; From 3bb97b1ca2fe0ef1c9ddc40c6a73455a39d6e64b Mon Sep 17 00:00:00 2001 From: Maryam Ariyan Date: Wed, 18 Sep 2019 16:49:54 -0700 Subject: [PATCH 09/12] minor improvement. didnt need to be nullable --- src/System.Console/src/System/TermInfo.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/System.Console/src/System/TermInfo.cs b/src/System.Console/src/System/TermInfo.cs index 35a1cdd170fc..07fec5f27069 100644 --- a/src/System.Console/src/System/TermInfo.cs +++ b/src/System.Console/src/System/TermInfo.cs @@ -322,7 +322,7 @@ private static bool TryOpen(string filePath, out SafeFileHandle? fd) /// Gets a string from the extended strings section. /// The name of the string as contained in the extended names section. /// The string if it's in the database; otherwise, null. - public string? GetExtendedString(string? name) + public string? GetExtendedString(string name) { Debug.Assert(name != null); @@ -563,7 +563,7 @@ public static string Evaluate(string format, FormatParam arg1, FormatParam arg2) /// The format string. /// The arguments to the format string. /// The formatted string. - public static string Evaluate(string? format, params FormatParam[]? args) + public static string Evaluate(string format, params FormatParam[] args) { if (format == null) { From 60d9a30ff268adc3f76b411da6e4e6e0625a594d Mon Sep 17 00:00:00 2001 From: Maryam Ariyan Date: Wed, 18 Sep 2019 16:57:48 -0700 Subject: [PATCH 10/12] Add NotNullWhen for TryOpen --- src/System.Console/src/System/TermInfo.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/System.Console/src/System/TermInfo.cs b/src/System.Console/src/System/TermInfo.cs index 07fec5f27069..b35d8b5a947d 100644 --- a/src/System.Console/src/System/TermInfo.cs +++ b/src/System.Console/src/System/TermInfo.cs @@ -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; @@ -219,7 +220,7 @@ private Database(string term, byte[] data) /// The path to the file to open. /// If successful, the opened file descriptor; otherwise, -1. /// true if the file was successfully opened; otherwise, false. - 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) @@ -250,7 +251,6 @@ private static bool TryOpen(string filePath, out SafeFileHandle? fd) return null; } - Debug.Assert(fd != null); using (fd) { // Read in all of the terminfo data From fb4cd4bdf8e34639eb03202f885e91f39e516d99 Mon Sep 17 00:00:00 2001 From: Maryam Ariyan Date: Wed, 18 Sep 2019 17:28:06 -0700 Subject: [PATCH 11/12] remove remaining nullable enable --- src/Common/src/System/Text/OSEncoding.Windows.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Common/src/System/Text/OSEncoding.Windows.cs b/src/Common/src/System/Text/OSEncoding.Windows.cs index 82ad53b1dcb6..e23db3ca1701 100644 --- a/src/Common/src/System/Text/OSEncoding.Windows.cs +++ b/src/Common/src/System/Text/OSEncoding.Windows.cs @@ -2,7 +2,6 @@ // 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; From 1afa4c8028006b7d1c25420ed66ab679028cc047 Mon Sep 17 00:00:00 2001 From: Maryam Ariyan Date: Wed, 18 Sep 2019 17:29:58 -0700 Subject: [PATCH 12/12] Revert "remove remaining nullable enable" This reverts commit fb4cd4bdf8e34639eb03202f885e91f39e516d99. --- src/Common/src/System/Text/OSEncoding.Windows.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Common/src/System/Text/OSEncoding.Windows.cs b/src/Common/src/System/Text/OSEncoding.Windows.cs index e23db3ca1701..82ad53b1dcb6 100644 --- a/src/Common/src/System/Text/OSEncoding.Windows.cs +++ b/src/Common/src/System/Text/OSEncoding.Windows.cs @@ -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;